业务需要,得对特定的请求进行拦截,判断能不能满足状态,满足后才放行,不满足的话就抛出异常,过程主要分为四部分,首页是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;
}
}
业务需要,需要设置一个拦截器,对特定接口进行校验,使用HttpServletRequest.getParameter()和getParameterMap()以及getAttribute()都获取不到请求参数,数据为空
因为是springBoot项目,参数一般都是Post方式,@RequestBody的形式,前端的配置类型是application/json,所以获取不到参数,@RequestBody是通过流的形式读取的,我们也得使用流的方式读取参数.一般使用,request.getInputStream()或者getReader()方式
request.getInputStream()或者getReader()只能调用一次,如果在拦截器层就调用了,那么@RequestBody就读取不了会出现异常信息
javaI/O error while reading input message; nested exception is java.io.IOException: Stream closed
或者
java
java.lang.IllegalStateException: getReader() has already been called for this request
由于业务需要得实现一个周期性的自动执行任务,之前的话都是在启动类上使用@EnableScheduling,然后定义一个自动任务类,在方法上使用@Scheduled(cron = "${job.archive.cron}"),来实现功能需要,这次就想换种方式实现,采用实现CommandLineRunner接口,这个接口在启动完成后,会自动执行run方法,我准备在run方法里使用周期线程池,来周期性执行。
在项目遇到@Validated验证失效的场景,比如请求的类型是一个List< T >对象的话就无效,它只能验证javaBean类型的,或者采用@vaild注解,但是@Vaild注解不支持分组校验
在Cotroller类上加上@VailDated,方法上参数前就可以使用@NotEmpty(),来判断list是否为空,但是这样虽然可以校验但是不能实现分组的效果
使用自定义的list,使用自定义list去包实体类,这样请求参数前面就可以使用@Vaildated注解
java
package com.lhw.entity;
import lombok.Data;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.*;
@Data
public class ValidatedList<E> implements List<E>, Serializable {
@Valid
@NotEmpty(message = "请求参数列表不能为空")
private List<E> list = new LinkedList<>();
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean add(E e) {
return list.add(e);
}
@Override
public boolean remove(Object o) {
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return list.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
@Override
public void clear() {
list.clear();
}
@Override
public E get(int index) {
return list.get(index);
}
@Override
public E set(int index, E element) {
return list.set(index, element);
}
@Override
public void add(int index, E element) {
list.add(index, element);
}
@Override
public E remove(int index) {
return list.remove(index);
}
@Override
public int indexOf(Object o) {
return list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
@Override
public ListIterator<E> listIterator() {
return list.listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
}
由于业务需要,需要从数据库中存放签名图片,采用blob格式存储,接口获取请求后,需从数据库中读取返回这个字段里的内容
采用byte[]的方式接受blob里的内容,图片需要转为base64,其他存放文本的blob需要转回正常的格式 工具类方法
java /**
*
* @Description: 二进制流转Base64字符串
* @Param: byteArr
* @author lihaowei
* @since: 2023/10/26 11:32
* @return String
*/
public static String byteArr2String(byte[] byteArr) throws Exception {
String stringBase64 = null;
try {
Base64 encoder = new Base64();
stringBase64 =(byteArr != null ? encoder.encodeToString(byteArr) : "");
} catch (Exception e) {
throw new Exception("byteArr2String转换异常:"+e);
}
return stringBase64;
}
具体功能
java
List<RecMrDetailSignsResponse> responses=new ArrayList<>();
for (RecMrDetailSignsEntity e:list) {
RecMrDetailSignsResponse r=BeanUtil.toBean(e,RecMrDetailSignsResponse.class);
try {
r.setPlainData(Base64Util.byteArr2String(e.getPlainData()));
r.setSignData(new String(e.getSignData(),"GBK"));
r.setSignTimeStamp(new String(e.getSignTimeStamp(),"GBK"));
} catch (Exception ex) {
ex.printStackTrace();
throw new BusinessException(ResultCodeEnum.ERR_0x1000.getCode(),"签名信息转换出错");
}
responses.add(r);
}
return responses;