业务需要,得对特定的请求进行拦截,判断能不能满足状态,满足后才放行,不满足的话就抛出异常,过程主要分为四部分,首页是webMvcConfg配置,如何是拦截器的拦截逻辑编写,然后是对于json类型的消息头需要重写HttpServletRequestWrapper方法,实现多次对流的读取,不然拦截器读取后,放行请求路径对应的方法就获取不到请求体了,因为流只能读一次,所以还需要过滤器将对应的请求再塞回去
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private IRecSealService iRecSealService;
/**
* 添加拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器,并且指定需要拦截的请求路径
registry.addInterceptor(new URLInterceptor(iRecSealService))
.addPathPatterns("/recMrIndex/aaa"
, "/recMrIndex/bbb"
, "/recMrIndex/ccc"
, "/recUpperShelf/ddd"
);
WebMvcConfigurer.super.addInterceptors(registry);
}
/**
* 对指定请求的 HttpServletRequest 进行重新注册返回
*
*/
@Bean
public FilterRegistrationBean setLogServiceFilter() {
//使用过滤器将请求体塞回去避免流只能读一次造成的错误
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
RequestBodyFilter requestBodyFilter = new RequestBodyFilter();
registrationBean.setFilter(requestBodyFilter);
registrationBean.setName("interceptor filter body params");
registrationBean.addUrlPatterns("/recMrIndex/aaa"
, "/recMrIndex/bbb"
, "/recMrIndex/ccc"
, "/recUpperShelf/ddd"
);
registrationBean.setOrder(1);
return registrationBean;
}
}
java
/**
*
* <p>
* 对特定的url进行拦截, 按添加的路径进行拦截,获取 各种参数,进行验证
* </p>
*
* @author lihaowei
* @since: 2023/11/6 15:23
*
*/
@Component
public class URLInterceptor implements HandlerInterceptor {
@Resource
private IRecSealService iRecSealService;
public URLInterceptor(private IRecSealService iRecSealService) {
this.iRecSealService = iRecSealService;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String contentType="application/json";
if (request.getContentType().contains(contentType)){
String methodName = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1);
RequestReaderHttpServletRequestWrapper requestWrapper=new RequestReaderHttpServletRequestWrapper(request);
String body = requestWrapper.inputStream2String(requestWrapper.getInputStream());
switch (methodName) {
//aaa
case "aaa":
ObjectRequest receiveRequest = JSON.parseObject(body,ObjectRequest.class);
if (ObjectUtil.isNull(receiveRequest)) {
return true;
}
return getSealPatientStatusByList(receiveRequest.getList,ObjectRequest.class);
//bbb
case "bbb":
List<ObjectRequest> sends = JSON.parseArray(body, ObjectRequest.class);
return getSealPatientStatusByList(receiveRequest.getList,ObjectRequest.class);
//ccc
case "ccc":
List<ObjectRequest> bindRequest = JSON.parseArray(body, ObjectRequest.class);
return getSealPatientStatusByList(receiveRequest.getList,ObjectRequest.class);
//ddd
case "ddd":
ObjectRequest onShelf = JSON.parseObject(body, ObjectRequest.class);
if (ObjectUtil.isEmpty(onShelf)) {
return true;
}
List<patientRequest> patients=new ArrayList<>();
.....
return getSealPatientStatus(patients);
}
}
return HandlerInterceptor.super.preHandle(request, response, handler);
}
public boolean getSealPatientStatus(List<PatientRequest> patients){
for (PatientRequest request : patients) {
QueryWrapper<RecSealEntity> queryWrapper=new QueryWrapper<>();
.....
RecSealEntity recSeal = iRecSealService.getOne(queryWrapper);
if (ObjectUtil.isNull(recSeal)){
return true;
}
if () {
//判断业务逻辑
} else {
//判断业务逻辑
}
}
return true;
}
public <T> boolean getSealPatientStatusByList(List<T> list,Class<T> clazz) {
if (CollUtil.isEmpty(list)) {
return true;
}
List<PatientRequest> patients= new ArrayList<>();
try {
for (T t:list){
PatientRequest patient=new PatientRequest();
Field patientId=clazz.getDeclaredField("patientId");
Field visitNo=clazz.getDeclaredField("visitNo");
//允许访问私有属性值
patientId.setAccessible(true);
visitNo.setAccessible(true);
patient.setPatientId((String) patientId.get(t));
patient.setVisitNo((String) visitNo.get(t));
patients.add(patient);
}
}catch (NoSuchFieldException e) {
e.printStackTrace();
throw new BusinessException(ResultCodeEnum.ERR_0x1000.getCode(),"拦截器获取属性出错属性值为空:"+e.getMessage());
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new BusinessException(ResultCodeEnum.ERR_0x1000.getCode(),"拦截器获取属性出错");
}
if (CollUtil.isEmpty(patients)){
return true;
}
return getSealPatientStatus(patients);
}
}
java
/**
* 解决拦截器从流中获取完整的 body 请求参数后,无法再次调用流中数据的问题,否则报以下错误信息
* <p>
* I/O error while reading input message; nested exception is java.io.IOException: Stream closed
*/
public class RequestReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
private final byte[] body;
public RequestReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = inputStream2String(request.getInputStream()).getBytes(Charset.forName("UTF-8"));
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
/**
* 将 inputStream 里的数据读取出来并转换成字符串
*
* @param inputStream inputStream
* @return String
*/
public String inputStream2String(InputStream inputStream) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
sb.append("get body params fail");
LOGGER.error(e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
}
return sb.toString();
}
}
java
/**
*
* <p>
* 重新组装 HttpServletRequest 返回, 解决拦截器中从流中获取完 post 请求中的 body 参数,controller 层无法再次获取的问题
* </p>
*
* @author lihaowei
* @since: 2023/11/6 15:21
*
*/
public class RequestBodyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String method = httpServletRequest.getMethod();
String contentType = httpServletRequest.getContentType() == null ? "" : httpServletRequest.getContentType();
// 如果是POST请求并且不是文件上传
if (HttpMethod.POST.name().equals(method) && !contentType.equals(MediaType.MULTIPART_FORM_DATA_VALUE)) {
// 重新生成ServletRequest 这个新的 ServletRequest 获取流时会将流的数据重写进流里面
requestWrapper = new RequestReaderHttpServletRequestWrapper((HttpServletRequest) request);
}
}
if (requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
本文作者:Weee
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!