SpringBoot 统一功能处理

一.拦截器

1.1 介绍

拦截器是Spring框架提供的核心功能之一,主要用于拦截用户的请求,根据业务需要执行预先设定的代码,可以在用户的请求响应前后执行,也可以在用户请求前阻止其执行

1.2 拦截器的使用

拦截器的使用步骤分为两步:定义拦截器和注册配置拦截器

  1. 定义拦截器
  • preHandle()方法:目标方法执行前执行,返回true则继续执行后续操作,返回false则中端后续操作
  • postHandle()方法:目标方法执行后执行
  • afterCompletion()方法:视图渲染完毕后执行,最后执行(不常用)
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 在目标方法前执行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 具体代码实现
    }

    /**
     * 在目标方法执行后执行
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 具体代码实现
    }

    /**
     * 视图渲染完毕后执行(最后执行)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 具体代码实现
    }
}
  1. 注册配置拦截器
  • addPathPatterns()方法:对指定请求进行拦截
  • excludePathPatterns()方法:对指定请求不进行拦截
  • 拦截路径:/*表示拦截一级路径,如/user,/book,不能拦截多级路径,如/user/login,/**表示拦截任意级路径(即一级或多级路径),同理/user/*表示拦截/user路径下的一级路径,/user/**表示拦截/user下的任意级路径
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Component
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/**");
    }
}

1.3 拦截器的执行流程

  1. 添加拦截器方法后,执行Controller的方法之前,请求会先被拦截器拦截住,执行preHandle()方法,如果返回true则放行本次操作,继续访问controller层的方法,如果返回false则不会放行,即不会执行controller层的方法
  2. Controller层的方法执行完毕后,再回来执行postHandle()这个方法以及afterCompletion()方法,执行完毕之后,最终给浏览器相应数据
    在这里插入图片描述

1.4 适配器模式

适配器模式,也叫包装器模式,指将一个类的接口转换成符合需求的另一个接口,简单来说就是目标类不能直接使用,需要通过一个新的类进行包装,从而适配调用方的调用,把两个不兼容的接口通过一定的方式转变为兼容。在日常生活中,适配器模式也是非常常见,比如转换插头,网络转接头等。在适配器模式中,分别有四类角色:

  • Target:目标接口(可以是抽象类或接口)
  • Adaptee:适配者,与Target不兼容
  • Adapter:适配器类,适配器模式的核心,通过继承或引用适配者的对象,把适配者转为目标接口
  • client:需要使用适配器的对象
// 适配器模式的简单举例
// slf4j提供了一系列用于打印日志的Api,底层调用log4j或logback来打印日志,调用者只需调用slf4j的Api就可以打印日志
//目标接口Target
public interface Slf4jApi {
    void log(String message);
}

//适配者Adaptee
public class Log4j {
    void log4jLog(String message){
        System.out.println("log4j:" + message);
    }
}

//适配器类Adapter
public class Slf4jLog4jAdapter implements Slf4jApi{

    private Log4j log4j;
    
    public Slf4jLog4jAdapter(Log4j log4j){
        this.log4j = log4j;
    }

    @Override
    public void log(String message) {
        log4j.log4jLog(message);
    }
}

//使用适配器的对象client
public class client {
    public static void main(String[] args) {
        Slf4jApi slf4jApi = new Slf4jLog4jAdapter(new Log4j());
        slf4jApi.log("日志打印");
    }
}

二.统一数据返回格式

2.1 介绍

在实际的业务环境中,如果后端每一个接口返回的数据格式都大不相同,那么在前端处理起来会变得非常麻烦,因而需要对数据返回格式进行统一的处理,方便前端人员对相关数据的获取,Spring提供了使用@ControllerAdvice注解和ResponseBodyAdvice来返回统一数据格式

2.2 统一数据返回格式的使用

  • supports()方法:判断是否要执行beforeBodyWrite方法,为true则执行,为false则不执行,通过该方法可以选择哪些类或者哪些方法的response要进行处理,其他的不进行处理
  • beforeBodyWrite()方法:对response方法进行具体操作处理
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        return body; //返回值可以自己定义实现
    }
}

2.3 优点

  1. 方便前端人员更好接收和解析后端数据接口返回的数据
  2. 降低前端人员和后端人员的沟通成本,确定好返回数据的具体格式即可
  3. 有利于项目统一数据的维护和修改
  4. 有利于后端技术部门的统一规范的标准制定,不会出现乱七八糟的返回内容

三.统一异常处理

3.1 介绍

在日常写代码过程中,有的程序会因为某些原因抛出异常,而这些异常一般都是利用try,catch的方式处理异常或者throw,throws的方式抛出异常不管,如果每一个可能抛出异常的地方都要编写重复的代码,处理起来可能相对比较麻烦,这时如果不想过多的自己去处理各种异常编写重复的代码,统一异常处理就变得很重要,很便捷。在Spring中,可以集中定义全局异常处理器类,使用@ControllerAdvice注解和@ExceptionHandler注解统一捕获和处理所有 Controller 中可能抛出的异常

3.2 统一异常处理的使用

以下只是对统一异常处理的简单示例,通常可以在统一数据返回结果添加异常信息的对应属性,将全局捕获的异常设置到异常信息属性中,更好观察后端的具体返回结果。统一异常捕获的匹配顺序为当前类以及其子类向上依次匹配,所以抛出的空指针异常等会先被针对这些异常进行处理的handler捕获,而不会先被处理异常类Exception的handler捕获。针对不同的异常类型,可以运用不同的处理方式。
注:如果返回的数据是json数据,那么需要添加注解@ResponseBody,或者把@ControllerAdvice换为@RestControllerAdvice(综合了@ResponseBody和@ControllerAdvice)

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
@Slf4j
public class ExceptionAdvice {

    @ExceptionHandler
    public String handler(Exception e){
        log.error("发生异常:", e);
        // 返回值可以设置到统一数据返回结果的异常信息属性中
        return e.getMessage();
    }

    // 可以针对不同异常进行特殊的处理
    @ExceptionHandler
    public String handler(NullPointerException e){
        log.error("发生空指针异常:", e);
        return e.getMessage();
    }
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值