目录
SpringBoot 统一功能处理概念
统一用户登录权限验证
登录功能代码
Spring拦截器实现步骤:
统一项目访问前缀
第一种方法:重写configurePathMatch方法进行配置
第二种方法:在系统的配置文件.properties中进行配置
统一异常处理返回
统一数据格式返回
SpringBoot 统一功能处理就是AOP思想的实战环节,接下来就开始讲解SpringBoot 统一功能实战处理了。
SpringBoot 统一功能实现主要是实现以下功能:
1、统一用户登录权限验证(使用拦截器实现)
2、统一数据格式返回
3、统一异常处理返回
在原来进行用户登录权限验证时 ,需要在每一个方法体中进行登录方法的验证,代码十分的麻烦。于是就出现了Spring AOP思想,可以进行统一登录权限验证,但是原生Spring AOP实现统一拦截的难点就在于:
1、定义拦截的规则(表达式)非常难;
2、在切面类中拿到HttpSession比较难。
因此在该背景下于是就出现了Spring拦截器。
@RequestMapping("/hi")
@RestController
public class controller {
@RequestMapping("/getLogin")
public String Login(){
System.out.println("执行了login~~");
return "login~~";
}
@RequestMapping("/getUser")
public String User(){
System.out.println("执行了user~~");
return "user~~";
}
@RequestMapping("/getReg")
public String reg(){
System.out.println("执行了reg~~");
return "reg~~";
}
}
1、实现HandlerInterceptor接口并且重写preHeadler方法,在方法中编写自己的业务代码
public class LoginInter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 用户登录效验
HttpSession session = request .getSession(false);
if(session != null && session.getAttribute("userInfo") != null){
// 说明用户已经登录
return true;
}
// 执行到这里说明用户未登录,既可以设置跳转到登录界面进行重新登录
response.sendRedirect("/login.html");
return false;
}
}
2、将拦截器添加到配置文件中,并且设置拦截规则
1.添加注解:@Configuration
2.实现WebMvcConfigurer接口并重写addInterceptors方法
3.使用 addPathPatterns确定哪些需要拦截的方法,excludePathPatterns为不拦截哪些URL(**表示拦截所有的方法)
代码如下
@Configuration
public class config implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInter())
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/hi/getLogin") // 不拦截该请求URL
.excludePathPatterns("/hi/getReg") // 不拦截该请求URL
.excludePathPatterns("/**/*.html"); // 不拦截所有的html页面
}
}
以上代码未拦截URL为 "/hi/getLogin" 、"/hi/getReg"、"/**/*.html", 而是拦截了URL为"/hi/getUser",并且自动跳转到了登录界面login.html
不加拦截器效果
加了拦截器,会在调⽤ Controller 之前进⾏相应的业务处理,执⾏的流程如下图
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("hello",c->true);
}
# 配置统一访问前缀
server.servlet.context-path=/hello
配置后如果使用原来的URL就会报404错误,此时需要添加前缀/hello进行访问
当后端发生异常时,需要返回异常通知到前端,方便前端接收识别到异常并进行处理。因此就需要后端返回统一的异常提交给前端,否则前端会无法识别到后端返回的异常错误
示例:当后端发生空指针异常时
@RequestMapping("/login")
public String Login(){
int a = 100/0;
System.out.println("执行了login~~");
return "login~~";
}
此时我们需要返回一个统一的异常格式json给前端
步骤:
1.创建一个类,并在类上标明@ControllerAdvice
2.添加方法@ExceptionHandler来订阅异常
@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执行某个通知,执行某个方法事件
@ControllerAdvice
@ResponseBody
public class ErrorException {
@ExceptionHandler(Exception.class)
public HashMap exception(Exception e){
HashMap result = new HashMap<>();
result.put("code","-1"); // 状态码
result.put("emg",e.getMessage()); // 错误码描述信息
result.put("data",null);
return result;
}
}
统一数据格式返回可以更好的方便前端接收和解析后端返回的数据,可以大大加快工作效率
步骤:
1.在类上添加注解:@ControllerAdvice
2.实现接口ResponseBodyAdvice并且必须重写supports和beforeBodyWrite这两个方法
@ControllerAdvice
public class Advice implements ResponseBodyAdvice {
/*
*重写support和beforeBodyRead两个方法
* */
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true; // 返回true 则执行下面的beforeBodyWrite,否则不执行
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
HashMap map = new HashMap<>(); // 返回数据格式为哈希map格式
map.put("code",200); // 状态码
map.put("message","");
map.put("data",body);
return map;
}
}
后端返回给前端数据为数字和字符串形式
controller代码如下:
@RequestMapping("/num")
public Integer getNum(){
return new Random().nextInt(100); // 后端传递100以内的随机数字给前端
}
@RequestMapping("/char")
public String getString(){
return "hello,world"; //后端传递字符串"hello,world"给前端
}
后端传递数字给前端,结果正常显示
后端传递"hello,world"字符串给前端,结果错误显示
原因:HashMap 转换成字符串出现异常,因为字符串是一个特殊的类型,需要借助jakson的转换工具来进行HashMap 转换成字符串
添加jaskon代码如下:
if(body instanceof String){ // instanceof 为判断数据类型
try {
return objectMapper.writeValueAsString(map); // 将HashMap 转换成字符串类型
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
再次运行项目,此时后端将hello,world字符串就成功传递给前端了