SpringBoot统一功能处理

简介: SpringBoot统一功能处理

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

一:用户登录权限验证

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

1.2:Spring 拦截器

1.2.1:自定义拦截器

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;
    }
}

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

@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");
    }
}

1.2.3:测试类

@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";
    }
}

运行结果:

1.2.4:拦截器的实现原理

实现原理:

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

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

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

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


 

二:统一异常处理

2.1:统一异常处理步骤

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

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

2.2:案例

@ControllerAdvice
//当前所有的方法返回的是一个数据,而不是一个静态页面
@ResponseBody
public class MyExHandler {
    //拦截所有的空指针异常,并返回所有的信息
    @ExceptionHandler(NullPointerException.class)
    public HashMap<String,Object> nullException(NullPointerException e){
        HashMap<String,Object> result=new HashMap<>();
        result.put("code",-1);
        result.put("msg","空指针异常"+e.getMessage());//错误码的描述信息
        result.put("data",null);
        return result;
    }
    @ExceptionHandler(ArithmeticException.class)
    public HashMap<String,Object> mathException(ArithmeticException e){
        HashMap<String,Object> 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<String,Object> exception(Exception e){
        HashMap<String,Object> 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!";
    }
}

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层

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

3.2.2:创建的类

@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<String,Object> hashMap=new HashMap<>();
        hashMap.put("code",200);
        hashMap.put("data",body);
        hashMap.put("msg","");
        return hashMap;
    }
}

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格式的字符串。

@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<String,Object> 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;
    }
}

相关文章
|
7天前
|
消息中间件 缓存 Java
手写模拟Spring Boot启动过程功能
【11月更文挑战第19天】Spring Boot自推出以来,因其简化了Spring应用的初始搭建和开发过程,迅速成为Java企业级应用开发的首选框架之一。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,帮助读者深入理解其工作机制。
22 3
|
7天前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
25 0
|
1月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
42 4
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
148 1
|
1月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
36 0
|
2月前
|
Java 关系型数据库 MySQL
创建一个SpringBoot项目,实现简单的CRUD功能和分页查询
【9月更文挑战第6天】该内容介绍如何使用 Spring Boot 实现具备 CRUD 功能及分页查询的项目。首先通过 Spring Initializr 创建项目并选择所需依赖;其次配置数据库连接,并创建实体类与数据访问层;接着构建服务层处理业务逻辑;最后创建控制器处理 HTTP 请求。分页查询可通过添加 URL 参数实现。
|
20天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
95 62
|
17天前
|
前端开发 Java easyexcel
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
57 8
|
18天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
36 2
|
22天前
|
JSON Java API
springboot集成ElasticSearch使用completion实现补全功能
springboot集成ElasticSearch使用completion实现补全功能
24 1