紧接着上一篇博客,现在我们开始测试我们的菜单展示功能。本篇博客主要实现职位、职称管理。
目录
- 1.测试
- 2.职位管理
- 2.1.实现功能
- 2.2.测试
- 2.3.定义全局异常
- 3.职称管理
- 3.1.实现功能
- 3.2.测试
1.1.菜单展示测试
重启项目,打开8081端口。跟着步骤点击发送。根据代码逻辑第一次查询会从数据库中查询,之后每一次查询菜单就在Redis(服务器开启状态下)中查询。
首先先看使用了Redis的效果:
这是文档给个数据:
而且Redis里也有我们设置的menu_1
后端控制台也是显示了运行了SQL语句,说明这是从数据库中获取的。
那我们再一次点击发送,看看结果:
第二查询并非时查询菜单的SQL语句,而是登录时所用的SQL查询,说明这次是从Redis中获取菜单数据。
前面也提到过,这个项目的菜单不是很多,而且我的Redis安装在虚拟机中,每次需要手动开启虚拟机,考虑到如果一次性打开过多软件我的电脑可能会奔溃,所以后面我将不会启动Redis,还是直接从数据库中查询,因为Redis服务没开启会报RedisConnectionFailureException异常,索性我直接捕获,跳过Redis。但是如果使用我下面的代码,运行速度就会受到影响,暂时还没有更好改进方法,所以根据自己需求选择代码。当然有更好的处理方式也可自行解决。
IMenuServiceImpl.java
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
@Resource
private MenuMapper menuMapper;
@Resource
private RedisTemplate redisTemplate;
/**
* 通过用户ID查询菜单列表
*
* @return
*/
@Override
public List<Menu> getMenusByAdminId() {
Integer adminId = AdminUtils.getCurrentAdmin().getId();
// 如果Redis未开启服务,会报RedisConnectionFailureException,那么我们就直接从数据库中获取
try {
ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
// 从redis获取菜单数据
List<Menu> menus = (List<Menu>) opsForValue.get("menu_" + adminId);
// 如果为空,就去数据库中获取
if (CollectionUtils.isEmpty(menus)) {
menus = menuMapper.getMenusByAdminId(adminId);
// 将数据设置到redis中
opsForValue.set("menu_" + adminId, menus);
}
return menus;
} catch (RedisConnectionFailureException e) {
List<Menu> menus = menuMapper.getMenusByAdminId(adminId);
return menus;
}
}
}
1.2.权限测试
编写测试类,通过SQL语句查询到我们的admin用户只能查询到基本资料,高级资料无法查到,
那我们使用admin用户测试能否访问到这两个路径
@GetMapping("/employee/basic/hello")
public String test2(){
return "/employee/basic/hello";
}
@GetMapping("/employee/advanced/hello")
public String test3(){
return "/employee/advanced/hello";
}
test2结果:
test3结果:
权限管理和菜单展示功能完成。
职位管理功能实现起来就比较简单,就是一般的CRUD。
注意点:
- 进行展示创建时间的时候只需展示年月日
- 前缀必须和数据库中对应/system/basic/pos
2.1.1.自定义日期格式
在component目录下新建日期转换类
DateConverter.java
@Component
public class DateConverter implements Converter<String, LocalDate> {
@Override
public LocalDate convert(String s) {
try {
return LocalDate.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd").withLocale(Locale.CHINA));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
修改职位实体类
Position.java
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_position")
@ApiModel(value="Position对象", description="")
public class Position implements Serializable {
......
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
private LocalDateTime createDate;
@ApiModelProperty(value = "是否启用")
private Boolean enabled;
}
2.1.2.编写控制层
PositionController.java
@RestController
@RequestMapping("/system/basic/pos")
public class PositionController {
@Resource
private IPositionService positionService;
@ApiOperation(value = "获取所有职位信息")
@GetMapping("/")
public List<Position> getAllPositions() {
return positionService.list();
}
@ApiOperation(value = "添加职位信息")
@PostMapping("/")
public RespBean addPosition(@RequestBody Position position) {
position.setCreateDate(LocalDateTime.now());
if (positionService.save(position)) {
return RespBean.success("添加成功");
}
return RespBean.error("添加失败");
}
@ApiOperation(value = "更新职位信息")
@PutMapping("/")
public RespBean updatePosition(@RequestBody Position position) {
if (positionService.updateById(position)) {
return RespBean.success("更新成功!");
}
return RespBean.error("更新失败。");
}
@ApiOperation(value = "删除职位信息")
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public RespBean deletePosition(@PathVariable Integer id) {
if (positionService.removeById(id)) {
return RespBean.success("删除成功");
}
return RespBean.error("删除失败");
}
@ApiOperation(value = "批量删除职位信息")
@DeleteMapping("/")
public RespBean deletePositionByIds(Integer[] ids) {
if (positionService.removeByIds(Arrays.asList(ids))) {
return RespBean.success("删除成功");
}
return RespBean.error("删除失败");
}
}
添加职位功能
点击发送
测试前的t_position:
测试后的t_position:
更新职位功能
删除职位功能
当我们删除技术总监的时候:
我们看看后台情况:
翻译过来就是无法删除或更新父行:外键约束失败
对于程序员来讲这样的响应内容用来定位bug的确没什么问题,但是对于用户来说是不可取,我们应该给用户一个友好的提示信息。当然我们的程序可能不止这一个异常或者用户的误操作,为了把这些异常或者错误收集到一起处理,我们需要定义一个全局异常处理的方法。
处理全局异常方法:
- @ControllerAdvice和@ExceptionHandler注解
- ErrorController类
前者只能处理控制器抛出的异常,后者能处理所以异常,包括还没进入控制器的错误(404,401…),但是我们在项目中一般两者都会使用到,通过我们的@ControllerAdvice方式去处理我们控制器抛出的异常,通过ErrorController类处理未进入控制器的异常,所以他们并不是只能二选一,是能够二选一的。@ControllerAdvice可以定义多个拦截方法,拦截不同的异常类,并且可以获取抛出的异常信息。
新建Exception目录,创建全局异常处理类
GlobalException.java
@RestControllerAdvice
public class GlobalException {
@ExceptionHandler(SQLException.class)
public RespBean mySqlException(SQLException e) {
if (e instanceof SQLIntegrityConstraintViolationException) {
return RespBean.error("该数据有关联数据,操作失败");
}
return RespBean.error("数据库异常,操作失败");
}
}
与职位管理功能差不多,步骤基本差不多所以直接上代码。
3.1.1.自定义日期格式
修改职称实体类
Joblevel.java
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_joblevel")
@ApiModel(value="Joblevel对象", description="")
public class Joblevel implements Serializable {
......
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
private LocalDateTime createDate;
@ApiModelProperty(value = "是否启用")
private Boolean enabled;
}
3.1.2.编写控制层
JoblevelController.java
@RestController
@RequestMapping("/system/basic/joblevel")
public class JoblevelController {
@Resource
private IJoblevelService joblevelService;
@ApiOperation(value = "获取所有职称")
@GetMapping("/")
public List<Joblevel> getAllJobLevels() {
return joblevelService.list();
}
@ApiOperation(value = "添加职称")
@PostMapping("/")
public RespBean addJobLevel(@RequestBody Joblevel joblevel) {
joblevel.setCreateDate(LocalDateTime.now());
if (joblevelService.save(joblevel)) {
return RespBean.success("添加成功");
}
return RespBean.error("添加失败");
}
@ApiOperation(value = "更新职称")
@PutMapping("/")
public RespBean updateJobLevel(@RequestBody Joblevel joblevel) {
if (joblevelService.updateById(joblevel)) {
return RespBean.success("更新成功!");
}
return RespBean.error("更新失败。");
}
@ApiOperation(value = "删除职称")
@DeleteMapping("/{id}")
public RespBean deleteJobLevel(@PathVariable Integer id) {
if (joblevelService.removeById(id)) {
return RespBean.success("删除成功");
}
return RespBean.error("删除失败");
}
@ApiOperation(value = "批量删除职称")
@DeleteMapping("/")
public RespBean deleteJobLevelByIds(Integer[] ids) {
if (joblevelService.removeByIds(Arrays.asList(ids))) {
return RespBean.success("删除成功");
}
return RespBean.error("删除失败");
}
}
这里我就只演示获取所有职称测试,其他自行测试,与职位管理测试不同的是,需要输入titleLevel
参考值:‘正高级’,‘副高级’,‘中级’,‘初级’,‘高级’,数据库已固定。
Spring Security 权限控制