Spring Boot 统一功能处理

本篇学习Spring Boot 统一功能处理的案例,主要学习三个目标:统⼀⽤户登录权限验证; 统⼀数据格式返回;统⼀异常处理。


spring boot统一功能处理,是 AOP 的实战环节
分为三个目标:

  1. 统⼀用户登录权限验证;
  2. 统⼀数据格式返回;
  3. 统⼀异常处理。

用户的登录权限校验

spring Boot拦截器实现

1.自定义拦截器

创建一个普通的拦截器,实现HandlerInterceptor接口,并重写接口中的相关方法

代码如下:

public class LoginInterceptor implements HandlerInterceptor {//继承HandlerInterceptor
    //调用目标方法之前执行的方法
    //此方法发布会boolean类型的值:
    //      如果返回True,表示拦截器验证成功,继续走后续的流程,执行目标方法
    //      如果返回false,表示拦截器执行失败,验证不通过,后续流程和目标方法不执行了
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //用户登录判断业务
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("seesion_userinfo") != null){
            return true;
        }
        response.setStatus(401);
        return false;
    }
}

在这里插入图片描述

2.将自定义拦截器配置到系统配置项,并且设置合理的拦截规则

代码执行:

@Configuration
public class MyConfig implements WebMvcConfigurer {//继承 WebMvcConfigurer
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {//重写 addInterceptors
        //registry.addInterceptor(new LoginInterceptor());
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")//拦截所有的url
                .excludePathPatterns("/user/login")//排除url /user/login 不拦截的
                .excludePathPatterns("/user/reg");//排除注册
                .addPathPatterns("/**") // 拦截所有接⼝
 				.excludePathPatterns("/**/*.js")
 				.excludePathPatterns("/**/*.css")
 				.excludePathPatterns("/**/*.jpg")
 				.excludePathPatterns("/login.html")
 				.excludePathPatterns("/**/login"); // 排除接⼝
    }
}

在这里插入图片描述
排除所有的静态资源

拦截器实现原理

标准流程:

在这里插入图片描述
加入拦截器:
在这里插入图片描述

源码实现分析

出在开始执行 Controller 之前,会先调用预处理方法applyPreHandle,而applyPreHandle 方法的实现源码在 applyPreHandle 中会获取所有的拦截器 HandlerInterceptor 并执行拦截器中的 preHandle 方法中。
拿到所有拦截器,如果return 则false

springBoot 的拦截器是基于spring mvc框架的拦截器机制,当客户端发送请求,请求会经过一系列组件处理,包括拦截器。

统一访问添加前缀

在所有请求地址添加api前缀:

@Configuration
public class AppConfig implements WebMvcConfigurer {
 	// 所有的接⼝添加 api 前缀
 	@Override
 	public void configurePathMatch(PathMatchConfigurer configurer) {
 		configurer.addPathPrefix("api", c -> true);
 	}
}

其中第二个参数是⼀个表达式,设置为 true 表示启动前缀。

统一的异常处理

统⼀异常处理使用的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执⾏某个通知,也就是执行某个方法事件

分为两步:
1.建一个统一异常的处理类
添加注解@ControllerAdvice

代码:

@ControllerAdvice//监控所有类的异常
@ResponseBody//返回的页面为json格式
public class MyExceptionAdvice {
    /*只能处理空指针异常*/
    @ExceptionHandler(NullPointerException.class)//监控所有类的空指针异常
    public HashMap<String,Object> doNullPointerException(NullPointerException e){
        HashMap<String,Object> result = new HashMap<>();
        result.put("code",-1);
        result.put("mag","空指针"+e.getMessage());
        result.put("data",null);
        return result;
    }

    /*默认的异常处理,当没有匹配到时,会执行此方法*/
    @ExceptionHandler(NullPointerException.class)//监控所有类的异常
    public HashMap<String,Object> doException(Exception e){
        HashMap<String,Object> result = new HashMap<>();
        result.put("code",-1);
        result.put("mag","空指针"+e.getMessage());
        result.put("data",null);
        return result;
    }
}

2.创建异常检测类和处理业务方法

在这里插入图片描述

统一数据返回格式

统⼀数据返回格式的优点有很多,比如以下几个:

  1. 方便前端程序员更好的接收和解析后端数据接口返回的数据。
  2. 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就行了,因为所有接口都是这样返回的。
  3. 有利于项目统⼀数据的维护和修改。
  4. 有利于后端技术部⻔的统⼀规范的标准制定,不会出现稀奇古怪的返回内容

统⼀数据返回格式的实现

统⼀的数据返回格式可以使用@ControllerAdvice + ResponseBodyAdvice 的方式实现,具体实现代码如下

返回之前判断,为true说明返回数据前进行处理

统一数据返回(强制性统一数据返回),会在返回数据之前进行数据重写
代码:
添加@ControllerAdvice 注解,实现ResponseBodyAdvice 并且重写方法。

/*统一数据处理*/
@ControllerAdvice//
public class ResponseAdvice  implements ResponseBodyAdvice {
    /*是否执行beforeBodyWrite方法,true代表执行,重写返回结果*/
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    /*返回数据之前进行数据重写
    * body原始的返回值*/
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //HashMap<String,Object> ->code,msg,data
        if (body instanceof HashMap){//instanceof判断数据类型是否相同
            return body;//相同返回
        }
        //重写返回结果,让其返回一个统一的结果
        HashMap<String,Object> result = new HashMap<>();
        result.put("code",200);
        result.put("data",body);
        result.put("msg","");
        return request;
    }
}

统一异常处理在遇到String返回时报错的问题

在这里插入图片描述
流程执行:

  1. 方法返回的时String
  2. 统一数据返回之前处理 -> String 转换成 HashMap
  3. 将HashMap抓换成application或者json字符串给前端(接口)

判断原Body的类型:

  1. 是String类型-> StringHttpMessageConverter进行类型转换(无法转换HashMap)
  2. 不是String类型-> HttpMessageConverter进行类型转换

解决方案:
1.将StringHttpMessageconverter去掉
新建一个类为系统配置类,在里面代码:

@Configuration
public class MyConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.removeIf(converter -> converter instanceof StringHttpMessageConverter);
    }
}

2.在统一数据重写时单独处理String,让其返回一个String,而非HashMa

注入json处理工具
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值