Spring统一功能处理

这篇具有很好参考价值的文章主要介绍了Spring统一功能处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. AOP存在的问题

  • 获取参数复杂
  • AOP的规则相对简单

2. 拦截器

2.1. 应用(以登录为例)

2.1.1. 自定义拦截器

新建interceptor文件夹

import org.springframework.web.servlet.HandlerInterceptor;

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

@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("username")!=null){
            //通过
            return true;
        }else {
            //没登录
            response.setStatus(401);
            return false;
        }
    }
}

2.1.2. 将自定义拦截器加入到系统配置

新建config文件夹

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springaop.interceptor.LoginInterceptor;

@Configuration
public class AppConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")         //"/**"表示拦截所有
                .excludePathPatterns("/user/login")  //除了登录
                .excludePathPatterns("/user/reg");    //除了注册
    }
}

2.1.3. 业务代码

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

@Slf4j
@RequestMapping("/user")
@RestController
public class UserController {
    //获取用户信息
    @RequestMapping("/getInfo")
    public String getInfo(){
        log.info("log.getInfo");
        return "get info...";
    }

    //注册
    @RequestMapping("/reg")
    public String reg(){
        log.info("log.reg");
        return "reg...";
    }

    //登录
    @RequestMapping("/login")
    public boolean login(HttpServletRequest request,String username,String password){
        log.info("log.login");
        //判断username和password是否为空
//        if (username!=null && username.equals("") && password!=null && password.equals("")){
//            //
//        }
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){
            return false;
        }
        if (!"admin".equals(username) || !"admin".equals(password)){
            return false;
        }
        HttpSession session = request.getSession(true);
        session.setAttribute("username",username);
        return true;
    }
}

2.2. 排除所有静态资源方法

方法1

registry.addInterceptor(new LoginInterceptor())
            .addPathPatterns("/**") // 拦截所有接口
            .excludePathPatterns("/**/*.js")
            .excludePathPatterns("/**/*.css")
            .excludePathPatterns("/**/*.jpg")
            .excludePathPatterns("/login.html")
            .excludePathPatterns("/**/login"); // 排除接口

方法2

private final List<String> excludePaths = 
    //注意List的这种方式的初始化赋值不允许再追加元素
    Arrays.asList("/**/*.html",
                  "blog-editormd",
                  "/css/**",
                  "/js/**",
                  "/pic/**",
                  "/user/login",
                  "/user/res");
	
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludePaths);
    }

2.3. 实现原理

2.3.1. 总体思路

Spring统一功能处理,JavaEE,java

2.3.2. 部分源码分析

拦截器是基于AOP实现的

(AOP基于动态代理(JDK|CGLIB))

Spring统一功能处理,JavaEE,java

3. 统一功能处理

3.1. 统一登录处理

参考上一节 拦截器的应用

3.2. 统一异常处理

对于下面的异常, 我们在访问页面的时候,不希望让用户看到

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/exception")
public class ExceptionController {
    //算数异常
    @RequestMapping("/test1")
    public boolean test1(){
        int a = 10/0;
        return true;
    }

    //空指针异常
    @RequestMapping("/test2")
    public boolean test2(){
        String str = null;
        System.out.println(str.length());
        return true;
    }

    //手动异常
    @RequestMapping("/test3")
    public boolean test3(){
        throw new RuntimeException("手动异常");
    }
}

可能出现的问题:

类上面的@RequestMapping("/ex")访问的时候会有未知的问题,改成@RequestMapping("/exception")比较好

3.2.1. 配置ErrorHandler

针对不同的异常,进行不同的操作

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;

@Slf4j
@ControllerAdvice
@ResponseBody
public class ErrorHandler {
    
    @ExceptionHandler
    public Object error(Exception e){
        HashMap<String,Object> result = new HashMap<>();
        log.info("内部异常:",e);
        result.put("success",0);
        result.put("code",-1);
        result.put("msg","内部异常");
        return result;
    }

    @ExceptionHandler
    public Object error(ArithmeticException e){
        HashMap<String,Object> result = new HashMap<>();
        log.info("算数异常:",e);
        result.put("success",0);
        result.put("code",-2);
        result.put("msg","算术异常");
        return result;
    }

    @ExceptionHandler
    public Object error(NullPointerException e){
        HashMap<String,Object> result = new HashMap<>();
        log.info("空指针异常:",e);
        result.put("success",0);
        result.put("code",-3);
        result.put("msg","空指针异常");
        return result;
    }
}
3.2.1.1. 可能会遇到的问题

①写完代码访问的时候,会是错误404, 而且异常是返回的不是一个视图, 需要添加@ResponseBody注解,让程序意识到返回的就是数据, 而不是视图

②分辨不出来异常

之前在切面的@Around环绕通知里有一段代码

Spring统一功能处理,JavaEE,java

要是遇到了异常都会抛出RuntimeException, 从而掩盖了真正的异常, 需要改成下面的样子, 抛出真正的异常

Spring统一功能处理,JavaEE,java

3.3. 统一数据返回格式

3.3.1. 好处

统一数据返回格式的优点有很多. 比如以下几个:

  • 方便前端程序员更好的接收和解析后端数据接口返回的数据
  • 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就行了,因为所有接口都是这样返回的
  • 有利于项目统一数据的维护和修改
  • 有利于后端技术部门的统一规范的标准制定,不会出现稀奇古怪的返回内容

3.3.2. 代码

新建ResponseHandler

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashMap;

@ControllerAdvice
public class ResponseHandler implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;    //一定要改成true
    }

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        HashMap<String,Object> result = new HashMap<>();
        result.put("success",1);
        result.put("data",body);
        result.put("errMsg","");
        //对字符串进行特殊处理
        if (body instanceof String){
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(result);
        }
        return result;
    }
}

添加这段代码之前, 访问成功了,得到的是true, 加上这段代码就变成了{"data":true,"success":1,"errMsg":""}

3.3.2.1. 可能出现的问题

①supports()的返回值一定要改成true

②getInfo()的业务代码的返回值是String, 会引发java.util.HashMap cannot be cast to java.lang.String错误. 由于内部的数据类型转换问题导致, 解决方法是加一步验证.

Spring统一功能处理,JavaEE,java

这段代码会有异常, 用@SneakyThrows处理. 这个注解的作用就是自动生成一个try-catch, 直接抛出异常文章来源地址https://www.toymoban.com/news/detail-664891.html

到了这里,关于Spring统一功能处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring 统一功能处理(拦截器)

    SpringBoot统一功能处理。也就是AOP的具体实现。 最原始的用户登录验证方法,我们通过封装了一个方法来判断用户是否登录,但如果实现的功能多了,那么每一个需要登录的功能都要在对应的接口中来调用这个函数来判读是否登录。 上面的代码虽然已经封装成了方法,但是如

    2024年02月03日
    浏览(54)
  • 【Spring Boot 】Spring Boot 统一功能处理

    🎉🎉🎉 点进来你就是我的人了 博主主页: 🙈🙈🙈 戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔 🤺🤺🤺 目录 前言 1. Spring 拦截器 1.1 自定义拦截器 1.2 将自定义拦截器加入到系统配置中 1.3 拦截器实现原理 统一访问前缀添加 (扩展) 2. 统一异常的处理 (@Co

    2024年02月09日
    浏览(38)
  • 【Spring Boot】拦截器与统一功能处理:统一登录验证、统一异常处理与统一数据返回格式

     Spring AOP是一个基于面向切面编程的框架,用于将横切性关注点(如日志记录、事务管理)与业务逻辑分离,通过代理对象将这些关注点织入到目标对象的方法执行前后、抛出异常或返回结果时等特定位置执行,从而提高程序的可复用性、可维护性和灵活性。但使用原生Sp

    2024年02月16日
    浏览(47)
  • Spring Boot 系列4 -- 统一功能处理

    目录 前言 1. Spring AOP 用户统⼀登录验证的问题 1.1 自定义拦截器 1.2 配置拦截器并配置拦截的规则 1.3 拦截器的原理源码分析 2. 统一异常处理 2.1 实现统一异常处理 2.2 测试统一异常处理 3. 统一的数据格式返回 3.1 统⼀数据返回格式的实现 3.2 测试统一的数据返回         S

    2024年02月14日
    浏览(39)
  • Spring Boot统一处理功能——拦截器

    ⽤户登录权限的发展从之前每个⽅法中⾃⼰验证⽤户登录权限,到现在统⼀的⽤户登录验证处理,它是⼀个逐渐完善和逐渐优化的过程。 我们先来回顾⼀下最初⽤户登录验证的实现⽅法: 从上述代码可以看出,每个⽅法中都有相同的⽤户登录验证权限,它的缺点是: 1. 每个

    2024年02月13日
    浏览(36)
  • 【Spring Boot】拦截器与统一功能处理

    博主简介:想进大厂的打工人 博主主页: @xyk: 所属专栏: JavaEE进阶   上一篇文章我们讲解了Spring AOP是一个基于面向切面编程的框架,用于将某方面具体问题集中处理,通过代理对象来进行传递,但使用原生Spring AOP实现统一的拦截是非常繁琐的。而在本节,我们将使用一种

    2024年02月14日
    浏览(40)
  • 【Spring Boot统一功能处理】统一异常处理,统一的返回格式,@ControllerAdvice简单分析,即将走进SSM项目的大门! ! !

    前言: 大家好,我是 良辰丫 ,在上一篇文章中我们已经学习了一些统一功能处理的相关知识,今天我们继续深入学习这些知识,主要学习统一异常处理,统一的返回格式,@ControllerAdvice简单分析.💌💌💌 🧑个人主页:良辰针不戳 📖所属专栏:javaEE进阶篇之框架学习 🍎励志语句:生

    2024年02月16日
    浏览(42)
  • Spring Boot 统一功能处理(拦截器实现用户登录权限的统一校验、统一异常返回、统一数据格式返回)

    目录 1. 用户登录权限校验 1.1 最初用户登录权限效验 1.2 Spring AOP 用户统⼀登录验证 1.3 Spring 拦截器 (1)创建自定义拦截器 (2)将自定义拦截器添加到系统配置中,并设置拦截的规则 1.4 练习:登录拦截器 (1)实现 UserController 实体类 (2)返回的登录页面:login.html (3)实

    2024年02月12日
    浏览(50)
  • Spring Boot 优雅实现统一数据返回格式+统一异常处理+统一日志处理

            在我们的项目开发中,我们都会对数据返回格式进行统一的处理,这样可以方便前端人员取数据,当然除了正常流程的数据返回格式需要统一以外,我们也需要对异常的情况进行统一的处理,以及项目必备的日志。         在项目开发中返回的是json格式的数据

    2024年01月19日
    浏览(43)
  • SpringBoot 统一功能处理

    登录、注册页面不拦截,其他页面都拦截 当登录成功写入 session 之后,拦截的页面可正常访问 调用顺序: 正常情况下,程序会在调用 Controller 之前进行相应的业务处理(我们在切面中定义的事务),业务通过后,才会调用Controller 层,然后就是Controller - Serrvice - Mapper - 数据

    2024年01月24日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包