公司里面的祖传代码很多,然后对拦截器进行修改,在拦截器中添加一些参数校验,然而对于payload请求,不可以通过getParameter()方法直接获取body里面的参数,需要读取流,然后转换成json对象,然而,抽取出来了就不能自动装配了,这个之前有写过一篇文章描述如何解决该问题的。
目前又遇到了一个问题,这种参数校验的项目较多,每个项目添加几个类很麻烦,然后想着用spring-boot的starter来封装之前的解决方法,然后每次要用的时候,我只需要pom引入我的starter就行。
1. @Configuration //指定这个类是一个配置类
@ConditionalOnXXX //在指定条件成立的情况下自动配置类生效
@AutoConfigureAfter //指定自动配置类的顺序
@Bean //给容器中添加组件
2. @ConfigurationPropertie结合相关xxxProperties类来绑定相关的配置
@EnableConfigurationProperties //让xxxProperties生效加入到容器中
3. 自动配置类要能加载
将需要启动就加载的自动配置类,配置在META‐INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
推荐使用以下命名规约;
• 官方命名空间
– 前缀:“spring-boot-starter-”
– 模式:spring-boot-starter-模块名
– 举例:spring-boot-starter-web、spring-boot-starter-actuator、spring-boot-starter-jdbc
• 自定义命名空间
– 后缀:“-spring-boot-starter ”
– 模式:模块-spring-boot-starter
– 举例:mybatis-spring-boot-starter
将自动配置类需要的jar包在starter中的pom文件引入进来。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.infosecgroupId>
<artifactId>multiplyuse-spring-boot-starterartifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>com.infosecgroupId>
<artifactId>multiplyuse-spring-boot-starter-autoconfigurerartifactId>
<version>0.0.1-SNAPSHOTversion>
dependency>
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.6version>
dependency>
dependencies>
project>
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
@ConfigurationProperties(prefix = "httpservlet.mulitiplyuse")
public class MultiplyUseProperties {
private List urlParten;
public List getUrlParten() {
return urlParten;
}
public void setUrlParten(List urlParten) {
this.urlParten = urlParten;
}
}
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
public class ContentCachingRequestWrapper extends HttpServletRequestWrapper{
private byte[] body;
private BufferedReader reader;
private ServletInputStream inputStream;
public ContentCachingRequestWrapper(HttpServletRequest request) throws IOException{
super(request);
loadBody(request);
}
private void loadBody(HttpServletRequest request) throws IOException{
body = IOUtils.toByteArray(request.getInputStream());
inputStream = new RequestCachingInputStream(body);
}
public byte[] getBody() {
return body;
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (inputStream != null) {
return inputStream;
}
return super.getInputStream();
}
@Override
public BufferedReader getReader() throws IOException {
if (reader == null) {
reader = new BufferedReader(new InputStreamReader(inputStream, getCharacterEncoding()));
}
return reader;
}
private static class RequestCachingInputStream extends ServletInputStream {
private final ByteArrayInputStream inputStream;
public RequestCachingInputStream(byte[] bytes) {
inputStream = new ByteArrayInputStream(bytes);
}
@Override
public int read() throws IOException {
return inputStream.read();
}
@Override
public boolean isFinished() {
return inputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readlistener) {
}
}
}
添加过滤器
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class SignValidateFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
String body = IOUtils.toString(requestWrapper.getBody(),request.getCharacterEncoding());
chain.doFilter(requestWrapper, response);
}
@Override
public void destroy() {
}
}
import com.infosec.multiplyusespringbootstarterautoconfigurer.MultiplyUseProperties;
import com.infosec.multiplyusespringbootstarterautoconfigurer.SignValidateFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass(name = "org.apache.commons.io.IOUtils")
@EnableConfigurationProperties(value = MultiplyUseProperties.class)
public class MultiplyUseAutoConfiguration
{
@Autowired
private MultiplyUseProperties multiplyUseProperties;
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new SignValidateFilter());
filterRegistrationBean.setUrlPatterns(multiplyUseProperties.getUrlParten());
return filterRegistrationBean;
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.infosec.multiplyusespringbootstarterautoconfigurer.configuration.MultiplyUseAutoConfiguration
拦截器
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.testforauto.annotatin.LoginRequired;
import com.infosec.multiplyusespringbootstarterautoconfigurer.ContentCachingRequestWrapper;
import org.apache.commons.io.IOUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
public class UserInceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("========================");
ContentCachingRequestWrapper requestWapper = null;
if(request instanceof HttpServletRequest){
requestWapper = (ContentCachingRequestWrapper) request;
}
System.out.println(123456);
String body = IOUtils.toString(requestWapper.getBody(),request.getCharacterEncoding());
JSONObject obj = JSON.parseObject(body);
System.out.println(obj);
return true;
}
}
请求
import com.example.testforauto.annotatin.LoginRequired;
import com.example.testforauto.entity.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@LoginRequired
@PostMapping(value = "/user")
public String User(@RequestBody User user){
System.out.println(123);
System.out.println(user);
return user.getName();
}
}
测试结果:
========================
123456
{"name":"ljl","id":1}
123
User{id=1, name='ljl'}
从结果上看,httpServletRequest在拦截器中被调用之后,自动装配也是成功的,所以实现了重复读取的功能。