编辑
2023-11-07
学习记录
00

前提

由于业务需要得为从ftp读取到的pdf加上水印,采用itextpdf依赖的功能

依赖

xml
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.11</version> </dependency> <!-- PDF文件字体 防止中文乱码 --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>

代码

我是写在pdf工具类中

java
public static byte[] PDFAddWatermark(byte[] pdfbyte, String waterMarkName) throws Exception { // 每页水印行数 int row = 7; // 每行水印个数 int col = 3; // 旋转角度 float rotation = 30f; byte[] decodeBuffer = pdfbyte; // 读取PDF PdfReader reader = new PdfReader(decodeBuffer); //创建字节数组输出流 ByteArrayOutputStream ous =new ByteArrayOutputStream(); // 创建字节缓冲输出流 BufferedOutputStream bos = new BufferedOutputStream(ous); // 输出的PDF文件内容 PdfStamper stamper = new PdfStamper(reader, bos); BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED); PdfGState gs = new PdfGState(); gs.setFillOpacity(0.2f);//改透明度 gs.setStrokeOpacity(0.4f);//设置笔触字体不透明度 PdfContentByte content; int total = reader.getNumberOfPages();//pdf文件页数 for (int i=0; i<total; i++) { // 在内容上方加水印 content = stamper.getOverContent(i+1); // 在内容下方加水印 // content = stamper.getUnderContent(i+1); //开始写入 content.beginText(); content.setGState(gs); //字体大小 content.setFontAndSize(base, 20); //每页7行,一行3个 for (int j=0; j<col; j++) { for (int k=0; k<row; k++) { float x = reader.getPageSize(i+1).getWidth() / col * j + 90; float y = reader.getPageSize(i+1).getHeight() / row * k; //showTextAligned 方法的参数(文字对齐方式,位置内容,输出水印X轴位置,Y轴位置,旋转角度) content.showTextAligned(Element.ALIGN_CENTER, waterMarkName, x, y, rotation); } } // 添加水印文字 content.endText(); } stamper.close(); //添加水印后pdf的base64 byte[] bytes = ous.toByteArray(); ous.close(); bos.close(); reader.close(); return bytes; }
编辑
2023-11-06
学习记录
00

前提

业务需要,得对特定的请求进行拦截,判断能不能满足状态,满足后才放行,不满足的话就抛出异常,过程主要分为四部分,首页是webMvcConfg配置,如何是拦截器的拦截逻辑编写,然后是对于json类型的消息头需要重写HttpServletRequestWrapper方法,实现多次对流的读取,不然拦截器读取后,放行请求路径对应的方法就获取不到请求体了,因为流只能读一次,所以还需要过滤器将对应的请求再塞回去

WebMvcConfig代码

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; } }
编辑
2023-11-03
遇到的问题
00

前提

业务需要,需要设置一个拦截器,对特定接口进行校验,使用HttpServletRequest.getParameter()和getParameterMap()以及getAttribute()都获取不到请求参数,数据为空

原因

因为是springBoot项目,参数一般都是Post方式,@RequestBody的形式,前端的配置类型是application/json,所以获取不到参数,@RequestBody是通过流的形式读取的,我们也得使用流的方式读取参数.一般使用,request.getInputStream()或者getReader()方式

衍生问题

request.getInputStream()或者getReader()只能调用一次,如果在拦截器层就调用了,那么@RequestBody就读取不了会出现异常信息

java
I/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
编辑
2023-11-03
学习记录
00

前提

由于业务需要得实现一个周期性的自动执行任务,之前的话都是在启动类上使用@EnableScheduling,然后定义一个自动任务类,在方法上使用@Scheduled(cron = "${job.archive.cron}"),来实现功能需要,这次就想换种方式实现,采用实现CommandLineRunner接口,这个接口在启动完成后,会自动执行run方法,我准备在run方法里使用周期线程池,来周期性执行。

编辑
2023-11-01
遇到的问题
00

前提

在项目遇到@Validated验证失效的场景,比如请求的类型是一个List< T >对象的话就无效,它只能验证javaBean类型的,或者采用@vaild注解,但是@Vaild注解不支持分组校验

解决方式1

在Cotroller类上加上@VailDated,方法上参数前就可以使用@NotEmpty(),来判断list是否为空,但是这样虽然可以校验但是不能实现分组的效果

解决方式2

使用自定义的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); } }