编辑
2023-04-04
学习记录
00

简介

目的:要将ftp上的文件转存在另外的ftp地址,我们拆分成两步,先将文件输入流转为base64,再将base64字符串转成pdf存储在ftp上

读取代码

java
public String getPdfByFtpUrl(RecTypeDictStorageEntity storageEntity,ViewArchiveDocumentsEntity viewArchiveDocuments) { ByteArrayOutputStream fileData=new ByteArrayOutputStream(); FtpUtil ftpUtil = new FtpUtil(); String ftpConfig = "ftp://USER:PWD@IP:PORT"; ftpConfig = ftpConfig.replace("IP", storageEntity.getFtpIp()) .replace("USER", storageEntity.getFtpUser()) .replace("PWD", storageEntity.getFtpPwd()) .replace("PORT", storageEntity.getFtpPort()); ftpUtil.getConn(ftpConfig); String remoteFile = viewArchiveDocuments.getDocfile().substring(0, viewArchiveDocuments.getDocfile().lastIndexOf("/") + 1); String fileName = viewArchiveDocuments.getDocfile().substring(viewArchiveDocuments.getDocfile().lastIndexOf("/") + 1); try { boolean result = ftpUtil.fileExist(remoteFile, fileName); if (result) { fileData = ftpUtil.fileGet(remoteFile, fileName); } } catch (Exception e) { e.printStackTrace(); } finally { ftpUtil.ftpDisconnect(); } if (fileData!=null) { try { byte[] fileArray=fileData.toByteArray(); ByteArrayInputStream inputStream = new ByteArrayInputStream(fileArray); return Base64.getEncoder().encodeToString(IOUtils.toByteArray(inputStream)); } catch (Exception ex) { logger.info(ex.getMessage()); return ""; } } logger.info("找不到文件,获取不了文件信息"); return ""; }

上传代码

java
public UpLoadResponse upload(String base64Str, RecTypeDictStorageEntity recTypeDictStorage, ViewArchiveDocumentsEntity viewArchiveDocuments){ UpLoadResponse upLoadResponse=new UpLoadResponse(); //base转输入流 ByteArrayInputStream stream = null; try { byte[] bytes = Base64.getDecoder().decode(base64Str); stream = new ByteArrayInputStream(bytes); } catch (Exception e) { e.printStackTrace(); } InputStream inputStream=stream; FtpUtil ftpUtil = new FtpUtil(); String ftpConfig = "ftp://USER:PWD@IP:PORT"; ftpConfig = ftpConfig.replace("IP", recTypeDictStorage.getFtpIp()) .replace("USER", recTypeDictStorage.getFtpUser()) .replace("PWD", recTypeDictStorage.getFtpPwd()) .replace("PORT", recTypeDictStorage.getFtpPort()); try { logger.info("上传首页 ftp配置:" + ftpConfig); ftpUtil.getConn(ftpConfig); String remoteFile = ftpUtil.getMedDocPath(viewArchiveDocuments.getPatientid(), viewArchiveDocuments.getEpisodeid()); String fileName = MessageFormat.format("{0}_{1}_{2}.pdf",viewArchiveDocuments.getEpisodeid(),viewArchiveDocuments.getDocdesc(),DateUtil.format(new Date(),"yyyy_MM_dd_HH_mm_ss")); boolean result = ftpUtil.fileUpload(remoteFile,fileName, inputStream); upLoadResponse.setResult(result); upLoadResponse.setFileName(fileName); upLoadResponse.setRemoteFile(remoteFile); return upLoadResponse; } catch (Exception e) { logger.info(e.getMessage()); } finally { ftpUtil.ftpDisconnect(); } upLoadResponse.setResult(false); return upLoadResponse; }

通过base64字符串转成输入流,配置好路径地址ip以及端口信息、账号密码等,使用upload方法传输数据

编辑
2023-04-04
遇到的问题
00

注意

只有在编译的时候才会报错很容易忽视

样例

java
List<RecTypeDictEntity> recTypeDictList=recTypeDictEntities.stream().filter(i->i.getRecTypeCode().equals(docitemecode)).collect(Collectors.toList());

看起来好像没什么问题,但是实际上一运行就报错,因为没有对list中的对象属性判断是否为空,直接使用就会出现空指针异常问题

改进

java
List<RecTypeDictEntity> recTypeDictList=recTypeDictEntities.stream().filter(i->StrUtil.isNotBlank(i.getRecTypeCode())&&i.getRecTypeCode().equals(docitemecode)).collect(Collectors.toList());
编辑
2023-04-04
实用工具
00

前提

两个客户端直接都需要注册到同一个网关

引入open Feign依赖

xml
<dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>

配置服务接口

java
@Service @FeignClient("rec-multiple-data-sources") public interface dataSourcesSerive { @GetMapping("/collec/getArchiveDocumentListByInhospNo?inhospNo={No}") List<ViewArchiveDocumentsEntity> getArchiveDocumentListByInhospNo(@PathVariable("No") String inhospNo); }

也可以增加fallback配置,可以避免连接失败导致的错误

java
@FeignClient(name = "haowee-robService", fallback = RobServiceClient.FallBack.class) public interface RobServiceClient { @Component class FallBack implements RobServiceClient { @Override public Map<String, Object> submitRobTask(RobSubTaskReq req) { return null; } } @PostMapping("rob/submitRobTask") @ApiOperation("更改执行计划状态") Map<String, Object> submitRobTask(@RequestBody RobSubTaskReq req); }

@FeignClient("这里面填想调用的服务名称")

启动类上开启feign

@EnableFeignClients

被调用方接口

java
@RequestMapping("/collec") public class ExecutionCollectionController { @Resource private ExecutionCollectionService executionCollectionService; @GetMapping("/getArchiveDocumentListByInhospNo") public List<ViewArchiveDocumentsEntity> getArchiveDocumentListByInhospNo(@RequestParam("inhospNo") String inhospNo){ return executionCollectionService.getArchiveDocumentListByInhospNo(inhospNo); }

方法请求参数注解

  1. 没有参数 没有参数就很简单,只需要使用@GetMapping标识好请求路径就可以了。
@GetMapping("/noParam}") public List<Order> noParam();
  1. 多个基础类型参数 Get 请求多个参数时,需要使用@RequestParam或者@PathVariable注解,这是因为在加载方法元数据的时候,如果该形参没有注解,默认会直接将其放在请求体中,这样GET 请求时就会报错。

而且注解中的value属性必须指定绑定的参数名,不然会报错RequestParam.value() was empty on parameter 0。 案例:

@GetMapping("insert") public List<Order> insertOrder(@RequestParam("accountId") Long accountId, @RequestParam("commodityCode") String commodityCode, @RequestParam("count") Long count, @RequestParam("money") Long money); @GetMapping("id/{id}") public List<Order> id(@PathVariable("id") String id);
  1. 集合数据参数 在Spring MVC使用GET 请求传递集合参数时,需要这么写:
@GetMapping("/noParam") public List<Order> noParam(@RequestParam(list) List<Long> list);

在请求时,URL 集合值使用逗号隔开:

http://localhost:9000/order/noParam?list=22,33,44

在使用Feign 调用时,直接调用就可以了,可以从日志看到,Feign 自动将集合类型的参数进行了解析拼接。

  1. 单个对象参数 当Get 请求参数超过三个时,就需要进行查询参数封装为对象。

上面说到当参数没有注解时,就会放入到请求体中,但是@RequestParam不支持直接传递对象类,这时就需要使用@SpringQueryMap注解,它可以将对象属性及值,转为键值对拼接在URL 后面。

@GetMapping("/get") public Order getOrder(@SpringQueryMap Order order);
  1. 多个对象参数 多个对象参数时,只需要使用多个@SpringQueryMap即可:
@GetMapping("/get") public Order getOrder(@SpringQueryMap Order order,@SpringQueryMap Account account);

多个对象参数加基本类型参数时,只需要添加对应的注解即可,需要注意实体类中的属性和这个基础类型参数名不能相同,不然拼接到URL中,两个同名参数传递过去就会覆盖了。

@GetMapping("/get") public Order getOrder(@SpringQueryMap Order order,@RequestParam("accountId") Long accountId);
  1. 下载文件 下载文件需要注意的是,应该返回二进制数据,还有GET 请求时,需要对URL进行编码,不然会报错编码不符合规范,其他没什么区别。
@GetMapping("/download") public ResponseEntity<byte[]> download(@RequestParam("filePath") String filePath) ;

POST 请求案例 POST 请求一般用于数据提交到服务器,比如添加数据,上传文件等。

  1. 传递单个对象参数 默认形参没有添加注解时,就会放入到请求体中,这个时候会使用编码器,将对象编码,并以Content-Type: application/json形式发送请求,所以只要注意在服务提供者中,添加@RequestBody注解,将请求体转为对象即可。
@PostMapping("addOrder") public Order addOrder(@RequestBody Order order);
  1. 传递多个对象参数 如果像下面这样使用两个@RequestBody,是会报错的:
@PostMapping("addOrderAnd") public Order addOrderAnd(@RequestBody Order order,@RequestBody Account account);

这时候需要将两个对象封装在一个对象中,变成单个对象进行请求传递:

@PostMapping("addOrderAnd") public Order addOrderAnd(@RequestBody AccountAndOrder accountAndOrder);
  1. 上传文件 上传文件时,需要注意的是需要使用@RequestPart注解,Fiegn 会解析这个注解,标记为上传文件请求,还需要指定consumes为MULTIPART_FORM_DATA_VALUE,编码器会根据这个配置,将文件对象进行编码。
@PostMapping(value = "/spring/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE,produces =MediaType.APPLICATION_JSON_VALUE ) @ResponseBody public Object springUpload(@RequestPart("file") MultipartFile file) ;

在调用方,上传文件时,则需要将文件对象转为MultipartFile。

一般不采用Feign 去上传文件,这种方式请求链路比较长,性能很低,一般都是前端直接上传到文件服务器,然后再告诉后台上传了哪个文件。

@GetMapping("/insertOrder") public Object insertOrder() { File file = new File("E:\\javaPro\\prime-code-generator\\pom.xml"); MultipartFile multipartFile =fileToMultipartFile(file); Object o = orderFeign.springUpload(multipartFile); return o; } public static MultipartFile fileToMultipartFile(File file) { String fieldName = "file"; FileItemFactory factory = new DiskFileItemFactory(16, null); FileItem item = factory.createItem(fieldName, "multipart/form-data", true, file.getName()); int bytesRead = 0; byte[] buffer = new byte[8192]; try { FileInputStream fis = new FileInputStream(file); OutputStream os = item.getOutputStream(); while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } return new CommonsMultipartFile(item); }
编辑
2023-04-03
学习记录
00

提示

被调用的方法老是会跟随调用方回滚就算设置各种@transactional失效方式也没有用

@Transactional失效方式可以看我之前的文章

现在先简单实现一下

java
@Transactional(propagation = Propagation.REQUIRES_NEW,noRollbackFor = Exception.class) public void saveRecCallInterfaceLog(RecCallInterfaceLogEntity recCallInterfaceLogEntity) { int reslut= recCallInterfaceLogMapper.insert(recCallInterfaceLogEntity); if (reslut>0){ logger.info("接口调用表更新成功"); }else{ logger.info("接口调用表更新失败"); } }

Propagation.REQUIRES_NEW 是开启新的事务,不和调用方合并成一个,防止被一起回滚。

noRollbackFor = Exception.class 是设置该方法任何异常都不回滚

编辑
2023-03-31
实用工具
00

简介信息

text明文【转】Base64字符串; text的Base64字符串【转】明文; 文件(图片、pdf等)【转】Base64; Base64【转】文件(图片、pdf等); 将pdf的Base64编码格式【转为】img的Base64编码格式,只限最后一页的Base64编码; 将pdf的Base64编码格式【转为】img的Base64编码格式,并将所有页合成一张图片的Base64编码;

需要依赖

一、所需的包 注意:java.util.Base64是JDK1.8中新增的类,所以它只支持JDK1.8及以后的版本,如果你的JDK版本低于1.8,请使用org.apache.commons.codec.binary.Base64.

下面的包,是用于Base64的pdf转img使用的,如果不需要要,可以不引用,并删掉对应的方法(前言中的5和6)。

xml
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>fontbox</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.1</version> </dependency>