Spring MVC @Bean可以检查HTTP请求吗?

问题描述

我有一个方案,Spring应用程序使用自定义ContentType和JSON负载接收HTTP请求。一部分有效载荷是服务定位器调用中使用的密钥。

有效载荷:

{ "service_id": "ServiceA" }

我想使用@RequestScope的Spring @Bean检查请求并返回/注入正确的服务。

类似的东西:

@Configuration
public class ServiceLocatorConfig {

    @Bean
    @RequestScope
    public SomeService serviceByKey(WebRequest request,Map<String,SomeService> services) {

        // This is where I need a hand -- how would I get the request body?
        String serviceId = readServiceIdFromrequestBody(request);
        return services[key];
    }

}

到目前为止,我已经在@Bean中收到请求,但是获得请求正文没有任何成功。我得到的最接近的结果是盲目尝试ContentCachingRequestWrapper,但是在致电null时我总是收到.getContentAsByteArray()。听起来好像还需要表单编码的主体,因此自定义内容类型(在这种情况下无法修改)可能会带来更多麻烦。

Spring Bean如何检查HTTP请求?

解决方法

为了实现您需要的功能,您可以使用WebFilter作为进入请求的拦截器,在到达services之前,它可以访问json有效负载,并且您可以读取传入的参数并调用适当的组件以处理请求。

您的WebFilter类将类似于该类(在本示例中,我们正在拦截对'/ rest / *'的请求:

import java.io.IOException;
import java.nio.charset.Charset;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;


@WebFilter(urlPatterns = "/rest/*")
public class DoSomethingInterceptor implements Filter {

    private FilterConfig filterConfig;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
            throws IOException,ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        //Parse the json from request
        String jsonPayload = IOUtils.toString(request.getInputStream(),Charset.defaultCharset());
        IncomingRequest jsonRequest = mapper.readValue(jsonPayload,IncomingRequest.class);
        
        //Read the service parameter
        String serviceClass = jsonRequest.getServiceClass();
        
        //Map the incoming service to your service class
        Class<MyService> myServiceClass = ServiceType.get(serviceClass);
        
        //Get the bean from Spring context
        DoSomething bean =
                (DoSomething) WebApplicationContextUtils.
                        getRequiredWebApplicationContext(filterConfig.getServletContext()).
                        getBean(myServiceClass);
        
        //Call the method in the service
        String resultFromService = bean.doSomething();
        
        //Finally you will copy the result from service to the http response
        response.getOutputStream().write(resultFromService);
        return;
    }
}

也请记住在Spring上注册您的WebFilter,对于SpringBoot应用程序,可以像下面的示例中那样完成:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }

    @Bean
    @Autowired
    public FilterRegistrationBean registerFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new DoSomethingInterceptor());
        List<String> urlPatterns = new ArrayList<>();
        urlPatterns.add("/rest/*");
        filterRegistration.setUrlPatterns(urlPatterns);
        return filterRegistration;
    }

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...