)
前言
最终目的是使用redis存取字典表。这个案例只是一个很小的应用,但在此过程中也遇见很多问题,逐个击破,最后实现功能。
准备工作
这里只是实现springboot集成layui,完成自动获取下拉框数据的操作,redis在另一篇文章中也有说明。
这里我的目的是从mysql数据库获取值,如果不想这么麻烦,也可以将所有事情直接交给前端,使用layui和layui的插件。在另一篇文章中也有相关说明。
mysql建表就不展示了,只需要省市的id和name及相关数据即可。
首先需要以下依赖:
注:我当时随便用了个springcloud框架,这里是子工程的依赖,父工程也只是springcloud和springboot的dependencies统一管理,这里就不展示了。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
//mybatis和mysql就不解释了
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
//json格式处理
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
po文件(entity文件)
这里就使用简单的po就好,其实还可以使用vo将省市联合,简化查询语句,一查出多值,但是不建议这样使用,数据量大了一查太多值的话,效率就更低了。
city:
public class City1 {
private String id;
private String name;
private String codePid;
}//getter和setter方法及toString就不展示了
province:
public class Province1 {
private String id;
private String name;
}//getter和setter方法及toString就不展示了
mapper配置文件:
这里根据省id查市可以不用这么麻烦,但是sql拼接显得b格高一点,也不是太难。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.singularity.mapper.SelectMapper">
<resultMap id="ProvinceMap" type="com.singularity.po.Province1">
<id column="p_id" property="id"></id>
<result column="p_name" property="name"></result>
</resultMap>
<select id="query" resultMap="ProvinceMap">
select * from `provience_data`
</select>
<sql id="queryById">
<if test="id!=null">
and p_id =#{id}
</if>
</sql>
<resultMap id="CityMap" type="com.singularity.po.City1">
<id column="c_id" property="id"></id>
<result column="c_name" property="name"/>
<result column="p_id" property="codePid"/>
</resultMap>
<select id="queryById" resultMap="CityMap">
select * from `city_data`
<where>
<include refid="queryById"></include>
</where>
</select>
</mapper>
后端代码
接着配置mapper接口,创建service接口,service实现类,将mapper接口注入service的实现类,最后在controller中调用数据,这几个步骤集中展示。
mapper接口
@Mapper
public interface SelectMapper {
List<Province1> query();
List<City1> queryById(String id);
}
service接口
public interface SelectService {
List<Province1> query();
List<City1> queryById(String id);
}
service实现类
@Service
public class SelectServiceImpl implements SelectService {
@Resource
SelectMapper selectMapper;
@Override
public List<Province1> query() {
return selectMapper.query();
}
@Override
public List<City1> queryById(String id) {
return selectMapper.queryById(id);
}
}
controller控制层类
@Controller
@RequestMapping("/query")
public class SelectController {
@Resource
SelectService selectService;
@ResponseBody
@RequestMapping("/queryP")
public List<Province1> query(){
List<Province1> query = selectService.query();
return query;
}
@ResponseBody
@RequestMapping("/queryC")
public List<City1> queryCity(@RequestParam String id){
List<City1> queryCity = selectService.queryById(id);
return queryCity;
}
注:
写完之后一定要写测试类测试是否能取到值,否则后面找错更麻烦。这也是我遇到的问题之一,花费了很长时间找问题。这里需要注意springboot使用test测试类需要添加两个注解,在另一篇文章也有写到,不想找的话直接看下面也可
@RunWith(SpringRunner.class)@SpringBootTestpublic class Test { @Resource SelectService selectService; @org.junit.Test public void query(){ List<City1> query = selectService.queryById("1001"); query.forEach(city1 -> System.out.println(city1)); }}
前端部分
这里前端直接使用layui框架,我的问题主要也是体现在这里,对该框架不熟悉,碰上了很多问题,浪费了较长时间,不过最终还是实现了前后端交互。
我个人是直接将layui和html一同放在resources的static文件夹下面,也可以将html放在templates下面,无影响。
前端这里就分段说明。
头文件
这里需要注意的地方就是不用忘记引用,最好就放在文件头,否则放其他位置可能使用先于引用,会报错。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="js/layui/layui.js"></script> <link rel="stylesheet" href="js/layui/css/layui.css"></head>
下拉框
这里面像是lay-filter,layui-form这种都是固定写法,不这么写的话下面的script会找不到值,找不到位置。
<body><form class="layui-form"> <div class="layui-input-inline"> <select id="province" name="province" lay-verify="required" class="select" lay-filter="brickType"> <option id="pid" value="" >请选择省</option> </select> </div> <div class="layui-input-inline"> <select id="city" name="city" lay-verify="required" class="select"> <option id="cid" value="" >请选择市</option> </select> </div></form>
动态js
<script> layui.use('form',function(){ var $ = layui.jquery; var form = layui.form; $.ajax({ url: '/query/queryP', dataType: 'json', type: 'post', success: function(query) { //$("#province").append(new Option("请选择省", "0")); $.each(query, function(index, item) { $('#province').append(new Option(pvalue =item.name,pid =item.id)); }); //重新渲染 form.render("select"); } }); //判定省的值是否改变,实质上就是一个onchange事件 form.on('select(brickType)', function(data){ var val=data.value; //console.info(val); $.ajax({ url: '/query/queryC', data:{id:val}, dataType: 'json', type: 'post', success: function(queryCity) { //$("#province").append(new Option("请选择省", "0")); $('#city').empty(); $.each(queryCity, function(index, item) { $('#city').append(new Option(cvalue =item.name,cid =item.id)); }); //重新渲染 form.render("select"); } }); }); });
注
这里就是我花费较长时间的地方,主要有几点。
- 1.我看线上较多只使用一次ajax,也就是返回后端一次。这样所带来的问题之一前面也提到过,数据量一大反而效率更低。不过返回两次也谈不上高效率,不过增加redis的话能在很大程度上弥补这个问题。
- 2这里的layui拓展模块是重复造轮子了,并不是我自己写的,因为layui文档中下拉框也没有动态获取这个模块,线上找了不少办法,没有需求与我类似的,要么值直接在前端写死,要么只返回后端一次,这里的代码也只能满足某一特定需求。
- 3.layui前后端交互传值时较多地使用json格式。
- 4.layui中没有onchange事件。
- 5.前端编写注意边写边测试。否则后面很难找bug。
最终效果
数据是自己写在mysql里面的,所以值不是很多
这里选择一个省之后,市的数据就已经自动获取了
写在后面
这里就只是springboot+layui实现下拉框数据动态获取,前面也提到过,要做redis才算得上是提高效率,因此还有redis+springbooot集成,也已出。