SpringBoot统一功能处理

本文详细介绍了Spring框架中的拦截器如何实现登录验证,DispatcherServlet的工作原理,以及适配器模式的应用。还探讨了如何统一数据返回格式和处理异常,如使用@ControllerAdvice和ResponseBodyAdvice进行控制和转换。
摘要由CSDN通过智能技术生成

目录

 

一.拦截器

拦截器的实现

拦截器的定义

注册拦截器

登录校验

二.DispatcherServlet源码分析

​编辑适配器

适配器模式

三.统一数据返回格式

​编辑

四.统一异常处理


一.拦截器

拦截器是Spring框架提供的核心功能之一,在指定方法前后,根据业务需要执行预先设定的代码。

按照图书管理系统举例子:

登录验证

指定方法:我们登录验证后可以执行的某些方法(图书的增删改查)

预先设定的代码:对用户是否登录进行验证

再举例:去银行办理业务,办理业务前后,都会有一些工作,我们可以把业务前后的这些工作视为拦截工作。办理业务前,拦截器做的工作是取号(带身份证取号);办理业务后,拦截工作则是进行服务评价。

拦截器的实现

拦截器的实现分为两步

1.定义一个拦截器

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

拦截器的定义

我们自己写的拦截器的类要继承HanderInterceptor这个类,并且重写这个类中自带的两个方法。

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("目标方法执行前");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
   log.info("目标方法执行后");
    }
}

注册拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器
        //**表示给所有方法添加拦截器
         registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("");//排除不进行拦截的
    }
}

继承的WebMvcConfigurer类中有添加拦截器的方法addInterceptors

测试拦截器的效果

登录校验

通过拦截器完成图书管理系统中的最后一步操作:通过拦截器完成图书管理系统中的登录校验功能。

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器
        //**表示给所有方法添加拦截器
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login");//排除不进行拦截的

    }
}

把controller中的注册注释掉

拦截器内的工作内容

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;
            //401表示未认证登录
        }

        @Override
        public void postHandle (HttpServletRequest request, HttpServletResponse response, Object
        handler, @Nullable ModelAndView modelAndView) throws Exception {
            log.info("目标方法执行后");
        }
    }

以上拦截器只是排除拦截的后端的注册登录代码,这个时候拦截器拦截住了前端页面,此时我们还需要排除前端页面的代码。将所有的前端页面内容放入一个队列中,然后直接排除掉这个队列。

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    private static List<String> excludePath = Arrays.asList("/user/login",
            "/css/**",
            "/js/**",
            "/pic/**",
            "/**/*.html");
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器
        //**表示给所有方法添加拦截器
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")//表示给所有方法都添加拦截器
                .excludePathPatterns(excludePath);

    }
}

二.DispatcherServlet源码分析

当Tomcat启动时,有一个核心的类DispatcherServlet来控制程序进行的顺序,如果有拦截器则会先执行拦截器的内容。

Ctrl+N搜索DispatcherServlet这个类

阅读源码的流程

拦截器的执行流程

适配器

适配器模式, 也叫包装器模式. 简单来说就是目标类不能直接使用, 通过⼀个新类进行包装⼀下, 适配调用方使用. 把两个不兼容的接口通过⼀定的方式使之兼容。

适配器模式

举例:

一般来说,适配器模式可以看做一种“补偿模式”来补救设计上的缺陷,应用这种模式是“无奈之举”。所以适配器模式更多的应用场景是对正在运行的代码进行改造,并且希望可以复用原有代码实现新的功能,比如版本升级等。

三.统一数据返回格式

统一数据返回格式使用@ControllerAdvice和ResponseBodyAdvice(继承的类)

@ControllerAdvice表示控制器通知类

对于图书管理系统,添加类 ResponseAdvice , 实现 ResponseBodyAdvice 接口 , 并在类上添加
@ControllerAdvice 注解
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        //重写的support方法中,返回改为true
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //在返回前要做的事情
        return Result.success(body);
    }
}

但是在测试中会出现两个问题:

1.请求返回类型为Result时,结果会出现嵌套(有重复出现的部分),不需要再进行处理了。

2.返回结果为String时,不能正确进行处理。

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Autowired
    private ObjectMapper objectMapper;
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        //重写的support方法中,返回改为true
        return true;
    }

    @SneakyThrows 
    //下面body转换成String的方法,idea给的解决异常的方法(相当于添加的try...catch语句)
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //在返回前要做的事情
        if (body instanceof Result){
            return body;
        }
        if(body instanceof String){
            return objectMapper.writeValueAsString(Result.success(body));
        }
        return Result.success(body);
    }
}

四.统一异常处理

对统一结果处理的代码进行调整统⼀异常处理使用的是 @ControllerAdvice + @ExceptionHandler 来实现的, @ControllerAdvice 表示控制器通知类, @ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执行某个通知,也就是执行某个方法事件。添加@ResponseBody返回数据(不添加表示返回页面)。

@ResponseBody//结果返回数据
@Slf4j
@ControllerAdvice
public class ErrorHandler {
    @ExceptionHandler
    public Result exception(Exception e){
        log.error("发生异常,e:{}",e);
        return Result.fail("内部错误");
    }
    @ExceptionHandler
    public Result exception(NullPointerException e){
        log.error("发生异常,e:{}",e);
        return Result.fail("NullPointerException异常,请联系管理员");
    }
    @ExceptionHandler
    public Result exception(ArithmeticException e){
        log.error("发生异常,e:{}",e);
        return Result.fail("ArithmeticException异常");
    }
}

当有多个异常通知时,匹配顺序为当前类及其子类向上依次匹配。
  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Roylelele

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值