一般由产品经理设计,根据产品原型图来进行逻辑设计与开发。
设计接口
数据库设计
在Controller层中代码
/**
*新增员工
*/
@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO){
log.info("新增员工:{}",employeeDTO);
employeeService.save(employeeDTO);
return Result.success();
}
接口类
/**
* 新增员工实现方法
* @param employeeDTO
*/
void save(EmployeeDTO employeeDTO);
实现类
/**
* 新增员工
* @param employeeDTO
*/
@Override
public void save(EmployeeDTO employeeDTO) {
Employee employee=new Employee();
//对象属性拷贝,简化代码,前提属性名需要一致
BeanUtils.copyProperties(employeeDTO, employee);
//设置账号状态,默认正常状态为1,0为锁定状态
employee.setStatus(StatusConstant.ENABLE);
//设置密码,默认123456
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
//设置当前记录创建时间以及修改时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
//设置当前记录创建人和修改人id
//TODO 后期需要改为当前登录用户的id,目前先要写死
employee.setCreateUser(10L);
employee.setUpdateUser(10L);
employeeMapper.insert(employee);
}
后端Mapper类
/**
* 插入员工数据
* 数据库变量中默认kebab下划线命名方式(此为历史惯例),在Mybatis中需要通过yml进行驼峰命名转换符合变量命名习惯
* @param employee
*/
@Insert("insert into employee(name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user) " +
"values " +
"(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})")
void insert(Employee employee);
开发阶段更多通过接口文档测试
使用接口文档进行测试
使用debug调试时初始会报401接口异常,是因为jwt令牌拦截未通过。
那如何测试呢?
要先通过登录接口debug获取一个令牌
通过左侧文档管理设置一个全局令牌,参数值即为登录接口所获得的令牌
再重新进行debug测试数据已封装好
插入成功
存在问题
//在拦截器中存入
BaseContext.setCurrentId(empId);
//Controller层
employee.setCreateUser(BaseContext.getCurrentId());
employee.setUpdateUser(BaseContext.getCurrentId());
controller层
@GetMapping("/page")
@ApiOperation("员工分页查询")
public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
log.info("员工分页查询参数为:{}", employeePageQueryDTO);
PageResult pageResult=employeeService.pageQuery(employeePageQueryDTO);
return Result.success(pageResult);
}
Service实现类
/**
* 分页查询实现类
* @param employeePageQueryDTO
* @return
*/
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
//select * from employee limit 0,10
//使用PageHelper分页插件
PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
Page<Employee> page=employeeMapper.pageQuery(employeePageQueryDTO);
long total = page.getTotal();
List<Employee> records = page.getResult();
return new PageResult(total, records);
}
Mapper中使用xml方式,动态SQL
<select id="pageQuery" resultType="com.sky.entity.Employee">
select * from employee
<where>
<if test="name!=null and name!=''">
# 使用concat拼接字符串
and name like concat('%',#{name},'%')
</if>
</where>
# 降序排序
order by create_time desc
</select>
</mapper>
同时复习一下动态SQL的知识
在MyBatis中,动态SQL是一种能够根据不同条件生成不同SQL语句的机制。这使得在查询、更新、插入或删除数据时,可以根据运行时的条件动态地构建SQL语句,而不是在静态的SQL语句中硬编码所有条件。动态SQL通过在XML映射文件中使用一些特定的元素来实现,这些元素允许根据条件包含或排除不同的SQL片段。
where标签:
where标签用于在生成SQL语句时提供一个条件判断块,它会自动去除首个条件之前的多余的AND或OR。这使得可以在使用动态SQL时更灵活地拼接条件,而无需过多的考虑首个条件是否需要添加AND或OR。
<select id="findUsers" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<if test="username != null">
AND username = #{username}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
对比直接使用WHERE则需要手动添加逻辑连接符(如AND、OR)和条件语句,对于首个条件需要额外注意不要添加不必要的连接符。
<select id="findUsers" parameterType="map" resultType="User">
SELECT * FROM users
WHERE
<if test="username != null">
AND username = #{username}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
注意token令牌过期问题需要使用接口登录获取新的token并设置全局变量
问题:日期格式不规范
解决方案:
其中方式一仅对当前注解的变量有效,以后用到日期格式时需要重新添加。推荐使用第二种方式。
方法二,在WebMvcConfiguration配置类中重写父类
/**
* 扩展Spring MVC框架的消息转换器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器..");
//创建一个消息转换器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
//需要为消息转换器设置一个对象转换器,可以将Java对象序列化为json数据
converter.setObjectMapper(new JacksonObjectMapper());
//将自己的消息转换器加入容器中
converters.add(0,converter);
}
修改成功
业务规则:
接口文档:
在启用以及禁用过程中,当用户在浏览器界面点击启用禁用按钮时,参数可以将status值由1变0,由0变1,大概率是通过前端的JavaScript 的功能逻辑实现的,后期查看前端代码再解决。
Controller层
/**
* 启用禁用员工账号
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("启用禁用员工账号")
public Result startOrStop(@PathVariable Integer status,Long id){
log.info("启用禁用员工账号:{},{}",status,id);
employeeService.startOrStop(status, id);
return Result.success();
}
@PathVariable以及前面@RequestBody 两个注解异同点总结
@PathVariable 主要用于从 URI 路径中提取变量值,适用于处理 RESTful 风格的请求。
@RequestBody 主要用于将请求体中的数据映射到方法的参数上,适用于处理 POST、PUT 等请求,接收客户端JSON 数据传递的数据。
Service实现类
/**
* 启用禁用员工账号
* @param status
* @param id
*/
@Override
public void startOrStop(Integer status, Long id) {
//update employee set staus= ? where id= ?
Employee employee = new Employee();
employee.setStatus(status);
employee.setId(id);
employeeMapper.update(employee);
}
Mapper中的XML
因为只需要改status值即可,其实可以只写那一句status的标签但为了后续功能开发方便代码复用,所以全部判断并更新一遍。
<update id="update" parameterType="Employee">
update employee
<set>
<if test="name != null">name = #{name},</if>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="sex != null">sex = #{sex},</if>
<if test="idNumber != null">id_number = #{idNumber},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateUser != null">update_user = #{updateUser},</if>
<if test="status != null">status = #{status},</if>
</set>
where id=#{id}
</update>
在where中#{id} 中的 id 是指 Employee 对象中的属性,表示通过参数传递进来的 Employee 对象中的 id属性的值。具体的传递过程是在调用这个更新操作的 Java 代码中,通过传递一个包含 id 属性的 Employee 对象,将 id的值传递给 SQL 语句。
根据id查询用户信息
此接口设计data中信息太多,实际上要根据id查询并回显用户信息仅用EmployeeDTO即可,不需要使用Employee可能还可以防止数据泄露提高安全性。
Controller层
/**
* 根据id查询员工信息
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询员工信息")
public Result<EmployeeDTO> getById(@PathVariable Long id){
EmployeeDTO employeeDTO=employeeService.getById(id);
return Result.success(employeeDTO);
}
Service实现层
@Override
public EmployeeDTO getById(Long id) {
EmployeeDTO employeeDTO=employeeMapper.getById(id);
return employeeDTO;
}
Mapper层
@Select("select * from employee where id = #{id}")
EmployeeDTO getById(Long id);
编辑员工信息
Controller层
/**
* 编辑员工信息
* @param employeeDTO
* @return
*/
@PutMapping
@ApiOperation("编辑员工信息")
public Result update(@RequestBody EmployeeDTO employeeDTO){
log.info("编辑员工信息:{}",employeeDTO);
employeeService.update(employeeDTO);
return Result.success();
}
Servcie层
/**
* 编辑员工信息
* @param employeeDTO
*/
@Override
public void update(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
//属性拷贝将DTO的属性赋值给employee对象
BeanUtils.copyProperties(employeeDTO, employee);
employee.setUpdateTime(LocalDateTime.now());
employee.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.update(employee);
}
剩余按照项目提供的代码导入。