• SpringBoot统一功能处理


    目录

    一:用户登录权限验证 

    1.1:原生Spring Aop实现拦截的难点

    1.2:Spring 拦截器 

    1.2.1:自定义拦截器

    1.2.2:将自定义拦截器加入到系统配置中

    1.2.3:测试类 

    1.2.4:拦截器的实现原理 

    二:统一异常处理

    2.1:统一异常处理步骤 

    2.2:案例 

    2.3:运行结果: 

     三:统一数据返回格式

    3.1:统一数据返回格式的步骤

    3.2:统一数据返回格式的案例

    3.2.1:Controller层

    3.2.2:创建的类

    3.3.3:运行结果

    ​ 3.3:总结 

     3.4:注意事项


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

    一:用户登录权限验证 

    1.1:原生Spring Aop实现拦截的难点

    1.2:Spring 拦截器 

    1.2.1:自定义拦截器

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

    1.2.2:将自定义拦截器加入到系统配置中

    1. @Configuration
    2. public class AppConfig implements WebMvcConfigurer {
    3. @Override
    4. public void addInterceptors(InterceptorRegistry registry) {
    5. registry.addInterceptor(new LoginInterceptor())
    6. .addPathPatterns("/**")//拦截所有的请求
    7. .excludePathPatterns("/user/login")//不拦截的url地址
    8. .excludePathPatterns("/user/reg")
    9. //不拦截所有的静态页面
    10. .excludePathPatterns("/**/*.html")
    11. .excludePathPatterns("/**/*.css")
    12. .excludePathPatterns("/**/*.js");
    13. }
    14. }

    1.2.3:测试类 

    1. @RestController
    2. @RequestMapping("/user")
    3. public class UserController {
    4. @RequestMapping("/getuser")
    5. public String getUser(){
    6. System.out.println("执行了get User");
    7. return "getUser";
    8. }
    9. @RequestMapping("/login")
    10. public String login(){
    11. System.out.println("执行了 login");
    12. return "login";
    13. }
    14. }

    运行结果:

    1.2.4:拦截器的实现原理 

    实现原理:

    当用户调用后端程序时,先进行预处理,即利用拦截器拦截

    判断有没有在包含的路径下:

    如果有,则进入Handler......这个接口,执行里面的流程,1):当符合预处理的规则,走控制器层-->服务器层-->数据持久层(数据持久层再 调用底层的数据库).2):当不符合出路的规则,返回无权限访问或者相应的前端页面。

    如果没有,走当符合预处理规则的这一条路径。


     

    二:统一异常处理

    2.1:统一异常处理步骤 

    2.1.1:创建一个类,在类上添加注解@ControllerAdvice(增强对Controller的通知)+@ResponseBody(告诉前端返回的是一个数据,并非是静态页面html)

    2.1.2:在方法上添加@ExceptionHandler(异常管理器),对异常做出处理。

     

    2.2:案例 

    1. @ControllerAdvice
    2. //当前所有的方法返回的是一个数据,而不是一个静态页面
    3. @ResponseBody
    4. public class MyExHandler {
    5. //拦截所有的空指针异常,并返回所有的信息
    6. @ExceptionHandler(NullPointerException.class)
    7. public HashMap nullException(NullPointerException e){
    8. HashMap result=new HashMap<>();
    9. result.put("code",-1);
    10. result.put("msg","空指针异常"+e.getMessage());//错误码的描述信息
    11. result.put("data",null);
    12. return result;
    13. }
    14. @ExceptionHandler(ArithmeticException.class)
    15. public HashMap mathException(ArithmeticException e){
    16. HashMap result=new HashMap<>();
    17. result.put("code",-1);
    18. result.put("state",0);
    19. result.put("msg","数字异常"+e.getMessage());
    20. result.put("data",null);
    21. return result;
    22. }
    23. @ExceptionHandler(Exception.class)
    24. public HashMap exception(Exception e){
    25. HashMap result=new HashMap<>();
    26. result.put("code",-1);
    27. result.put("state",0);
    28. result.put("msg","异常"+e.getMessage());
    29. result.put("data",null);
    30. return result;
    31. }
    32. }

     

     在第一步的时候,即用户登录权限验证,我们并没有对注册和登录做出拦截,因此,为了方便期间,我们在这两个方法里面添加异常,用来验证能不能统一处理异常。

    1. @RestController
    2. @RequestMapping("/user")
    3. public class UserController {
    4. @RequestMapping("/getuser")
    5. public String getUser(){
    6. System.out.println("执行了get User");
    7. return "getUser";
    8. }
    9. @RequestMapping("/login")
    10. public String login(){
    11. Object obj=null;
    12. obj.hashCode();
    13. System.out.println("执行了 login");
    14. return "login";
    15. }
    16. @RequestMapping("/reg")
    17. public String reg(){
    18. int num=10/0;
    19. System.out.println("执行了reg");
    20. return "reg!";
    21. }
    22. }

    2.3:运行结果: 


     三:统一数据返回格式

    3.1:统一数据返回格式的步骤

    3.1.1:创建一个类,添加注解@ControllerAdvice

    3.1.2:让创建的类实现 ResponseBodyAdvice 接口

    3.1.3:重写boforeBodyWritesupports方法

    3.2:统一数据返回格式的案例

    以1-9返回任意的数据,以json的格式返回给前端页面。

    3.2.1:Controller层

    1. @RequestMapping("/getnum")
    2. public Integer getNumber(){
    3. return new Random().nextInt(10);
    4. }

    3.2.2:创建的类

    1. @ControllerAdvice
    2. public class ResponseAdvice implements ResponseBodyAdvice {
    3. /*
    4. 此方法返回true,则执行底下的beforeBodyWrite方法
    5. 如若返回false,则不执行底下的beforeBodyWrite方法
    6. */
    7. @Override
    8. public boolean supports(MethodParameter returnType, Class converterType) {
    9. return true;
    10. }
    11. @Override
    12. public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    13. HashMap hashMap=new HashMap<>();
    14. hashMap.put("code",200);
    15. hashMap.put("data",body);
    16. hashMap.put("msg","");
    17. return hashMap;
    18. }
    19. }

    3.3.3:运行结果

    3.3:总结 

    总结:

       1:创建一个类,让这个类实现ResponseBodyAdvice这个接口,并且在类的上面添加@ContrrollerAdvice这个注解 ,让其实现控制层进行加强

       2:对接口里面的两个方法(supports,beforeBodyWrite)进行重写,要让后端向前端数据保持统一性,要将supports的返回值为true,再将beforeBodyWrite里面的方法进行重写,利用Map集合包括(code,msg,data),进行补充。

     3.4:注意事项

    在beforeBodyWrite这个方法里面,如果body的数据为String类,此时,map所创建的集合不能转换为String类。因此,我们进行特殊处理。对于String类,我们使用jackson这个工具类,利用依赖注入注入ObjectMapper创建对象,

    调用objectMapper.writeValueAsString(hashMap)这个静态方法,将map集合转换为json格式的字符串。

    1. @ControllerAdvice
    2. public class ResponseAdvice implements ResponseBodyAdvice {
    3. @Autowired
    4. private ObjectMapper objectMapper;
    5. /*
    6. 此方法返回true,则执行底下的beforeBodyWrite方法
    7. 如若返回false,则不执行底下的beforeBodyWrite方法
    8. */
    9. @Override
    10. public boolean supports(MethodParameter returnType, Class converterType) {
    11. return true;
    12. }
    13. @Override
    14. public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    15. HashMap hashMap=new HashMap<>();
    16. hashMap.put("code",200);
    17. hashMap.put("data",body);
    18. hashMap.put("msg","");
    19. if(body instanceof String){
    20. //需要特殊处理,因为String 在转换的时候需要特殊处理
    21. try {
    22. objectMapper.writeValueAsString(hashMap);
    23. } catch (JsonProcessingException e) {
    24. throw new RuntimeException(e);
    25. }
    26. }
    27. return hashMap;
    28. }
    29. }

     

  • 相关阅读:
    华为云确定性运维,为政务云平台稳定可靠运行保驾护航
    深度学习100例 | 第31天-卷积神经网络(DenseNet)识别生活物品
    工作流引擎:Workflow Engine 7.0 Crack
    Sentinel服务保护
    C++面试八股文:如何避免死锁?
    离子液体 [C6MIm]BF4/cas:244193-50-8/1-己基-3-甲基咪唑四氟硼酸盐黄色液体
    Java使用documents4j将word和excel转pdf
    木马特征值免杀
    【博客455】Linux网桥如何接管attach上来的设备的流量
    ZZNUOJ_用C语言编写程序实现1359:数独(附完整源码)
  • 原文地址:https://blog.csdn.net/weixin_65492194/article/details/133581725