目录
本次博客完成有关Aop的三个实战环节,如下三个:

- public class LoginInterceptor implements HandlerInterceptor {
- /*
- 此方法返回一个boolean类型的值
- 如果为true,代表验证成功,执行后续功能
- 如果为false,代表验证失败,后面的流程就不能执行了。
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- //用户登录业务判断
- // 当session不存在时候,不需要创建session的绘画信息
- HttpSession session = request.getSession(false);
- if(session!=null&&session.getAttribute("userinfo")!=null){
- //说明用户已经登录
- return true;
- }
- //跳转到登录页面or返回401/403无权限的状态码
-
- response.setStatus(403);
- return false;
-
-
-
-
- }
- }

- @Configuration
- public class AppConfig implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new LoginInterceptor())
- .addPathPatterns("/**")//拦截所有的请求
- .excludePathPatterns("/user/login")//不拦截的url地址
- .excludePathPatterns("/user/reg")
- //不拦截所有的静态页面
- .excludePathPatterns("/**/*.html")
- .excludePathPatterns("/**/*.css")
- .excludePathPatterns("/**/*.js");
- }
- }

- @RestController
- @RequestMapping("/user")
- public class UserController {
- @RequestMapping("/getuser")
- public String getUser(){
- System.out.println("执行了get User");
- return "getUser";
- }
- @RequestMapping("/login")
- public String login(){
- System.out.println("执行了 login");
- return "login";
- }
-
- }
运行结果:



实现原理:
当用户调用后端程序时,先进行预处理,即利用拦截器拦截
判断有没有在包含的路径下:
如果有,则进入Handler......这个接口,执行里面的流程,1):当符合预处理的规则,走控制器层-->服务器层-->数据持久层(数据持久层再 调用底层的数据库).2):当不符合出路的规则,返回无权限访问或者相应的前端页面。
如果没有,走当符合预处理规则的这一条路径。

2.1.1:创建一个类,在类上添加注解@ControllerAdvice(增强对Controller的通知)+@ResponseBody(告诉前端返回的是一个数据,并非是静态页面html)
2.1.2:在方法上添加@ExceptionHandler(异常管理器),对异常做出处理。
- @ControllerAdvice
- //当前所有的方法返回的是一个数据,而不是一个静态页面
- @ResponseBody
- public class MyExHandler {
- //拦截所有的空指针异常,并返回所有的信息
- @ExceptionHandler(NullPointerException.class)
- public HashMap
nullException(NullPointerException e){ - HashMap
result=new HashMap<>(); - result.put("code",-1);
- result.put("msg","空指针异常"+e.getMessage());//错误码的描述信息
- result.put("data",null);
- return result;
- }
- @ExceptionHandler(ArithmeticException.class)
- public HashMap
mathException(ArithmeticException e){ - HashMap
result=new HashMap<>(); - result.put("code",-1);
- result.put("state",0);
- result.put("msg","数字异常"+e.getMessage());
- result.put("data",null);
- return result;
- }
- @ExceptionHandler(Exception.class)
- public HashMap
exception(Exception e){ - HashMap
result=new HashMap<>(); - result.put("code",-1);
- result.put("state",0);
- result.put("msg","异常"+e.getMessage());
- result.put("data",null);
- return result;
-
- }
-
- }

在第一步的时候,即用户登录权限验证,我们并没有对注册和登录做出拦截,因此,为了方便期间,我们在这两个方法里面添加异常,用来验证能不能统一处理异常。
- @RestController
- @RequestMapping("/user")
- public class UserController {
- @RequestMapping("/getuser")
- public String getUser(){
- System.out.println("执行了get User");
- return "getUser";
- }
- @RequestMapping("/login")
- public String login(){
- Object obj=null;
- obj.hashCode();
- System.out.println("执行了 login");
- return "login";
- }
- @RequestMapping("/reg")
- public String reg(){
- int num=10/0;
- System.out.println("执行了reg");
- return "reg!";
- }
-
- }


3.1.1:创建一个类,添加注解@ControllerAdvice
3.1.2:让创建的类实现 ResponseBodyAdvice 接口
3.1.3:重写boforeBodyWrite和supports方法
以1-9返回任意的数据,以json的格式返回给前端页面。
- @RequestMapping("/getnum")
- public Integer getNumber(){
- return new Random().nextInt(10);
- }
- @ControllerAdvice
- public class ResponseAdvice implements ResponseBodyAdvice {
- /*
- 此方法返回true,则执行底下的beforeBodyWrite方法
- 如若返回false,则不执行底下的beforeBodyWrite方法
- */
- @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) {
- HashMap
hashMap=new HashMap<>(); - hashMap.put("code",200);
- hashMap.put("data",body);
- hashMap.put("msg","");
- return hashMap;
- }
- }

3.3:总结 总结:
1:创建一个类,让这个类实现ResponseBodyAdvice这个接口,并且在类的上面添加@ContrrollerAdvice这个注解 ,让其实现控制层进行加强
2:对接口里面的两个方法(supports,beforeBodyWrite)进行重写,要让后端向前端数据保持统一性,要将supports的返回值为true,再将beforeBodyWrite里面的方法进行重写,利用Map集合包括(code,msg,data),进行补充。
在beforeBodyWrite这个方法里面,如果body的数据为String类,此时,map所创建的集合不能转换为String类。因此,我们进行特殊处理。对于String类,我们使用jackson这个工具类,利用依赖注入注入ObjectMapper创建对象,
调用objectMapper.writeValueAsString(hashMap)这个静态方法,将map集合转换为json格式的字符串。
- @ControllerAdvice
- public class ResponseAdvice implements ResponseBodyAdvice {
- @Autowired
- private ObjectMapper objectMapper;
- /*
- 此方法返回true,则执行底下的beforeBodyWrite方法
- 如若返回false,则不执行底下的beforeBodyWrite方法
- */
- @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) {
-
- HashMap
hashMap=new HashMap<>(); - hashMap.put("code",200);
- hashMap.put("data",body);
- hashMap.put("msg","");
- if(body instanceof String){
- //需要特殊处理,因为String 在转换的时候需要特殊处理
- try {
- objectMapper.writeValueAsString(hashMap);
- } catch (JsonProcessingException e) {
- throw new RuntimeException(e);
- }
- }
- return hashMap;
- }
- }
