给你的网站加上站内搜索---Spring+Hibernate基于Compass(基于Lucene)实现

news/2024/5/12 13:28:31/文章来源:https://blog.csdn.net/Dracotianlong/article/details/7955048

给你的网站加上站内搜索---Compass入门教程

syxChina(syxchina.cnblogs.com)

Compass(基于Lucene)入门教程

1 序言

2 Compass介绍

3 单独使用Compass

4 spring+hibernate继承compass

4-1 jar包

4-2 配置文件

4-3 源代码

4-4 说明

4-5 测试

5 总结下吧

1 序言

这些天一直在学点新的东西,想给毕业设计添加点含量,长时间的SSH项目也想尝试下新的东西和完善以前的技术,搜索毋容置疑是很重要的。作为javaer,作为apache的顶级开源项目lucene应该有所耳闻吧,刚学完lucene,知道了基本使用,学的程度应该到可以使用的地步,但不的不说lucene官方给的文档例子不是很给力的,还好互联网上资料比较丰富!在搜索lucene的过程中,知道了基于lucene的compass和lucene-nutch。lucene可以对给定内容加上索引搜索,但比如搜索本地数据库和web网页,你需要把数据给拿出来索引再搜索,所以你就想可不可以直接搜索数据库,以数据库内容作为索引,并且伴随着数据库的CRUD,索引也会更新,compass出现了,compass作为站内搜索那是相当的方便的,并且官方提供了spring和hibernate的支持,更是方便了。Lucene-nutch是基于lucene搜索web页面的,如果有必要我在分享下lucene、lecene-nutch的学习经验,快速入门,其他的可以交给文档和谷歌了。

不得不提下,compass09年貌似就不更新了,网上说只支持lucene3.0以下版本,蛮好的项目不知道为什么不更新了,试了下3.0以后的分词器是不能使用了,我中文使用JE-Analyzer.jar。我使用的环境:

Spring3.1.0+Hibernate3.6.6+Compass2.2.0。

2 Compass介绍

Compass是一个强大的,事务的,高性能的对象/搜索引擎映射(OSEM:object/search engine mapping)与一个Java持久层框架.Compass包括: 

* 搜索引擎抽象层(使用Lucene搜索引荐),

* OSEM (Object/Search Engine Mapping) 支持,

* 事务管理,

* 类似于Google的简单关键字查询语言,

* 可扩展与模块化的框架,

* 简单的API.

官方网站:谷歌

3 单独使用Compass

Compass可以不继承到hibernate和spring中的,这个是从网上摘录的,直接上代码:

wps_clip_image-6849wps_clip_image-20611wps_clip_image-27320

@Searchable

publicclass Book {

private String id;//编号

private String title;//标题

private String author;//作者

privatefloatprice;//价格

public Book() {

}

public Book(String id, String title, String author, float price) {

super();

this.id = id;

this.title = title;

this.author = author;

this.price = price;

}

@SearchableId

public String getId() {

returnid;

}

@SearchableProperty(boost = 2.0F, index = Index.TOKENIZED, store = Store.YES)

public String getTitle() {

returntitle;

}

@SearchableProperty(index = Index.TOKENIZED, store = Store.YES)

public String getAuthor() {

returnauthor;

}

@SearchableProperty(index = Index.NO, store = Store.YES)

publicfloat getPrice() {

returnprice;

}

publicvoid setId(String id) {

this.id = id;

}

publicvoid setTitle(String title) {

this.title = title;

}

publicvoid setAuthor(String author) {

this.author = author;

}

publicvoid setPrice(float price) {

this.price = price;

}

@Override

public String toString() {

return"[" + id + "] " + title + " - " + author + " $ " + price;

}

}

publicclass Searcher {

protected Compass compass;

public Searcher() {

}

public Searcher(String path) {

compass = new CompassAnnotationsConfiguration()//

.setConnection(path).addClass(Book.class)//

.setSetting("compass.engine.highlighter.default.formatter.simple.pre", "<font color='red'>")//

.setSetting("compass.engine.highlighter.default.formatter.simple.post", "</font>")//

.buildCompass();//

Runtime.getRuntime().addShutdownHook(new Thread() {

publicvoid run() {

compass.close();

}

});

}

/**

* 新建索引

* @param book

*/

publicvoid index(Book book) {

CompassSession session = null;

CompassTransaction tx = null;

try {

session = compass.openSession();

tx = session.beginTransaction();

session.create(book);

tx.commit();

} catch (RuntimeException e) {

if (tx != null)

tx.rollback();

throw e;

} finally {

if (session != null) {

session.close();

}

}

}

/**

* 删除索引

* @param book

*/

publicvoid unIndex(Book book) {

CompassSession session = null;

CompassTransaction tx = null;

try {

session = compass.openSession();

tx = session.beginTransaction();

session.delete(book);

tx.commit();

} catch (RuntimeException e) {

tx.rollback();

throw e;

} finally {

if (session != null) {

session.close();

}

}

}

/**

* 重建索引

* @param book

*/

publicvoid reIndex(Book book) {

unIndex(book);

index(book);

}

/**

* 搜索

* @param queryString

* @return

*/

public List<Book> search(String queryString) {

CompassSession session = null;

CompassTransaction tx = null;

try {

session = compass.openSession();

tx = session.beginTransaction();

CompassHits hits = session.find(queryString);

int n = hits.length();

if (0 == n) {

return Collections.emptyList();

}

List<Book> books = new ArrayList<Book>();

for (int i = 0; i < n; i++) {

books.add((Book) hits.data(i));

}

hits.close();

tx.commit();

return books;

} catch (RuntimeException e) {

tx.rollback();

throw e;

} finally {

if (session != null) {

session.close();

}

}

}

publicclass Main {

static List<Book> db = new ArrayList<Book>();

static Searcher searcher = new Searcher("index");

publicstaticvoid main(String[] args) {

add(new Book(UUID.randomUUID().toString(), "Thinking in Java", "Bruce", 109.0f));

add(new Book(UUID.randomUUID().toString(), "Effective Java", "Joshua", 12.4f));

add(new Book(UUID.randomUUID().toString(), "Java Thread Programing", "Paul", 25.8f));

long begin = System.currentTimeMillis();

int count = 30;

for(int i=1; i<count; i++) {

if(i%10 == 0) {

long end = System.currentTimeMillis();

System.err.println(String.format("当时[%d]条,剩[%d]条,已用时间[%ds],估计时间[%ds].", i,count-i,(end-begin)/1000, (int)((count-i)*((end-begin)/(i*1000.0))) ));

}

String uuid = new Date().toString();

add(new Book(uuid, uuid.substring(0, uuid.length()/2), uuid.substring(uuid.length()/2), (float)Math.random()*100));

}

int n;

do {

n = displaySelection();

switch (n) {

case 1:

listBooks();

break;

case 2:

addBook();

break;

case 3:

deleteBook();

break;

case 4:

searchBook();

break;

case 5:

return;

}

} while (n != 0);

}

staticint displaySelection() {

System.out.println("\n==select==");

System.out.println("1. List all books");

System.out.println("2. Add book");

System.out.println("3. Delete book");

System.out.println("4. Search book");

System.out.println("5. Exit");

int n = readKey();

if (n >= 1 && n <= 5)

return n;

return 0;

}

/**

* 增加一本书到数据库和索引中

*

* @param book

*/

privatestaticvoid add(Book book) {

db.add(book);

searcher.index(book);

}

/**

* 打印出数据库中的所有书籍列表

*/

publicstaticvoid listBooks() {

System.out.println("==Database==");

int n = 1;

for (Book book : db) {

System.out.println(n + ")" + book);

n++;

}

}

/**

* 根据用户录入,增加一本书到数据库和索引中

*/

publicstaticvoid addBook() {

String title = readLine(" Title: ");

String author = readLine(" Author: ");

String price = readLine(" Price: ");

Book book = new Book(UUID.randomUUID().toString(), title, author, Float.valueOf(price));

add(book);

}

/**

* 删除一本书,同时删除数据库,索引库中的

*/

publicstaticvoid deleteBook() {

listBooks();

System.out.println("Book index: ");

int n = readKey();

Book book = db.remove(n - 1);

searcher.unIndex(book);

}

/**

* 根据输入的关键字搜索书籍

*/

publicstaticvoid searchBook() {

String queryString = readLine(" Enter keyword: ");

List<Book> books = searcher.search(queryString);

System.out.println(" ====search results:" + books.size() + "====");

for (Book book : books) {

System.out.println(book);

}

}

publicstaticint readKey() {

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

try {

int n = reader.read();

n = Integer.parseInt(Character.toString((char) n));

return n;

} catch (Exception e) {

thrownew RuntimeException();

}

}

publicstaticString readLine(String propt) {

System.out.println(propt);

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

try {

return reader.readLine();

} catch (Exception e) {

thrownew RuntimeException();

}

}

}

wps_clip_image-5530

这种方法向数据库插入数据和加索引速度很慢,下面方法可以提高,注意这上面没设置分词器,所以使用默认的,如果是中文的话会分隔为一个一个的。

4 spring+hibernate继承compass

4-1 jar包

wps_clip_image-25759wps_clip_image-5116wps_clip_image-20051wps_clip_image-11513wps_clip_image-29500wps_clip_image-6212

4-2 配置文件

wps_clip_image-9831

Beans.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"

xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/beans

         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

         http://www.springframework.org/schema/context

         http://www.springframework.org/schema/context/spring-context-3.0.xsd

         http://www.springframework.org/schema/tx

      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

         http://www.springframework.org/schema/aop

         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<context:annotation-config/>

<context:component-scanbase-package="com.syx.compass"></context:component-scan>

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

<importresource="hibernate-beans.xml"/>

<importresource="compass-beans.xml"/>

</beans>

compass-beans.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="...">

<!--compass主配置 -->

<beanid="compass"class="org.compass.spring.LocalCompassBean">

<propertyname="compassSettings">

<props>

<propkey="compass.engine.connection">file://compass</prop><!-- 数据索引存储位置 -->

<propkey="compass.transaction.factory">

org.compass.spring.transaction.SpringSyncTransactionFactory</prop>

<propkey="compass.engine.analyzer.default.type">

jeasy.analysis.MMAnalyzer</prop><!--定义分词器-->

<propkey="compass.engine.highlighter.default.formatter.simple.pre">

<![CDATA[<font color="red"><b>]]></prop>

<propkey="compass.engine.highlighter.default.formatter.simple.post">

<![CDATA[</b></font>]]></prop>

</props>

</property>

<propertyname="transactionManager">

<refbean="txManager"/>

</property>

<propertyname="compassConfiguration" ref="annotationConfiguration"/>

<propertyname="classMappings">

<list>

<value>com.syx.compass.test1.Article</value>

</list>

</property>

</bean>

<beanid="annotationConfiguration"

class="org.compass.annotations.config.CompassAnnotationsConfiguration">

</bean>

<beanid="compassTemplate"class="org.compass.core.CompassTemplate">

<propertyname="compass"ref="compass"/>

</bean>

<!-- 同步更新索引, 数据库中的数据变化后同步更新索引 -->

<beanid="hibernateGps"class="org.compass.gps.impl.SingleCompassGps"

init-method="start"destroy-method="stop">

<propertyname="compass">

<refbean="compass"/>

</property>

<propertyname="gpsDevices">

<list>

<refbean="hibernateGpsDevice"/>

</list>

</property>

</bean>

<!--hibernate驱动 链接compass和hibernate -->

<beanid="hibernateGpsDevice"

class="org.compass.spring.device.hibernate.dep.SpringHibernate3GpsDevice">

<propertyname="name">

<value>hibernateDevice</value>

</property>

<propertyname="sessionFactory">

<refbean="sessionFactory"/>

</property>

<propertyname="mirrorDataChanges">

<value>true</value>

</property>

</bean>

<!-- 定时重建索引(利用quartz)或随Spring ApplicationContext启动而重建索引 -->

<beanid="compassIndexBuilder"

class="com.syx.compass.test1.CompassIndexBuilder"

lazy-init="false">

<propertyname="compassGps"ref="hibernateGps"/>

<propertyname="buildIndex"value="false"/>

<propertyname="lazyTime"value="1"/>

</bean>

<!-- 搜索引擎服务类 -->

<beanid="searchService"class=" com.syx.compass.test1.SearchServiceBean">

<propertyname="compassTemplate">

<refbean="compassTemplate"/>

</property>

</bean>

</beans>

hibernate-beans.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="...">

<!-- DataSource -->

<beanid="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource">

<propertyname="driverClass"value="${jdbc.driverClassName}"/>

<propertyname="jdbcUrl"value="${jdbc.url}"/>

<propertyname="user"value="${jdbc.username}"/>

<propertyname="password"value="${jdbc.password}"/>

<propertyname="autoCommitOnClose"value="true"/>

<propertyname="checkoutTimeout"value="${cpool.checkoutTimeout}"/>

<propertyname="initialPoolSize"value="${cpool.minPoolSize}"/>

<propertyname="minPoolSize"value="${cpool.minPoolSize}"/>

<propertyname="maxPoolSize"value="${cpool.maxPoolSize}"/>

<propertyname="maxIdleTime"value="${cpool.maxIdleTime}"/>

<propertyname="acquireIncrement"value="${cpool.acquireIncrement}"/>

<!-- <property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}"/> -->

</bean>

<bean

class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<propertyname="locations">

<value>classpath:jdbc.properties</value>

</property>

</bean>

<!-- SessionFacotory -->

<beanid="sessionFactory"

class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

<propertyname="dataSource"ref="dataSource"/>

<propertyname="annotatedClasses">

<list>

<value>com.syx.compass.model.Article</value>

<value>com.syx.compass.model.Author</value>

<value>com.syx.compass.test1.Article</value>

</list>

</property>

<propertyname="hibernateProperties">

<props>

<propkey="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

<propkey="hibernate.current_session_context_class">thread</prop>

<propkey="javax.persistence.validation.mode">none</prop>

<propkey="hibernate.show_sql">true</prop>

<propkey="hibernate.format_sql">false</prop>

<propkey="hibernate.hbm2ddl.auto">update</prop>

</props>

</property>

</bean>

<beanid="hibernateTemplate"class="org.springframework.orm.hibernate3.HibernateTemplate">

<propertyname="sessionFactory"ref="sessionFactory"></property>

</bean>

<beanid="txManager"

class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<propertyname="sessionFactory"ref="sessionFactory"/>

</bean>

</beans>

jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver

jdbc.hostname=localhost

jdbc.url=jdbc:mysql://localhost:3306/compass

jdbc.username=root

jdbc.password=root

cpool.checkoutTimeout=5000

cpool.minPoolSize=1

cpool.maxPoolSize=4

cpool.maxIdleTime=25200

cpool.maxIdleTimeExcessConnections=1800

cpool.acquireIncrement=5

log4j.properties

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.Target=System.out

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.rootLogger=error, stdout

4-3 源代码

wps_clip_image-5691

@Searchable(alias = "article")

@Entity(name="_article")

publicclass Article {

private Long ID; // 标识ID

private String content; // 正文

private String title; // 文章标题

private Date createTime; // 创建时间

public Article(){}

public Article(Long iD, String content, String title, Date createTime) {

ID = iD;

this.content = content;

this.title = title;

this.createTime = createTime;

}

public String toString() {

return String.format("%d,%s,%s,%s", ID, title, content, createTime.toString());

}

@SearchableId

@Id

@GeneratedValue

public Long getID() {

returnID;

}

publicvoid setID(Long id) {

ID = id;

}

@SearchableProperty(index = Index.TOKENIZED, store = Store.YES)

public String getContent() {

returncontent;

}

publicvoid setContent(String content) {

this.content = content;

}

@SearchableProperty(index = Index.TOKENIZED, store = Store.YES)

public String getTitle() {

returntitle;

}

publicvoid setTitle(String title) {

this.title = title;

}

@SearchableProperty(index = Index.TOKENIZED, store = Store.YES)

public Date getCreateTime() {

returncreateTime;

}

publicvoid setCreateTime(Date createTime) {

this.createTime = createTime;

}

}

publicclass CompassIndexBuilder implements InitializingBean {   

// 是否需要建立索引,可被设置为false使本Builder失效.    

privatebooleanbuildIndex = false;    

// 索引操作线程延时启动的时间,单位为秒    

privateintlazyTime = 10;    

// Compass封装    

private CompassGps compassGps;    

// 索引线程    

private Thread indexThread = new Thread() {    

@Override

publicvoid run() {    

try {    

                Thread.sleep(lazyTime * 1000);    

                System.out.println("begin compass index...");    

long beginTime = System.currentTimeMillis();    

// 重建索引.    

// 如果compass实体中定义的索引文件已存在,索引过程中会建立临时索引,    

// 索引完成后再进行覆盖.    

compassGps.index();    

long costTime = System.currentTimeMillis() - beginTime;    

                System.out.println("compss index finished.");    

                System.out.println("costed " + costTime + " milliseconds");    

            } catch (InterruptedException e) {    

                e.printStackTrace();    

            }    

        }    

    };    

/**  

     * 实现<code>InitializingBean</code>接口,在完成注入后调用启动索引线程.

     */

publicvoid afterPropertiesSet() throws Exception {    

if (buildIndex) {    

indexThread.setDaemon(true);    

indexThread.setName("Compass Indexer");    

indexThread.start();    

        }    

    }    

publicvoid setBuildIndex(boolean buildIndex) {    

this.buildIndex = buildIndex;    

    }    

publicvoid setLazyTime(int lazyTime) {    

this.lazyTime = lazyTime;    

    }    

publicvoid setCompassGps(CompassGps compassGps) {    

this.compassGps = compassGps;    

    }    

}  

publicclass SearchServiceBean {

private CompassTemplate compassTemplate;

/** 索引查询 * */

publicMap find(final String keywords, final String type, finalint start, finalint end) {

returncompassTemplate.execute(new CompassCallback<Map>() {

publicMap doInCompass(CompassSession session) throws CompassException {

List result = newArrayList();

int totalSize = 0;

Map container = newHashMap();

CompassQuery query = session.queryBuilder().queryString(keywords).toQuery();

CompassHits hits = query.setAliases(type).hits();

totalSize = hits.length();

container.put("size", totalSize);

int max = 0;

if (end < hits.length()) {

max = end;

} else {

max = hits.length();

}

if (type.equals("article")) {

for (int i = start; i < max; i++) {

Article article = (Article) hits.data(i);

String title = hits.highlighter(i).fragment("title");

if (title != null) {

article.setTitle(title);

}

String content = hits.highlighter(i).setTextTokenizer(CompassHighlighter.TextTokenizer.AUTO).fragment("content");

if (content != null) {

article.setContent(content);

}

result.add(article);

}

}

container.put("result", result);

return container;

}

});

}

public CompassTemplate getCompassTemplate() {

returncompassTemplate;

}

publicvoid setCompassTemplate(CompassTemplate compassTemplate) {

this.compassTemplate = compassTemplate;

}

}

publicclass MainTest {

publicstatic ClassPathXmlApplicationContext applicationContext;

privatestatic HibernateTemplate hibernateTemplate;

@BeforeClass

publicstaticvoid init() {

System.out.println("sprint init...");

applicationContext = new ClassPathXmlApplicationContext("beans.xml");

hibernateTemplate = applicationContext.getBean(HibernateTemplate.class);

System.out.println("sprint ok");

}

@Test

publicvoid addData() {

System.out.println("addDate");

//把compass-beans.xml 中 bean id="compassIndexBuilder"

//buildIndex=true lazyTime=1

//会自动的根据数据库中的数据重新建立索引

try {

Thread.sleep(10000000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

@Test

publicvoid search() {

String keyword = "全文搜索引擎";

SearchServiceBean ssb = applicationContext.getBean(SearchServiceBean.class);

Map map = ssb.find(keyword, "article", 0, 100);//第一次搜索加载词库

long begin = System.currentTimeMillis();

map = ssb.find(keyword, "article", 0, 100);//第二次才是搜索用时

long end = System.currentTimeMillis();

System.out.println(String.format(

"搜索:[%s],耗时(ms):%d,记录数:%d", keyword, end-begin, map.get("size")));

List<Article> list = (List<Article>) map.get("result");

for(Article article : list) {

System.out.println(article);

}

}

4-4 说明

compass-beans.xml中可以设置建立索引的目录和分词器,测试的时候我们使用数据库添加数据,启动的建立索引,测试速度。

4-5 测试

使用mysql,写了一个添加数据的函数:

DELIMITER $$

CREATE

    FUNCTION `compass`.`addDateSyx`(num int(8))

    RETURNS varchar(32)

    BEGIN

declare i int(8);

set i = 0;

while ( i < num) DO

insert into _article (title,content, createTime) values (i, num-i, now());

set i = i + 1;

end while;

return "OK";

    END$$

DELIMITER ;

4-5-1 10000条重复的中文数据测试

数据库函数的时候修改下insert:

insert into _article (title,content, createTime) values ('用compass实现站内全文搜索引擎(一)', 'Compass是一个强大的,事务的,高性能的对象/搜索引擎映射(OSEM:object/search engine mapping)与一个Java持久层框架.Compass包括: 

* 搜索引擎抽象层(使用Lucene搜索引荐),

* OSEM (Object/Search Engine Mapping) 支持,

* 事务管理,

* 类似于Google的简单关键字查询语言,

* 可扩展与模块化的框架,

* 简单的API.

如果你需要做站内搜索引擎,而且项目里用到了hibernate,那用compass是你的最佳选择。 ', now());

插入数据:

select addDateSyx1(10000);//hibernate 中的 hibernate.hbm2ddl.auto=update

wps_clip_image-569wps_clip_image-11587

建立索引:

wps_clip_image-15051

wps_clip_image-4911

wps_clip_image-16445

10000条,8045ms,速度还不错。

索引大小:

wps_clip_image-10964

搜索:

wps_clip_image-6267

的确分词了,如果使用默认的分词,中文会每个中文分一个,速度比较快,如果使用JE-Anaylzer 116ms也是可以接受的。

4-5-2 10w条重复的中文数据测试

插入数据:

wps_clip_image-32560

Mysql 10w大约12s左右。

建立索引:

wps_clip_image-21575

wps_clip_image-12492索引大小和我想象的差不多,就是时间比我像的长多了,但我不想在试了。

搜索:

wps_clip_image-24973

10w的是数据,243ms还是很不错的,看来只要索引建好,搜索还是很方便的。

5 总结下吧

Compass用起来还是挺顺手的,应该基本需求可以满足的,不知道蛮好的项目怎么就不更新了,不然hibernate search就不会有的。

因为compass的不更新,所以lucene3.0以后的特性就不能用了,蛮可以的,虽然compass可以自动建索引(当然也可以手动CRUD),但如果封装下lucene来完成compass应该可以得到比较好的实现,期待同学们出手了。

参考文章:

compass实现站内全文搜索引擎(一)

再谈compass:集成站内搜索

compass快速给你的网站添加搜索功能

ITEYE上一篇也不错,不小心页面关了...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_903173.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

提高网站打开速度的7大秘籍 http://lusongsong.com/reed/360.html

很多站长使用虚拟主机来做网站&#xff0c;网页内容一旦很多&#xff0c;网站打开速度就会特别慢&#xff0c;如果说服务器、带宽、CDN这类硬指标我们没有经济实力去做&#xff0c;不妨通过网页代码优化的方式来提高速度&#xff0c;卢松松总结了一些可行性的方法。 1: 缩小Jav…

搭建 ngrok 服务实现外网访问局域网内的网站

本文转自 http://www.itjiaoshou.com/ngrok-access-website-in-lan.html 一般情况下&#xff0c;家庭用户使用的电信宽带服务是没有固定 IP 的&#xff0c;某些企业客户即使给分配了一个固定 IP 也不允许对外暴露 80 端口&#xff08;要是每个公司内部就能提供 web 服务&#x…

从前端出发做好SEO需要考虑什么

一、背景介绍 什么是SEO&#xff1f; SEO由英文Search Engine Optimization缩写而来&#xff0c;中文意译为“搜索引擎优化”。 其实叫做针对搜索引擎优化更容易理解。它是指从自然搜索结果获得网站流量的技术和过程&#xff0c;是在了解搜索引擎自然排名机制的基 础上&…

码云GitHub新建仓库repositories,github建立自己的网站

github和国内的码云的新建大同小异。 话不多说 网址 github的地址 首先创建自己的账户 需要密码复杂一些 邮箱验证 验证成功后 右上角点击 new repository 第一个箭头处 填跟自己用户一样的名字.github.io 如 xxx.github.io 之后public private 都行 我选的是public…

阿里云ECS服务器搭建静态网站

首先如下图购买阿里云的云翼计划的学生机&#xff0c;选择云服务器ECS&#xff0c;预装环境选择CentOS。网址为https://promotion.aliyun.com/ntms/act/campus2018.html。 注意设置root用户的登陆密码&#xff0c;需要记录&#xff0c;等下会用到。 还需要记录远程连接密码。 …

用Dreamweaver实现网站批量更新

在Dreamweaver 4.0中&#xff0c;我们就已接触了模板与库的概念&#xff0c;知道它们是批量生成风格类似的网页的好工具。如今在Dreamweaver MX(以下简称DW MX)中&#xff0c;模板与库的功能得到了进一步细化与加强&#xff0c;尤其是实现关联网页自动更新的特点&#xff0c;使…

50毫秒就判断网站设计好坏

【摘 要】加拿大渥太华卡尔顿大学的研究人员发现&#xff0c;人的大脑将在首次看到一个网页后的二十分之一秒的时间内判断其质量 1月17日消息&#xff0c;据一项新的研究显示&#xff0c;浏览互联网的用户通常会在极短的时间内判断一个网站的质量。 加拿大渥太华卡尔顿大学的…

探讨国外网站设计动用的成本,网页设计师必看

【摘 要】我们都承认国外的网站设计价格高&#xff0c;同样一个看似简单的网站价格是国内几倍或者数倍。通过此文&#xff0c;希望国内的网站设计师同行稍稍静下心来&#xff0c;不要浮躁... 同样是一个网站设计&#xff0c;国外的设计却蕴涵了设计背后的更多东西&#xff0c…

网站设计理念 形成视觉冲击的几种方式

【摘 要】构图&#xff0c;从广义上讲&#xff0c;是指形象或符号对空间占有的状况。 因此理应包括一切立体和平面的造型&#xff0c;但立体的造型由于视角的可变&#xff0c;使其空间占有状况如果用固定的方法阐述&#xff0c;就显得不够全面 1&#xff1a;构图图形的层次感…

Windows以及Chrome浏览器的一些使用技巧,快捷键,盲打练习网站分享

文章目录 Windows使用技巧Chrome使用技巧关于盲打 Windows使用技巧 用户目录以及桌面等文件夹的移动 用户目录在C盘-用户文件夹 然后可以找到我们自己命名过的文件夹&#xff0c;默认是administer&#xff0c;里面有桌面、下载、文档之类的文件夹&#xff0c;桌面就是我们的电脑…

优化网站性能 提高网站速度访问速度的14条实践

关键字: 优化网站性能 提高网站速度访问速度的14条实践 相信互联网已经越来越成为人们生活中不可或缺的一部分。ajax&#xff0c;flex等等富客户端的应用使得人们越加“幸福”地体验着许多原先只能在C/S实现的功能。比如Google机会已经把最基本的office应用都搬到了互联网上。当…

数据结构可视化网站https://visualgo.net/zh如何注册

数据结构可视化网站https://visualgo.net/zh qq邮箱注册的时候要去掉确认链接后的点。M后面的点要去掉。

[源码和文档分享]基于JavaScript和MySQL的文化平台网站的设计与实现

摘要 中国文化源远流长&#xff0c;自古就有文人雅士作诗赋词&#xff0c;舞文弄墨&#xff0c;尽显风雅。现今则有歌手作家思想成文&#xff0c;心绪为曲&#xff0c;亦现儒雅。文化是传承的&#xff0c;是流传不息的&#xff0c;也是众多人所追求的。从各种各样的文化中&…

[源码和文档分享]基于C#和SQL SERVER的校园知识问答论坛网站的设计与实现

摘 要 本文使用Asp.Net Core 和MsSqlServer技术&#xff0c;详细说明开发校园知识论坛系统的开发。校园知识论坛系统是基本B/S模式的一种交互性极强的电子信息服务系统。它为使用者提供一个交流的平台&#xff0c;每一个用户都可以在上面问答知识&#xff0c;获取信息&#xf…

[源码和文档分享]基于Node.js中间层的微信图书借阅平台网站的设计与实现

1 引言 步入信息时代以来&#xff0c;互联网给人们的生活带来了翻天覆地的变化&#xff0c;互联网也不再简单地仅仅通过提供便利快捷的资讯服务来丰富我们的生活。互联网的出现打破了许多传统行业垄断的格局&#xff0c;互联网以其接入面广、信息即使、人人可参与等等性质&…

基于Keras和tensorflow深度学习Python实现的支持人脸识别和情绪分类的社区APP网站和微信小程序...

1 项目介绍 1.1 背景 视觉使人类得以感知和理解周边的世界&#xff0c;人的大脑皮层大约有 70%的活动在处理 视觉相关信息。计算机视觉即通过电子化的方式来感知和理解影像&#xff0c;以达到甚至超 越人类视觉智能的效果。 从 1966 年学科建立&#xff08;MIT&#xff1a;TheS…

基于php与sqlite数据库的运动社交网站

一、总体设计 1.1 开发环境 本系统采用php作为主要开发语言&#xff0c;服务端主要使用php&#xff0b;sqliteApache&#xff0c;客户端使用htmlcssjs。用Apache作为服务器&#xff0c;采用sqlite作为后台数据管理系统。 开发环境&#xff1a;Windows 10 开发工具&#xff1a;p…

[源码和文档分享]基于C#实现的电影网站数据爬虫和电影网站

1 简介 1.1 背景 随着网络的发展&#xff0c;网购也越来越流行&#xff0c;人们可以在去各大电影院的网站方便的购票并选择自己喜欢的时间去影院观看。但电影院网站众多&#xff0c;人们可能为了寻找一个电影而奔波与各大网站&#xff0c;导致浪费大量时间在寻找电影资源上。本…

[源码和文档分享]基于JAVA FX实现的酒店预订系统网站

1 产品概述 参考酒店预订系统用例文档和酒店预订系统软件需求规格说明文档中队产品的概括描述。酒店预订系统主要是应用于网上预定远程酒店订单的在线系统&#xff0c;主要功能见用例图如下。 源码下载地址&#xff1a;https://www.write-bug.com/article/1441.html