使用SSM+Solr优雅的实现电商项目中的搜索功能

SSM+Redis+Shiro+Solr+Vue.js整合项目 手摸手教你优雅的实现电商项目中的Solr搜索功能,整合SSM框架和Shiro安全框架;教你用Vue.JS和ElementUI写出超漂亮的页面 技术栈 后端: SSM + Shiro + Redis + Solr 前端: Vue.JS + ElementUI 测试环境 IDEA + Maven + Tomcat8 项目设计 ssm-redis-solr ├── READ... 阅读详情

在学习了Redis&Spring-Data-Redis入门和Solr&Spring-Data-Solr入门后,接下来就该是项目实战了。这次我们用Vue.JS和ElementUI写前端页面,优雅的整合SSM-Shiro-Redis-Solr框架。

手摸手教你优雅的实现电商项目中的Solr搜索功能,整合SSM框架和Shiro安全框架;教你用Vue.JS和ElementUI写出超漂亮的页面

项目开源地址:SSM整合Solr实现电商项目中的搜索功能


准备

Shiro

关于Shiro,我这里写了详细的SSM框架整合Shiro安全框架的文档,利用SSM框架+Shiro框架实现用户-角色-权限管理系统;

详细的文档地址:SSM整合Shiro框架后的开发

项目Github源码地址:SSM整合Shiro框架后的开发, 欢迎star


Solr & Spring-Data-Solr

** 关于Solr安装配置和Spring-Data-Solr的入门Demo请查看博文:Solr和Spring-Data-Solr的入门学习 **

Solr需要单独部署到Tomcat服务器上,我这里提供自己已经安装和配置好的Tomcat和Solr: Github

注意事项:

  1. 部署Solr的Tomcat端口和本地项目的端口不能相同,会冲突。

  2. 注意Github仓库中solr-tomcat/webapps/solr/WEB-INF/web.xml中solrhome的位置要修改为自己的。


Redis & Spring-Data-Redis

关于Redis安装配置和Spring-Data-Redis的入门Demo请查看博文:Redis和Spring-Data-Redis的入门学习


起步

启动Solr和Redis

5.png

如果访问localhost:8080/solr/index.html出现Solr Admin页则启动成功。


初始化表结构

CREATE DATABASE ssm_redis DEFAULT CHARACTER SET utf8;

具体的数据库约束文件和表数据请看:ssm-redis-solr/db

这里我们模拟添加了934条商品数据


搭建SSM-Shiro集成环境

具体的SSM整合Shiro的教程请看我这个项目: 手摸手教你SSM整合Shiro。这里不再说SSM整合Shiro的教程,默认认为已经大家已经完成。


搭建SSM-Redis集成环境

集成SSM-Redis开发环境,首先你需要安装Redis并启动Redis-Server,然后就是在项目中搭建Spring-Data-Redis的运行环境:


创建redis-config.properties配置文件

redis.host=127.0.0.1
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true

创建spring-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:other/*.properties"/>
    <!-- redis 相关配置 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大空闲数 -->
        <property name="maxIdle" value="${redis.maxIdle}"/>
        <!-- 连接时最大的等待时间(毫秒) -->
        <property name="maxWaitMillis" value="${redis.maxWait}"/>
        <!-- 在提取一个jedis实例时,是否提前进行验证操作;如果为true,则得到的jedis实例均是可用的 -->
        <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
    </bean>
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}"/>
        <property name="port" value="${redis.port}"/>
        <property name="password" value="${redis.pass}"/>
        <property name="poolConfig" ref="poolConfig"/>
    </bean>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory"/>
        <!-- 序列化策略 推荐使用StringRedisSerializer -->
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
    </beans>
</beans>

配置文件我们已经在博文Redis&Spring-Data-Redis入门中介绍过了,其中最需要关注的就是hashKeySerializer序列化配置。

如果你不添加序列化配置也是没影响的,但是存入Redis数据库中的KEY和VALUE值都是乱码的,当然是用Spring-Data-Redis是毫无影响的。

如果添加了序列化配置:配置值类型数据用StringRedisSerializer序列化方式;配置Hash类型数据用JdkSerializationRedisSerializer序列化方式。


测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/spring*.xml"})
public class TestRedisTemplate {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void setValue(){
        redisTemplate.boundValueOps("name").set("tycoding");
    }
}

然后在redis-cli命令行窗口中输入get name就能得到VALUE为:tycoding。

至此,SSM集成Redis已经完成。


搭建SSM-Solr集成环境

创建spring-solr.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:solr="http://www.springframework.org/schema/data/solr"
       xsi:schemaLocation="http://www.springframework.org/schema/data/solr
  		http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- solr服务器地址 -->
    <solr:solr-server id="solrServer" url="http://127.0.0.1:8080/solr/new_core"/>
    <!-- solr模板,使用solr模板可对索引库进行CRUD的操作 -->
    <bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
        <constructor-arg ref="solrServer"/>
    </bean>
</beans>

spring-solr配置文件我们再博文Solr&Spring-Data-Solr入门中我们已经介绍过了。其中最需要注意的就是solr服务器url地址的配置,组成结构一定要是:Ip + 端口 + solr项目名称 + core实例名称

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/spring-solr.xml")
public class TestSolrTemplate {
    @Autowired
    private SolrTemplate solrTemplate;
    @Test
    public void testAdd() {
        Goods goods = new Goods(1L, "IPhone SE", "120", "手机", "Apple", "Apple");
        solrTemplate.saveBean(goods);
        solrTemplate.commit(); //提交
    }
}

关于Goods实体类定义,请看/java/cn/tycoding/entity/Goods.java
然后我们在浏览器中访问localhost:8080/solr/index.html,点击Query可以看到:

6.png


开始

数据库数据批量导入Solr索引库

上面已经完成了SSM-Shiro-Redis-Solr的集成环境配置,那么思考:既然用Solr完成搜索功能,那么怎么实现呢?

以前我们直接请求数据库用concat()模糊查询实现搜索功能,但是这种方式有很大的弊端:1.给数据库造成的访问压力很大;2.无法识别用户查询的数据到底是title字段还是price字段…
如果用Solr完成搜索功能,就很容易解决了这些问题。那么我们需要往Solr索引库中添加数据,Sorl才能搜索出来数据呀:

@Component
public class SolrUtil {
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private SolrTemplate solrTemplate;

    /**
     * 实现将数据库中的数据批量导入到Solr索引库中
     */
    public void importGoodsData() {
        List<Goods> list = goodsMapper.findAll();
        System.out.println("====商品列表====");
        for (Goods goods : list) {
            System.out.println(goods.getTitle());
        }
        solrTemplate.saveBeans(list);
        solrTemplate.commit(); //提交
        System.out.println("====结束====");
    }
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring*.xml");
        SolrUtil solrUtil = (SolrUtil) context.getBean("solrUtil");
        solrUtil.importGoodsData();
    }
}

对应的Mapper.xml

<select id="findAll" resultType="cn.tycoding.entity.Goods">
    SELECT * FROM tb_item
</select>

目的就是查询数据库中所有数据,然后调用solrTemplate.saveBean(List)将查询到的List集合数据添加到Solr索引库中,之后我们在localhost:8080/solr/index.html中能查询出来共有934条记录数据。


实现Solr搜索功能

前端

由于前端使用了Vue.JS和ElementUI,如果不了解的话请仔细阅读官方文档,或者,你可以查看我的博文记录: Vue学习学习笔记

在index.html中定义:

<el-input placeholder="请输入内容" type="text" class="input-with-select" @keyup.enter.native="search" v-model="searchMap.keywords">
    <el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>

在index.js中定义:

data() {
  return {
    searchMap: { keywords: '' }
  }
},
methods: {
  search() {
      this.$http.post('goods/search.do', this.searchMap).then(result => {
          this.goods = result.body.rows;
      });
  },
}

后端

在GoodsController.java中定义:

@RequestMapping("/search")
public Map<String, Object> search(@RequestBody Map<String, Object> searchMap) {
    return goodsService.search(searchMap);
}

为什么要用Map接收前端数据?

如果前端传来的数据不止一个,且不属于后端的任何一个实体类对象,前端传来的仅是一个自定义的对象(xx:{});那么后端势必不能通过实体类对象来接收,且是POST请求,后端必须也使用对象类型来接收数据且必须用@RequestBody标识对象,原因:

  1. 前端传来的数据不止一种。
  2. 前端传来的数据封装在对象中。

所以,综上,Map<K, V>这种数据结构最适合作为接收对象类型。


在GoodsServiceImpl.xml中定义:

public Map<String, Object> search(Map searchMap) {
  Map<String, Object> map = new HashMap<String, Object>();
  Query query = new SimpleQuery();
  //添加查询条件
  Criteria criteria = new Criteria("item_keywords").is(searchMap.get("keywords"));
  query.addCriteria(criteria);
  ScoredPage<Goods> page = solrTemplate.queryForPage(query, Goods.class);
  map.put("rows", page.getContent()); //返回查询到的数据
  return map;
}

启动项目,再搜索框中输入苹果回车即出现:

7.png

但是发现页面中只显示10条数据(实际我们添加的苹果手机数据不止10条),为了更优雅的显示,我们实现分页


实现分页查询

在后端中我们用limit方式显示分页,或者更简单的用Mybatis的PageHelper分页查询实现分页查询。
而,我们在博文Solr&Spring-Data-Solr入门学习中讲了Solr分页查询的方式:

修改GoodsServiceImpl.java

public Map<String, Object> search(Map searchMap) {
    Map<String, Object> map = new HashMap<String, Object>();
    Query query = new SimpleQuery();
    //添加查询条件
    Criteria criteria = new Criteria("item_keywords");
    if (searchMap.get("keywords") != null && searchMap.get("keywords") != ""){
        System.out.println("执行了...");
        criteria.is(searchMap.get("keywords"));
    }
    query.addCriteria(criteria);

    //分页查询
    Integer pageCode = (Integer) searchMap.get("pageCode");
    if (pageCode == null) {
        pageCode = 1; //默认第一页
    }
    Integer pageSize = (Integer) searchMap.get("pageSize");
    if (pageSize == null) {
        pageSize = 18; //默认18
    }
    query.setOffset((pageCode - 1) * pageSize); //从第几条记录开始查询:= 当前页 * 每页的记录数
    query.setRows(pageSize);
    ScoredPage<Goods> page = solrTemplate.queryForPage(query, Goods.class);
    map.put("rows", page.getContent()); //返回查询到的数据
    map.put("totalPage", page.getTotalPages()); //返回总页数
    map.put("total", page.getTotalElements()); //返回总记录数
    return map;
}
前端

ElementUI提供了分页查询的插件,我们仅需要传给它几个参数,即可实现分页,详细的文档介绍请看我这篇博文:Vue+ElementUI实现分页

在index.html中添加:

<el-pagination
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="pageConf.pageCode"
        :page-sizes="pageConf.pageOption"
        :page-size="pageConf.pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pageConf.totalPage">
</el-pagination>

在index.js中添加:

data() {
  return {
    searchMap: {
        keywords: '',

        //分页选项
        pageCode: '', //当前页
        pageSize: '', //每页的记录数
    }
    pageConf: {
        //设置一些初始值(会被覆盖)
        pageCode: 1, //当前页
        pageSize: 18, //每页显示的记录数
        totalPage: 20, //总记录数
        pageOption: [18, 25, 30], //分页选项
    },
  }
},
methods: {
    //pageSize改变时触发的函数
    handleSizeChange(val) {
        console.log(val);
        this.searchMap.pageSize = val;
        this.searchMap.pageCode = this.pageConf.pageCode;
        this.search(this.pageConf.pageCode, val);
    },
    //当前页改变时触发的函数
    handleCurrentChange(val) {
        console.log(val);
        this.searchMap.pageCode = val;
        this.searchMap.pageSize = this.pageConf.pageSize;
        this.search(val, this.searchMap.pageSize);
    },
}

我们只需要修改以上JavaScript代码即可,因为search方法传给后台的是searchMap这个对象数据,只要其中包含了pageCode和pageSize这两个参数,就会被封装到后端接收的Map集合中。
其中点击上一页,下一页按钮触发的函数在<el-pagination>中已经定义了,如果点击上一页下一页触发handleCurrentChange()函数,如果点击每页5条记录变成10条记录就会触发handleSizeChange()函数;两个函数都又调用了search()方法,当点击分页按钮时就发送数据给后端,其中包含当前点击的pageCode和pageSize的值,后端接收到这两个值进行分页计算,并将数据返回给前端。

8.png


实现条件过滤

上面讲了分页查询,仅仅是单方面的查询,并没有任何条件限制。这一功能在SSM中我们直接通过concat()模糊条件过滤,但在Solr中提供了FilterQuery()实现条件过滤查询:

修改GoodsServiceImpl.java文件,在search()方法中添加:

      if (searchMap.get("category") != null) {
          if (!searchMap.get("category").equals("")) {
              System.out.println("执行了category");
              FilterQuery filterQuery = new SimpleFilterQuery();
              Criteria filterCriteria = new Criteria("item_category").is(searchMap.get("category"));
              filterQuery.addCriteria(filterCriteria);
              query.addFilterQuery(filterQuery);
          }
      }

      //按品牌过滤
      if (searchMap.get("brand") != null) {
          if (!searchMap.get("brand").equals("")) {
              System.out.println("执行了brand...");
              FilterQuery filterQuery = new SimpleFilterQuery();
              Criteria filterCriteria = new Criteria("item_brand").is(searchMap.get("brand"));
              filterQuery.addCriteria(filterCriteria);
              query.addFilterQuery(filterQuery);
          }
      }
前端

修改index.html

<el-checkbox-group :max="1" v-model="change.category" @change="selectMethod">
    <el-checkbox v-for="classify in classifyData.category" :label="classify" border size="mini">{{classify}}</el-checkbox>
</el-checkbox-group>
<el-checkbox-group :max="1" v-model="change.brand" @change="selectMethod">
    <el-checkbox v-for="classify in classifyData.brand" :label="classify" border size="mini">{{classify}}</el-checkbox>
</el-checkbox-group>

修改index.js

searchMap: {
  brand: '',
  price: '',
}

//checkbox选择的选项
change: {
    category: [],
    brand: [],
    price: []
},

selectMethod(val) {
    this.searchMap.category = this.change.category[0];
    this.searchMap.brand = this.change.brand[0];
    this.search(); //每次点击后都进行查询
},

实现商品价格升降过滤

修改GoodsServiceImpl.java中的search方法:

  //按价格的升降序查询
  if (searchMap.get("sort") != null) {
      if (!searchMap.get("sort").equals("")) {
          String sortValue = (String) searchMap.get("sort");
          String sortField = (String) searchMap.get("field");
          if (sortValue != null && !sortValue.equals("")) {
              if (sortValue.equals("asc")) {
                  Sort sort = new Sort(Sort.Direction.ASC, "item_" + sortField);
                  query.addSort(sort);
              }
              if (sortValue.equals("desc")) {
                  Sort sort = new Sort(Sort.Direction.DESC, "item_" + sortField);
                  query.addSort(sort);
              }
          }
      }
  }
前端

修改index.html:

<el-checkbox-group v-model="change.price" :max="1" @change="selectMethod">
        <el-checkbox :label="'0-500'" border size="mini">0-500元</el-checkbox>
        <el-checkbox :label="'500-1000'" border size="mini">500-1000元</el-checkbox>
        ...
</el-checkbox-group>

修改index.js

searchMap: {
  price: '',
}

selectMethod(val) {
  this.searchMap.price = this.change.sort[0];
}

9.png


实现查询结果高亮显示

实现高亮显示,我们先看一下效果:

10.png

可看到根据关键字苹果查询出来的记录中苹果字样都被标记为红色斜体样式,这即是我们的目的,你可以查看淘宝的查询,也是查询字样以红色显示出来。

如果使用高亮查询,那么之前的Query query = new SimpleQuery()就不在满足需求了;高亮查询使用HighlightQuery query = new SimpleHighlightQuery();

修改GoodsServiceImpl.java中的Search()方法:

    HighlightQuery query = new SimpleHighlightQuery();
    HighlightOptions highlightOptions = new HighlightOptions().addField("item_title"); //设置高亮的域
    highlightOptions.setSimplePrefix("<em style='color: red'>"); //设置高亮前缀
    highlightOptions.setSimplePostfix("</em>"); //设置高亮后缀
    query.setHighlightOptions(highlightOptions); //设置高亮选项

初始化高亮查询HighlightQuery类,利用其包含的setSimplePerfix设置查询结果的前缀html标签,利用setSimplePostfix设置查询结果后缀HTML标签。

循环高亮查询结果集合数据:

    HighlightPage<Goods> page = solrTemplate.queryForHighlightPage(query, Goods.class);
    //循环高亮入口集合
    for (HighlightEntry<Goods> h : page.getHighlighted()) {
        Goods goods = h.getEntity(); //获取原实体类
        if (h.getHighlights().size() > 0 && h.getHighlights().get(0).getSnipplets().size() > 0) {
            goods.setTitle(h.getHighlights().get(0).getSnipplets().get(0)); //设置高亮的结果
        }
    }

之前我们可以直接通过query.getContent()获取到查询结果,但是使用了高亮查询HighlightQuery就不能直接通过getContent()获取数据了,我们要手动遍历HighlightPage这个对象,他是一个层层嵌套的集合数据,详细数据结构这里不再说了。


更新索引

既然使用了Solr管理商品数据,查询时直接从Solr索引库中查询数据,而不是查询数据库中的数据,那么如果修改了商品的信息:添加、删除、修改。那么就必须同步使Solr索引库中的数据和数据库中的数据保持一致才能实现查询出来的数据是真实的。

所以我们要在对商品添加、删除、修改的时候同步更新Solr索引库数据:

修改GoodsServiceImpl.java中create、delete、update方法,更新Solr索引库:

    @Override
    public void create(Goods goods) {
        goodsMapper.create(goods);

        Long id = goodsMapper.maxId(); //获取根据主键自增插入的最新一条记录的ID值
        goods.setId(id);

        //更新索引库
        solrTemplate.saveBean(goods);
        solrTemplate.commit();
    }

    @Override
    public void update(Goods goods) {
        goodsMapper.update(goods);

        //更新索引库
        solrTemplate.deleteById(String.valueOf(goods.getId()));
        solrTemplate.commit();
        List<Goods> list = new ArrayList<Goods>();
        list.add(goods);
        solrTemplate.saveBeans(list);
        solrTemplate.commit();
    }

    @Override
    public void delete(Long... ids) {
        for (Long id : ids) {
            goodsMapper.delete(id);

            //更新索引库
            solrTemplate.deleteById(String.valueOf(id));
            solrTemplate.commit();
        }
    }

注意,在添加商品时,传来的实体类中并不包含Id属性数据,因为我们使用了MySql的自增主键;而想要向Solr索引库中添加新数据又必须制定Id属性值,因为Solr不会自增主键呀。所以我们在goodsMapper.create()后调用MaxId()方法获取最新自增的主键值,其在Mapper.xml中定义:

<select id="maxId" resultType="Long">
    SELECT MAX(id) FROM tb_item
</select>

关于Redis

眼看着教程就结束了,但是为什么教程中没有解释Redis的应用呢?

解释

关于SSM整合Redis的教程请仔细看我的博文:Redis和Spring-Data-Redis入门学习。

因为Redis在本项目中并没有用到实际的应用中,为何?首先我们要考虑为什么要用Redis?

Redis缓存嘛,不就是缓存哪些大批量的数据减轻服务器压力的。但是,并不是说所有的大批量的数据都得去缓存,虽然我们项目中的商品管理功能中已经出现了900多条数据,但是这些数据都需要频繁的正删改,而缓存技术中一个难点就是缓存同步问题,你的缓存数据必须时刻和数据库(真实的数据)保持一致,如果每修改一条记录就去更新一遍缓存势必会给缓存服务器造成很大压力。

什么数据适合放进缓存?不常修改的数据。比如商品的分类列表数据:

11.png

但是原谅我,我只是想简单的实现以下Solr的搜索功能,真实项目中商品的分类数据肯定是存在另一张表中,由于我并没有实现,所以Redis在本项目中的应用就比较少了。


项目截图

1.png
2.png

3.png

4.png


交流

如果大家有兴趣,欢迎大家加入我的Java交流群:671017003 ,一起交流学习Java技术。博主目前一直在自学JAVA中,技术有限,如果可以,会尽力给大家提供一些帮助,或是一些学习方法,当然群里的大佬都会积极给新手答疑的。所以,别犹豫,快来加入我们吧!


联系

If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.


交流

如果大家有兴趣,欢迎大家加入我的Java交流群:671017003 ,一起交流学习Java技术。博主目前一直在自学JAVA中,技术有限,如果可以,会尽力给大家提供一些帮助,或是一些学习方法,当然群里的大佬都会积极给新手答疑的。所以,别犹豫,快来加入我们吧!


联系

If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.

基于ssm的旅游网站的设计与实现 随着互联网科技的快速发展,各行各业都借助互联网飞快革新,开拓新的领域,借助计算机技术开发各种便捷的服务软件,各种网站能兼容各大浏览器,计算机在生活中起着至关重要的作用,很多行业把握住机会,利用科技信息化等有了不小收获。首先要对旅游用户以及管理员的相关信息有整体把握,了解用户旅游出行的诉求以及管理员对业务的要求,然后要实地调查了解每个景点旅游攻略,管理员对景点以及用户等信息的管理方式,记录和处理相关的数据。(4)酒店信息管理:对已经添加在网站出售的酒店信息查看修改,对新曾的酒店信息添加功能。 阅读详情

相关推荐

solr在SSM框架中使用(支持中文分词查询)

这个项目是solr在SSM框架中的使用,实现了在solr中增删改查操作,支持中文分词搜索,高亮显示查询内容,点击查询,描述条件处输入内容进行查询,可以测试中文分词功能。

SSM框架速成5:在图书馆管理系统上新增搜索查询功能(开发思维)

这篇内容是在上一次的SSM框架速成4也就是SSM实战的项目中新增一个功能,由于新增一个功能会修改源代码所以单独写出来。其实主要还是培养一下写功能的思路和流程咋样最好。没有怎么用bootstrap那些,很多还是简单的页面布局。

m0_52380556的博客 1712

SSM框架的分页模糊查询代码(精)

【学习SSM分页模糊查询必备】 .zip格式,方便Windows和Unix用户 登录页地址:http://localhost:8080/ssm3/user/login 账号密码为数据库中所有用户名和密码(admim 123) tomcat配置文件和jdbc不匹配的请自行修改 环境:基于SSM框架(Spring+SpringMVC+MyBatis) + Mysql数据库 + Tomcat7 功能:登录、首页显示用户名和身份、分页http://u.download.youkuaiyun.com/images/btn_submit.png、模糊查询、 页面跳转(首页、上一页、下一页、末页、指定页跳转(用户输入),第几/几页,总数据行数) 以及跳转页数的溢出判断、非整形正则判断 数据视图的隔行变色和光棒效果

ssm实现搜索功能

1.数据库持久层(mapper层) FoodMapper List<Food> findFood(@Param("foodName") String foodName, @Param("foodExplain") String foodExplain, @Param("start") int start, @Param("end") int end); FoodMapper.xml <!--搜索食品功能--> <!--将查询的结果放在二级缓存中--> <sel

Silly011的博客 3791

Coursera | 离散数学概论(北大)| quiz答案

Coursera离散数学概论quiz答案Week1:数理逻辑:基本概念Week2:数理逻辑:命题逻辑及形式系统Week3:数理逻辑:谓词逻辑及形式系统Week4:集合论:集合代数   先放下Coursera上找的离散数学部分相关课程:   btw.线上学习拿证书还有很多,MOOC、edm等都可。   博主选了北京大学离散数学概论Discrete Mathematics Generality。Mooc上貌似也有,但是上课时间貌似不如Coursera灵活,Coursera时间自己调度,规定时间上完即可。目前课

小鱼干的博客 4126

恶意代码实验3:Word宏病毒实验

只要下次打开这个word文档,就会执行以上代码,并将自身复制到Normal.dot(word文档的公共模板)和当前文档的ThisDocument中,同时改变函数名(模板中为Document_Close,当前文档为Document_Open),此时所有的word文档打开和关闭时,都将运行以上的病毒代码,可以加入适当的恶意代码,影响word的正常使用,本例中只是简单的跳出一个提示框。回答不正确三次,即可自动跳出病毒程序,但那时已经出现几十个文档。1、打开的宏编辑器如图所示,即可编写病毒代码。

qq_63949327的博客 6504

基于SSM,实现对数据的分页与搜索联动(详细代码实现)

分页与搜索联动务必熟练掌握,后面也会更新迭代,但这是基础,这都不会,那只能HelloWorld了。

Y_Y_9527的博客 1287

Crazyflie 2.1固件刷写与地址配置全攻略:从开箱到连接Crazyswarm

本文详细介绍了Crazyflie 2.1微型无人机的固件刷写、地址配置及与Crazyswarm系统的集成方法。从开箱检查到多机协同飞行,涵盖了硬件准备、固件刷写、无线电地址修改等关键步骤,帮助用户快速实现集群飞行控制。特别针对Crazyswarm系统集成提供了实用配置示例和调试技巧。

weixin_42530458的博客 405

SSM框架整合:新增搜索功能

【代码】SSM框架整合:新增搜索功能。

qq_53374893的博客 542

保姆级教程:用Vue3+Element Plus快速搭建Flowable流程定义管理后台界面

本文提供了一份详细的Vue3+Element Plus教程,指导开发者快速搭建Flowable流程定义管理后台界面。从项目初始化、核心页面设计到响应式数据处理,全面覆盖前端开发关键步骤,帮助提升企业级应用开发效率。

weixin_42662293的博客 478

VCSA 6.7证书更新全流程指南:从故障诊断到完整替换

本文详细介绍了VCSA 6.7证书更新的全流程,包括故障诊断、证书替换操作步骤及常见问题解决方案。通过使用官方脚本和证书管理器,帮助管理员快速解决证书过期问题,确保vCenter系统的稳定运行。特别强调了STS证书修复和全量证书重置的关键步骤,适用于vcsa6.7环境下的证书管理需求。

weixin_42634811的博客 450

优雅的实现电商Solr搜索功能,整合SSM+Redis+Shiro框架

网址https://ruby.ctolib.com/article/wiki/96646 SSM框架整合Shiro后的开发http://tycoding.cn/2018/09/18/ssm-shiro/ 手摸手教你SSM框架整合Shiro后的开发https://github.com/TyCoding/shiro   solr服务器url地址的配置,组成结构一定要是:Ip + 端口 + so...

java20150326的博客 545

大模型-高通qnn基础

提供较低级别、高度可定制的统一API,通过单独的库加速所有AI加速器核心上的AI模型, 可以直接用于针对特定的加速器核心或从流行的运行时(包括Qualcomm Neural Processing SDK、TensorFlow Lite和ONNX运行时)委派工作负载。一个支持异构计算、系统级配置的一体化SDK,旨在将AI工作负载引导到我们平台上的所有加速器核心。为开发人员提供灵活性,包括核心间协作支持和其他高级功能。是一个为训练好的神经网络模型提供高级量化和压缩技术的库。

点滴的岁月 4083

Solr学习 - 在liunx中安装Solr7.7

目录: 快速开始: Solr 7.7官方文档 下载地址:官网各版本下载包注意:solr需要和Java版本对应 目录结构 安装步骤 资源 一.目录结构 说明: bin:solr的运行脚本 contrib:solr的一些扩展jar包,用于增强solr的功能 dist:该目录包含build过程中产生的war和jar文件,以及相关的依赖文件 docs:solr的API文档 exa...

yiguang_820的博客 592

玩转Docker | 使用Docker部署Trilium Notes知识库工具

玩转Docker | 使用Docker部署Trilium Notes知识库工具

qq_59334230的博客 1441

通过电源模块降低电源噪声的3种方法

电源噪声是一种常见且不受欢迎的电气现象。如果不降低噪声,其会对敏感的医疗、测试测量、航空航天和国防系统的应用性能产生不利影响。当今的高精度模拟信号链系统需要直流/直流开关稳压器产生稳压电源轨,为低噪声应用中的模数转换器(ADC)、数模转换器(DAC)、现场可编程门阵列(FPGA)及其子系统供电。尽管直流/直流开关稳压器具有高工作效率,它们的开关操作会导致较大的不连续电流,从而产生较高的输入和输出电压纹波、频率尖峰和宽带噪声。

qq_43416206的博客 1423

运用SSM实现数据库的查询功能

运用ssm实现l查询的功能

WMJ_wmj75的博客 917

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

SSM整合实例--(四)条件搜索

一、条件搜索 商品条目一旦多了起来,就不能一页一页的翻找。需要设置条件,根据条件搜索条目。 二、代码实现 在原来的查找所有productList的功能基础上添加条件参数,设置条件查询。 2.1 JSP页面修改 product_list.jsp 添加 searchDiv 代码,如下图所示。为搜索前端页面展示 效果如下: 新增的div中对应的js代码: function resetSearch()...

Double____C的博客 2918

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

[BYSX] SSM框架中实现分页和搜索功能

[BYSX] SSM框架中实现分页和搜索功能 在显示用户信息或其他信息时,我们都会在页面中创建列表显示,但是当数据过多时,一个页面就会无法全部展示,因此我们需要使用分页。当我们使用用户名模糊查询用户时,查询的用户也可能通过分页的方式展示,因此分页功能和搜索功能会联系在一起。为了实现这两个功能,首先我们需要创建一个界面,这个界面中包括搜索,分页时的首页,尾页,下一页,上一页,以及每页的页数。 这个页面的实现是使用jsp文件来完成的,具体的就不展示了,我只将搜索和每页的页码的部分展示出来,如下: <!-

r2tan 1537

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

ssm+redis+solr小例子

Eclipse Mars Release (4.5.0) jdk1.8 redis服务3.0 solr服务6.5.1 mysql pom文件,这是我从另一个小项目里面复制出来的 关键的jar都有注释的<!-- 添加Servlet支持 --> <dependency> <groupId>javax.servlet</groupId> <artifact

yyao9986的博客 4618

SSM综合项目实战(TTSC) -- day09 Solr,搜索系统

一、solr服务的安装 二、Solr配置和使用 三、Solr集群版 四、创建搜索系统 五、数据准备

wingzhezhe的博客 2220

SSM整合步骤

整合SSM 大概步骤 一、数据库:创建一个存放书籍数据的数据库表 二、基本环境配置 1、新建一Maven项目!ssmbuild , 添加web的支持 2、导入相关的pom依赖! 3、Maven资源过滤设置 4、建立基本结构和配置框架! mybatis-config.xml applicationContext.xml 三、Mybatis层编写 1、数据库配置文件 database.properties 2、IDEA关联数据库 3、编写MyBatis的核心配置文件 4、编写数据库对应的实体类 com.kua

incarnation_ll的博客 438

ssm框架+easyUI模糊搜索。

最近项目赶得紧。自己还感冒了。不在状态,不过幸好做完了。留个纪念。 toolbar: [{ text: ' 文章名:' }, { iconCls: 'icon-search', text: '查询', handler: function () {

技术之旅:一位项目管理者的编程视角与项目管理洞见; 5496

SSM框架——实现分页和搜索分页

转载: https://blog.youkuaiyun.com/u012909091/article/details/26447713 1.分页 import java.io.Serializable; /** * 分页 */ public class Page implements Serializable { private static final long serialVersionUI...

村头杠把子的博客 322
上一篇: SpringBoot入门之工程搭建(IDEA版)
下一篇: Solr及Spring-Data-Solr入门学习
TyCoding
博客等级 码龄9年 316粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值