三、模块开发
3.1 (新增员工)分析设计P16
一般是对产品原型(静态HTML页面)分析,因为比较直观。思考录入项有没有什么限制。
密码采用默认密码,登录后可以进行修改。
接口定义如下(data一般是查询是会用到,msg一般是出错时会返回消息):
数据库设计如下:
3.2 (新增员工)代码开发P17
注意:当前端提交的数据和实体类中对应的属性差别较大时(也就是实体类中会有多余的属性),建议使用DTO来封装(DTO里的数据字段和前端提交的数据字段都能对应上)。
1.在EmployeeController中新建一个方法save,传入的参数是employeeDTO
1. 首先编写如下代码,是网页端读入的字段数据,在这里传入employeeService对象。有2点注意事项:①前端传入的数据是json格式,要用@RequestBody注解转换为对象。②为了方便调试加一个log.info,花括号{}的内容在后面会被替换为employeeDTO的值。
2. 在EmployeeService中编写如下代码,思路是:先创建一个emloyee实体类,然后把DTO的数据拷贝到实体类中,然后对剩下的属性进行赋值。
有2个注意事项:①可以用BeanUtils工具类中的copyProperties方法来对对象进行拷贝,前提是对象的属性有一部分是相同的。②不应该直接用数字数字,否则会是硬编码,应该使用StatusConstant常量类。
3. 在EmployeeMapper中编写SQL语句,来将数据插入数据库:
3.3 (新增员工)功能测试P18
在开发阶段,前端界面可能没有开发好,所以不能进行前后端联调测试,只能用接口文档进行测试。
下面进行测试出现401,是因为有拦截器进行了拦截,原因是缺少token令牌:
3.4 (新增员工)完善P19-20
问题1:录入的用户名已存在,抛出异常后没有处理,没处理的话,控制台会抛出错误P19。
用全局的异常处理器sky-server/handler/GlobalExceptionHandler,创建exceptionHandler方法,在方法里添加如下代码:
目的是输出:xxx已经存在的提示。核心思想是:提取错误那段话的第3个词,然后拼接后输出。
JWT认证机制:用户发起请求发送用户名和密码,后端进行校验,如果验证通过就生成JWT Token,将Token返回给客户端,客户端会保存Token,在后续请求的请求头中都会携带JWT Token,请求会被拦截器拦截到,会检查Token,如果通过就会展示数据,如果没有通过就会返回错误信息。
在拦截请求验证的时候可以获得JWT令牌
问题是:在解析出登录员工id后如何传递给Service的save方法?
答:通过ThreadLocal,它是Thread的局部变量,为每个线程提供单独一份的存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,在线程外则不能访问。
可以通过在controller、service和拦截器中输出线程的id来看是否单次请求是同一个线程,经实验验证是同一个线程。
在sky-common/src/main/java/context/BaseContext下封装了ThreadLocal的操作。
先在拦截器JwtTokenAdminInterceptor里将ID存到存储空间里(set),因为每次请求线程不变,所以存储空间的值不会被更改,因此可以在EmployeeServiceImpl类中取到该值(get),进而输出,很妙!
3.5 (分页查询)分析设计P21
分页展示,每页展示10条数据,可以输入员工姓名进行查询。total是总的数目,records是一页的条目数。
3.6 (分页查询)代码开发P22
下面是PageResult和EmployeePageQueryDTO的实体类定义:
Result<PageResult>是在PageResult的基础上加上code和msg,作为返回给前端的对象。
在EmployeeController添加一个方法
PageHelper的startPage方法可以通过传入的参数自动设置Limit,传入的是页码和每页的记录数,好处是:字符串的拼接不用自己做。底层实现是:它会给ThreadLocal设置上述参数,然后在执行SQL语句时会自动被取出,然后拼接成Limit。
Page是PageHelper插件定义的一个泛型类,是一个固定的返回类型。
pagehelper可以简化分页代码的编写:
在EmployeeMapper.xml中编写SQL语句,limit不用我们手写,pagehelper会自动帮我们追加拼接,order by是排序条件:
如果有传入name,代表是员工姓名查询,它只会返回带有相关词(字也可以,因为是模糊查询)的员工信息。
如果没有传入name,那么name就为空,<if>判断内容不执行,<where>默认返回1,所以它会查询所有employee元素。
在这里是模糊查询,用concat将name与%进行拼接,%的意思是匹配任意字符串/字符。
<select>标签的id是mapper中的对应方法名。resultType是传入的参数类型。