SpringBoot最常用的统一功能的处理

同一功能的处理也就是Aop的练习,之前在Aop的切面中实现用户登录权限的校验,有两个问题:
1.无法获取HttpSession对象;
2.拦截的规则该怎样设置呢?拦截谁?不拦截谁?
以上的问题就可以通过拦截器来实现。

Spring拦截器的实现

1、自定义拦截器,需要实现HandlerInterceptor类,并重写preHandle方法,此方法参数有preHandle(HttpServletRequest request, HttpServletResponse response, Object handler),可以获取session;
2、将自定义的拦截器配置到项目中,实现WebMvcConfigurer类和类中的addInterceptors方法。

以下为具体示例:

一、用户登录权限校验

1.用户类

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
}

2.业务操作

package com.example.spring_aop_test.controller;

import com.example.spring_aop_test.model.UserInfo;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
@ResponseBody
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/reg")
    public boolean reg(){
        return true;
    }

    @RequestMapping("/getuser")
    public UserInfo getUser(){
        UserInfo userInfo=new UserInfo();
        userInfo.setId(1);
        userInfo.setUsername("张三");
        userInfo.setPassword("123");
        return userInfo;
    }

    @RequestMapping("/login")
    public boolean login(String username, String password, HttpServletRequest request){
        if(StringUtils.hasLength(username) && StringUtils.hasLength(password)){
            if(username.equals("admin") && password.equals("123")) {
                //登录成功,将会话信息存储
                HttpSession session = request.getSession(true);
                session.setAttribute("userInfo", new UserInfo(1, "admin", "123"));
                return true;
            }
        }
        return false;
    }
}


3.自定义登录拦截器

//登录拦截器
//1.实现HandlerInterceptor,再实现方法preHandle
//登录拦截器
//1.实现HandlerInterceptor,再实现方法preHandle
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session=request.getSession(false);
        if(session!=null && session.getAttribute("userInfo")!=null){
            //已经登录
            return true;//返回true不会被拦截,继续执行后面的代码
        }
        //未登录
        response.sendRedirect("/login.html");
        return false;//返回false就会被拦截
    }
}

4.配置拦截器

//配置拦截器
@Configuration
public class AppConfig implements WebMvcConfigurer {
    //添加拦截器
    @Resource
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")//拦截所有实现
                .excludePathPatterns("/user/reg")//不拦截谁
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/**/*.html");

    }
}

结果:
未登录,访问getuser被拦截,直接跳到登录页面
SpringBoot最常用的统一功能的处理_第1张图片注册不需要拦截,直接访问
SpringBoot最常用的统一功能的处理_第2张图片
登录成功后,可访问getuser
SpringBoot最常用的统一功能的处理_第3张图片
SpringBoot最常用的统一功能的处理_第4张图片

二、统一异常处理

1、创建异常类,类上加@ControllerAdvice注解,进行增强;
2.异常类中添加同一异常处理的方法,方法上添加@ExceptionHandler(ArithmeticException.class),括号内为异常的类型。

(1)注册方法中出现异常

@RequestMapping("/reg")
    public boolean reg(){
        int num=10/0;
        return true;
    }

(2)查看异常类型
在这里插入图片描述
(3)添加异常处理类

@ControllerAdvice//当前类对异常进行了封装
public class ErrorAdvice {
    //算术异常处理方法
    @ResponseBody
    @ExceptionHandler(ArithmeticException.class)//标识异常的类型
    //出现此类异常就调用这个方法,并且将异常传入参数
    public HashMap<String, Object> myArithmeticException(ArithmeticException e){
        HashMap<String,Object> result=new HashMap<>();
        result.put("satte",-1);
        result.put("msg","算数异常"+e.getMessage());//得到异常信息
        result.put("data",null);
        return result;
    }
    //还可以添加空指针异常等等、、、、、、
    
    //也可以设置默认异常
    //Exception为异常的父类
    @ResponseBody
    @ExceptionHandler(Exception.class)//标识异常的类型
    //出现此类异常就调用这个方法,并且将异常传入参数
    public HashMap<String, Object> myExceptio(Exception e){
        HashMap<String,Object> result=new HashMap<>();
        result.put("satte",-1);
        result.put("msg","默认异常"+e.getMessage());//得到异常信息
        result.put("data",null);
        return result;
    }
}

异常非常多,可以列举典型异常,其他用默认异常。
出现哪个异常就走哪个异常

没有处理异常前,会返回此类界面,用户会很懵

SpringBoot最常用的统一功能的处理_第5张图片

处理后,但凡此类异常都会返回如下界面,不会影响前后端交互失败,前端可以识别到。

SpringBoot最常用的统一功能的处理_第6张图片

三、统一数据返回格式

1.表示封装的类为@ControllerAdvice,并实现ResponseBodyAdvice 接口;
2.重写supports和beforeBodyWrite方法。

//统一返回类型
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;//必须是true,表示要对返回的数据进行封装
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        HashMap<String,Object> result=new HashMap<>();
        result.put("state",1);
        result.put("msg","");
        result.put("data",body);//原始数据
        return result;
    }
}

设置前:
SpringBoot最常用的统一功能的处理_第7张图片
设置后:将true封装在data中SpringBoot最常用的统一功能的处理_第8张图片

你可能感兴趣的:(spring,boot,后端,java)