• 【springBoot】统一功能处理


    拦截器

    拦截器的实现

    1. 定义拦截器
    2. 把拦截器注册到项目中

    定义拦截器:

    @Component
    @Slf4j
    public class LoginInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("登录拦截器校验...");
            //返回true表示放行, 返回false 表示拦截
            HttpSession session = request.getSession();
            UserInfo userInfo = (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);
            if (userInfo!=null && userInfo.getId()>=0){
                return true;
            }
            response.setStatus(401);
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("目标方法执行后");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    注册拦截器:

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Autowired
        private LoginInterceptor loginInterceptor;
        private static List<String> excludePath = Arrays.asList("/user/login",
            "/css/**",
            "/js/**",
            "/pic/**",
            "/**/*.html",
            "/test/**");
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(loginInterceptor)
                    .addPathPatterns("/**") // /** 表示所有方法添加拦截器
                    .excludePathPatterns(excludePath);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    拦截路径含义举例
    /*⼀级路径能匹配/user,/book,/login,不能匹配/user/login
    /**任意级路径能匹配/user,/user/login,/user/reg
    /book/*/book下的⼀级路径能匹配/book/addBook,不能匹配/book/addBook/1,/book
    /book/**/book下的任意级路径能匹配/book,/book/addBook,/book/addBook/2,不能匹 配/user/login

    统一数据格式返回

    返回数据的格式:

    @Data
    public class Result {
        /**
         * 业务状态码
         */
        private ResultCode code;  //0-成功  -1 失败  -2 未登录
        /**
         * 错误信息
         */
        private String errMsg;
        /**
         * 数据
         */
        private T data;
    
        public static  Result success(T data){
            Result result = new Result();
            result.setCode(ResultCode.SUCCESS);
            result.setErrMsg("");
            result.setData(data);
            return result;
        }
        public static  Result fail(String errMsg){
            Result result = new Result();
            result.setCode(ResultCode.FAIL);
            result.setErrMsg(errMsg);
            result.setData(null);
            return result;
        }
        public static  Result fail(String errMsg,Object data){
            Result result = new Result();
            result.setCode(ResultCode.FAIL);
            result.setErrMsg(errMsg);
            result.setData(data);
            return result;
        }
        public static  Result unlogin(){
            Result result = new Result();
            result.setCode(ResultCode.UNLOGIN);
            result.setErrMsg("用户未登录");
            result.setData(null);
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    统一数据格式封装:

    1. 创建一个类,并添加@ControllerAdvice
    2. 实现ResponseBodyAdvice接口,并重写supports和beforelBodyWrite(统一对象就是此方法中实现的)
    /**
     * 实现统一数据返回的保底类
     * 说明:在返回数据之前,检测数据的类型是否为统一的对象,如果不是,封装成统一的对象
     */
    @ControllerAdvice
    public class ResponseAdvice implements ResponseBodyAdvice {
        /**
         * 开关,如果是true才会调用beforeBodyWrite
         */
        @Override
        public boolean supports(MethodParameter returnType, Class converterType) {
            return true;
        }
        /**
         * 对数据格式进行效验和封装
         */
        @Autowired
        private ObjectMapper objectMapper;
        @SneakyThrows//异常抛出,相当于方法上throw一个异常
        @Override
        public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
            //进行了统一对象的封装,直接返回body
            if (body instanceof Result){
                return body;
            }
            //字符串类型特殊处理。手动对其进行ajax类型的转化
            if (body instanceof String){
                return objectMapper.writeValueAsString(Result.success(body));
            }
            //未进行封装的对其进行统一封装
            return Result.success(body);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    统一异常处理

    异常统一封装:

    1. 创建一个类,并在类上标识@ControllerAdvice
    2. 添加方法@ExceptionHandler来订阅异常

    @ResponseBody,如果你在统一异常处理中没有使用@ResponseBody注解,并且返回的结果是一个普通的Java对象而不是响应体,可能会导致控制台循环输出的问题。这通常是因为Spring Boot尝试使用默认的ExceptionResolver去处理异常时,发现无法序列化返回的对象,而进入循环。

    @ResponseBody
    @Slf4j
    @ControllerAdvice
    public class ErrorHandler {
        @ExceptionHandler
        public Result excption(NullPointerException e){
            log.error("发生异常,e:{}",e);
            return Result.fail("NullPointerException异常,请联系管理员");
        }
        @ExceptionHandler
        public Result excption(ArithmeticException e){
            log.error("发生异常,e:{}",e);
            return Result.fail("ArithmeticException异常,请联系管理员");
        }
        @ExceptionHandler
        public Result excption(Exception e){
            log.error("发生异常,e:{}",e);
            return Result.fail("Exception异常,请联系管理员");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    如果后端返回的结果是String类型,当我们使用统一结果返回时,返回的是JSON字符串
    conten-type是text/html,我们需要把他转为JSON
    如果后端进行转换:

    @RequestMapping(value = "/addBook", produces = "application/json")
    
    • 1

    produces = "application/json"表示HTTP响应的数据类型是application/json

  • 相关阅读:
    spring-boot-starter-data-redis 引发的一系列惨案
    C#调用C++类,托管C++方式实现(创建C++ CLR dll项目)
    18.示例程序(编码器接口测速)
    分布式通过tcp控制开关
    使用WIX 进行商业智能OEM打包
    day03-搭建微服务基础环境02
    JavaScript面向对象:面向对象案例
    PerfView专题 (第十一篇):使用 Diff 功能洞察 C# 内存泄漏增量
    Qt编写ffmpeg本地摄像头显示(16路本地摄像头占用3.2%CPU)
    APM32F103VCT6 写内部Flash失败解决方案(亲试可用)
  • 原文地址:https://blog.csdn.net/weixin_66409969/article/details/136238698