【Spring框架】SpringBoot统一功能处理

目录

用户登录权限校验

用户登录拦截器

1.自定义拦截器

java 复制代码
package com.example.demo.config;

import com.example.demo.common.AppVar;
import org.springframework.web.servlet.HandlerInterceptor;

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

/**
 * 自定义拦截器
 */
 @Component
public class UserInterceptor implements HandlerInterceptor {

    /**
     * 返回 true -> 拦截器验证成功,继续执行后续方法
     * false -> 拦截器验证失败,不会执行后续的目标方法
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        // 业务方法
        HttpSession session = request.getSession(false);
        if (session != null &&
                session.getAttribute(AppVar.SESSION_KEY) != null) {
            // 用户已经登录
            return true;
        }
        return false;
    }
}


2.将自定义拦截器配置到系统设置中,并设置拦截规则

java 复制代码
package com.example.demo.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;

@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Autowired
    private UserInterceptor userInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new UserInterceptor());
        registry.addInterceptor(userInterceptor)
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/user/reg")
                .excludePathPatterns("/user/login");

    }
}

排除所有静态资源

java 复制代码
// 拦截器

@Override

public void addInterceptors(InterceptorRegistry registry) {
 registry.addInterceptor(new LoginInterceptor())
 .addPathPatterns("/**") // 拦截所有接⼝
 .excludePathPatterns("/**/*.js")
 .excludePathPatterns("/**/*.css")
 .excludePathPatterns("/**/*.jpg")
 .excludePathPatterns("/login.html")
 .excludePathPatterns("/**/login"); // 排除接⼝
}

练习:登录拦截器

  1. 登录、注册⻚⾯不拦截,其他⻚⾯都拦截。
  2. 当登录成功写⼊ session 之后,拦截的⻚⾯可正常访问。
java 复制代码
package com.example.demo.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;

@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Autowired
    private UserInterceptor userInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new UserInterceptor());
        registry.addInterceptor(userInterceptor)
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/user/reg")
                .excludePathPatterns("/reg.html")
                .excludePathPatterns("/login.html")
                .excludePathPatterns("/css/**")
                .excludePathPatterns("/editor.md/**")
                .excludePathPatterns("/img/**")
                .excludePathPatterns("/js/**")
        ;

    }
}
java 复制代码
package com.example.demo.config;

import com.example.demo.common.AppVar;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

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

/**
 * 自定义拦截器
 */
@Component
public class UserInterceptor implements HandlerInterceptor {

    /**
     * 返回 true -> 拦截器验证成功,继续执行后续方法
     * false -> 拦截器验证失败,不会执行后续的目标方法
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        System.out.println("do UserInterceptor");
        // 业务方法
        HttpSession session = request.getSession(false);
        if (session != null &&
                session.getAttribute(AppVar.SESSION_KEY) != null) {
            // 用户已经登录
            return true;
        }
        response.sendRedirect("https://www.baidu.com");
        return false;
    }
}

拦截器实现原理

然⽽有了拦截器之后,会在调⽤ Controller 之前进⾏相应的业务处理,执⾏的流程如下图所示:

统一异常处理

统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执⾏某个通知,也就是执⾏某个⽅法事件。

1.@ControllerAdvice/@RestControllerAdvice

2.@ExceptionHandler(Exception.class)统一返回的对象

java 复制代码
package com.example.demo.config;

import com.example.demo.common.ResultAjax;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class ExceptionAdvice {

    @ExceptionHandler(NullPointerException.class)
    public ResultAjax doNullPointerException(NullPointerException e) {
        ResultAjax resultAjax = new ResultAjax();
        resultAjax.setCode(-1);
        resultAjax.setMsg("空指针异常:"+ e.getMessage());
        resultAjax.setData(null);
        return resultAjax;
    }
    @ExceptionHandler(Exception.class)
    public ResultAjax doException(Exception e) {
        ResultAjax resultAjax = new ResultAjax();
        resultAjax.setCode(-1);
        resultAjax.setMsg("异常:"+ e.getMessage());
        resultAjax.setData(null);
        return resultAjax;
    }
}

统一数据返回格式

为什么需要统⼀数据返回格式?

统⼀数据返回格式的优点有很多,⽐如以下⼏个:

  1. ⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据。
  2. 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就⾏了,因为所有接⼝都是这样返回
    的。
  3. 有利于项⽬统⼀数据的维护和修改。
  4. 有利于后端技术部⻔的统⼀规范的标准制定,不会出现稀奇古怪的返回内容。

统⼀数据返回格式的实现

统⼀的数据返回格式可以使⽤ @ControllerAdvice + ResponseBodyAdvice 的⽅式实现。

  1. @ControllerAdvice
  2. 实现ResponseBodyAdvice接口,并重写它的两个方法:supports方法必须返回true,beforeBodyWrit方法中进行重新判断和重写操作。
java 复制代码
package com.example.demo.config;

import com.example.demo.common.ResultAjax;
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;

/**
 * 统一返回值的保底实现类
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    /**
     * true -> 才会调用 beforeBodyWrite 方法,
     * 反之则永远不会调用
     * @param returnType
     * @param converterType
     * @return
     */
    @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) {
        // 已经包装好的对象
        if (body instanceof ResultAjax) {
            return body;
        }

        return ResultAjax.succ(body);
    }
}
相关推荐
gadiaola40 分钟前
【JVM】Java虚拟机(二)——垃圾回收
java·jvm
coderSong25683 小时前
Java高级 |【实验八】springboot 使用Websocket
java·spring boot·后端·websocket
Mr_Air_Boy4 小时前
SpringBoot使用dynamic配置多数据源时使用@Transactional事务在非primary的数据源上遇到的问题
java·spring boot·后端
豆沙沙包?5 小时前
2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
java·开发语言·游戏
年老体衰按不动键盘5 小时前
快速部署和启动Vue3项目
java·javascript·vue
咖啡啡不加糖5 小时前
Redis大key产生、排查与优化实践
java·数据库·redis·后端·缓存
liuyang-neu5 小时前
java内存模型JMM
java·开发语言
UFIT6 小时前
NoSQL之redis哨兵
java·前端·算法
刘 大 望6 小时前
数据库-联合查询(内连接外连接),子查询,合并查询
java·数据库·sql·mysql
怀旧,6 小时前
【数据结构】6. 时间与空间复杂度
java·数据结构·算法