SpringBoot配置拦截器,获取请求内容

SpringBoot配置拦截器,获取get和post请求的内容
做这个需求时还遇到过一个小问题,因为拦截后想要获取post请求的参数需要用getInputStream()或getReader()来获取内容,但因为在整个请求中io流只能获取一次,我在这里就获取的话,后面会报相应的错误,故要重写类和方法,将获取到的流保存下来

配置拦截器,重写preHandle(),postHandle(),afterCompletion()方法处理入参,这三个方法的作用

preHandle():在请求处理之前进行调用(Controller方法调用之前),返回结果为true时,请求将会继续执行后面的操作,为false时,被请求时,请求终止,且后面的 postHandle 和 afterCompletion 方法都不会执行

postHandle():请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)

afterCompletion():请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)

package com.htsc.thfx.interceptor.interceptor;

import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class BootInterceptor implements HandlerInterceptor {
    /**
     * 在请求处理之前进行调用(Controller方法调用之前)
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("执行了BootInterceptor的preHandle方法");

        // 根据请求类型获取 入参
        String method = httpServletRequest.getMethod();
        if ("GET".equalsIgnoreCase(method)) {
            Map<String, String[]> parameterMap = httpServletRequest.getParameterMap();
        } else {
            //获取请求body
            byte[] bodyBytes = StreamUtils.copyToByteArray(httpServletRequest.getInputStream());
            String body = new String(bodyBytes, httpServletRequest.getCharacterEncoding());
        }

        //如果设置为true时,请求将会继续执行后面的操作
        //如果设置为false时,被请求时,请求终止,且后面的 postHandle 和 afterCompletion 方法都不会执行
        return true;
    }

    /**
     * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("执行了BootInterceptor的postHandle方法");


    }

    /**
     * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
     */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("执行了BootInterceptor的afterCompletion方法");


    }
}
package com.htsc.thfx.interceptor.config;

import com.htsc.thfx.interceptor.interceptor.BootInterceptor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;

@Configuration
public class BootConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer pathMatchConfigurer) {

    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer contentNegotiationConfigurer) {

    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer asyncSupportConfigurer) {

    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer defaultServletHandlerConfigurer) {

    }

    @Override
    public void addFormatters(FormatterRegistry formatterRegistry) {

    }

    @Override
    public void addInterceptors(InterceptorRegistry interceptorRegistry) {
        InterceptorRegistration registration = interceptorRegistry.addInterceptor(new BootInterceptor());
        // 过滤所有接口
        registration.addPathPatterns("/**");
        // 排除不过滤的接口
        registration.excludePathPatterns(
                "/simulationPort/**"
        );
    }

    @Bean
    @Qualifier(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServlet dispatcherServlet() {
        return new XinDispatcherServlet();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {

    }

    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {

    }

    @Override
    public void addViewControllers(ViewControllerRegistry viewControllerRegistry) {

    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) {

    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> list) {

    }

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> list) {

    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> list) {

    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> list) {

    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {

    }

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {

    }

    @Override
    public Validator getValidator() {
        return null;
    }

    @Override
    public MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}

自定义 DispatcherServlet 来分派 XinHttpServletRequestWrapper

package com.htsc.thfx.interceptor.config;

import org.springframework.web.servlet.DispatcherServlet;

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

/**
 * 自定义 DispatcherServlet 来分派 XinHttpServletRequestWrapper
 */
public class XinDispatcherServlet extends DispatcherServlet {

    /**
     * 包装成自定义的request
     *
     * @param request
     * @param response
     * @throws Exception
     */
    @Override
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        super.doDispatch(new XinHttpServletRequestWrapper(request), response);
    }
}

自定义HttpServletRequestWrapper 来包装输入流

package com.htsc.thfx.interceptor.config;

import org.springframework.util.StreamUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

/**
 * 自定义 HttpServletRequestWrapper 来包装输入流
 * 背景:因为ServletInputStream被读取后无法第二次再读取了,所以要把读取过的内容存下来,然后需要的时候对外提供可被重复读取的ByteArrayInputStream
 * 为了重写 ServletInputStream 的 getInputStream()方法,要自定义一个 HttpServletRequestWrapper
 */
public class XinHttpServletRequestWrapper extends HttpServletRequestWrapper {

    /**
     * 缓存下来的HTTP body
     */
    private byte[] body;

    public XinHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = StreamUtils.copyToByteArray(request.getInputStream());
    }

    /**
     * 重新包装 getInputStream
     *
     * @return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        InputStream bodyStream = new ByteArrayInputStream(body);
        return new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return bodyStream.read();
            }

            /**
             * 下面的方法一般情况下不会被使用,如果引入了一些需要使用ServletInputStream的外部组件,后面可以关注一下。
             * @return
             */
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    /**
     * 重新包装 getReader
     *
     * @return
     * @throws IOException
     */
    @Override
    public BufferedReader getReader() throws IOException {
        InputStream bodyStream = new ByteArrayInputStream(body);
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot,可以通过自定义拦截器获取请求头。拦截器Spring框架提供的一种机制,用于在请求处理之前或之后进行一些额外的处理。 要获取请求头,首先需要创建一个实现了HandlerInterceptor接口的拦截器类。在该类,可以重写preHandle方法,在该方法获取请求头信息。 下面是一个获取请求头的示例代码: ```java import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 获取请求头信息 String headerValue = request.getHeader("headerName"); System.out.println("Header Value: " + headerValue); // 返回true表示继续执行请求处理,返回false表示请求处理 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 在请求处理之后进行一些处理 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在请求完成之后进行一些处理 } } ``` 然后,在Spring Boot应用程序的配置注册该拦截器: ```java 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 WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()); } } ``` 这样,当有请求到达时,拦截器的preHandle方法会被调用,从而可以获取请求头信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值