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

前提

由于业务需要,得对pdf文件进行盖章上传,需要jks文件进行解密获取秘钥,demo将jks文件放在resource中可以正常解密,而将代码结合在主程序中就提示错误Invalid keystore format,前提是密码正常,jks文件正常有效

排查

首先不通过Thread.currentThread().getContextClassLoader().getResource("test.jks")的方式获取文件,先将文件存在其他盘的绝对路径中,进行测试,文件可以正常加载解密

第二步将Thread.currentThread().getContextClassLoader().getResource("test.jks")方法获取路径,复制出来写死在配置项中,加载文件,提示错误Invalid keystore format。

从两个测试来看,首先从第一个测试来看jks文件是正常的,密码正确,第二个测试来看不是类加载的加载问题,路径正常,但是加载器的路径是target/classes路径下面的文件,这个路径的文件有问题,源文件8kb,打开target路径查看,文件是12kb,说明maven打包的时候文件被修改了,导致解密错误

maven过滤文件

在模块的pom文件中添加resources内容进行过滤文件,第一个是resource表示resources目录下都是资源文件需要打包,第二个resouce表示需要过滤stamp/* 目录下的文件,不要替换占位符

xml
<project> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <excludes> <exclude>stamp/*</exclude> </excludes> <filtering>true</filtering> </resource> </resources> </build> </project>
编辑
2023-11-21
遇到的问题
00

前提

开发过程中一直提示数据库错误,内部类型转换异常,排查字段命名和数据库是否对应,数据类型是否相同都没问题,发现之前实体对象使用@builder类型来构建对象的注解导致的问题

报错

text
### Error querying database. Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'VALUE_TYPE' from result set. Cause: java.sql.SQLException: 无法转换为内部表示

解决方式

  1. 实体对象去除@builder注解,调整之前的业务实体构建方式
  2. 再为实体添加上@AllArgsConstructor @NoArgsConstructor 注解
编辑
2023-11-17
学习记录
00

前提

工作中很多时候需要从Class类中获取属性的值,下面会基础获取,以及结合工作内容

基础获取

java
public class Main { public static void main(String[] args) { Person person = new Person("张三", 25); try { Field nameField = Person.class.getDeclaredField("name"); Field ageField = Person.class.getDeclaredField("age"); // 设置访问权限,如果属性是私有的 nameField.setAccessible(true); ageField.setAccessible(true); // 获取属性值 String name = (String) nameField.get(person); int age = (int) ageField.get(person); System.out.println("姓名:" + name); System.out.println("年龄:" + age); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } } class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } }
编辑
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; } }