SpringBoot统一功能处理

作者:~小明学编程 

文章专栏:Spring框架

格言:热爱编程的,终将被编程所厚爱。
在这里插入图片描述

目录

Spring AOP 统一登录验证

登录功能

Spring拦截器

将拦截器加入到系统配置中

统一访问前缀

统一异常处理

统一数据类型的返回


前面我们说了AOP的思想,而springboot的统一功能处理就是我们AOP的实战环节目标主要有三个

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

Spring AOP 统一登录验证

登录功能

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/login")
    public String getLogin() {
        return "login";
    }
    @RequestMapping("/reg")
    public String getReg() {
        return "Reg";
    }
    @RequestMapping("/user1")
    public String getUser() {
        return "user";
    }
}

Spring拦截器

现在我们想要对用户是否登录进行一个验证,然后就是首先配置我们的拦截器,定义我们的拦截规则。

想要实现一个普通的拦截器的话分为三步:

实现HandlerInterceptor的接口
重写preHand的方法
在方法中实现自己的逻辑
@Component
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 返回 true 表示拦截判断通过,可以访问后面的接口
     * 返回 false 表示拦截判断未通过,直接返回后面结果给前端
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //得到 HttpSession 对象
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("userinfo") != null) {
            //表示已经登录
            return true;
        }
        //如果未登录,然后就跳转到登陆页面
        response.sendRedirect("/login.html");
        return false;
    }
}

将拦截器加入到系统配置中

将拦截器加入到系统配置中也是分为三个步骤:

  1. 实现WebMvcConfigurer接口。
  2. 重写addInterceptors方法。
  3. 确定我们要拦截哪些请求和排除哪些请求。
@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginIntercept;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginIntercept)
                .addPathPatterns("/**")//拦截所有的请求
                .excludePathPatterns("/user/login")//排除哪些请求不拦截
                .excludePathPatterns("/user/reg")
                .excludePathPatterns("/**/*.html");

    }
}

SpringBoot统一功能处理_第1张图片

SpringBoot统一功能处理_第2张图片

不加拦截器:

SpringBoot统一功能处理_第3张图片

 加了拦截器:

SpringBoot统一功能处理_第4张图片

统一访问前缀

有以下两种方式来实现请求地址添加 api 前缀:

第一种是通过重写我们的configurePathMatch方法

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("api",c->true);
    }

第二种是直接在我们的配置文件中去设置

SpringBoot统一功能处理_第5张图片

 可以看到这个时候想要访问某个地址就需要加上我们刚刚的前缀了。

统一异常处理

如下代码当我们的程序在处理逻辑的时候如果出现异常该怎么办呢?

    @RequestMapping("/login")
    public String getLogin() {
        int a = 10/0;
        return "login";
    }

SpringBoot统一功能处理_第6张图片

此时我们可以看到前端是这个样子的,这显然不是我们想要看到的,我们前端想要的只是一个json数据,所以我们就要对这些异常进行进行统一的处理。

步骤:

  • 给类上面加一个 @ControllerAdvice / @RestControllerAdvice 注解,相当于是对 controller 方法的增强。
  • 给方法上加一个 @ExceptionHandler 注解,但是后面要带参数,表示要处理异常的类型。然后添加异常返回的业务代码就好了。
     

代码:

@ControllerAdvice
@ResponseBody
public class MyExHandler {
    @ExceptionHandler(ArithmeticException.class)
    public HashMap arithmeticException(ArithmeticException e) {
        HashMap hashMap = new HashMap<>();
        hashMap.put("state",-1);
        hashMap.put("msg",e.getMessage());
        hashMap.put("date",null);
        return hashMap;
    }
}

SpringBoot统一功能处理_第7张图片

 处理多种异常:

    @ExceptionHandler(Exception.class)
    public HashMap exception(Exception e) {
        HashMap hashMap = new HashMap<>();
        hashMap.put("state",-1);
        hashMap.put("msg",e.getMessage());
        hashMap.put("date",null);
        return hashMap;
    }

我们直接写上所有异常的父类就可以处理所有异常了,但是写了子类的时候子类的优先级最高。

统一数据类型的返回

我们前后端交互的时候最重要的就是前后端返回的数据格式,这就体现到了我们统一数据类型返回的重要性了,我们需要将我们返回的数据类型给统一起来。

实现步骤:

  • 添加 @ControllerAdvice 注解。
  • 实现 ResponseBodyAdvice 接口,并且重写里面的方法。必须重写 里面的 supports 和 beforeBodyWrite 方法。
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        HashMap hashMap = new HashMap<>();
        hashMap.put("code",200);
        hashMap.put("msg","");
        hashMap.put("date",body);
        return hashMap;
    }

    //用来控制我们的拦截开关
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
}

controller:

    @RequestMapping("/user1")
    public String getUser() {
        return "user";
    }
    @RequestMapping("/getnum")
    public Integer getNum() {
        return new Random().nextInt(10);
    }

SpringBoot统一功能处理_第8张图片

 这个时候我们可以看到返回了我们想要的数据格式。

这个时候我们又发现了问题,报错信息是我们的hashmap在转换成String的时候出现了问题。

这是因为我们的String类型的转换方式与其它的类型不一样,String类型有着其独特的转换方式,这个时候我们需要借助其它的工具来实现。

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Autowired
    private ObjectMapper objectMapper;
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        HashMap hashMap = new HashMap<>();
        hashMap.put("code",200);
        hashMap.put("msg","");
        hashMap.put("date",body);
        if (body instanceof String) {
            try {
                return objectMapper.writeValueAsString(hashMap);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return hashMap;
    }

    //用来控制我们的拦截开关
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
}

如上述所示,我们用jakson这个工具对其类型进行一个转换就解决了。

SpringBoot统一功能处理_第9张图片

 

你可能感兴趣的:(spring框架,spring,boot,java,spring)