1.Dozer
这是一个在网上视频里不会看到的一个工具包,在该项目中用于做数据对象映射,
一个映射的框架在一个分层的体系架构中非常有用,特别是你在创建一个抽象的分层去包装一些特殊数据的变化 vs 这些数据传输到其它层(外部服务的数据对象、领域的数据对象、数据传输对象、内部服务数据对象)。因此一个映射框架非常适合于使用在映射器类型的类中,负责将数据从一个数据对象映射到另一个数据对象。
1.1Dozer的封装类
项目组又将它进行了一层封装,从中我又学到了一种写法,
可以不将工具类全部静态化,只将我们要使用的方法静态化,通过创建静态实例化对象,如下图所示
package com.etl.commons.dozer;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
@Component
public class Dozer {
private static Mapper dozerMapper;
@Autowired
private Mapper mapper;
public Dozer() {
}
public Mapper getMapper() {
return this.mapper;
}
@PostConstruct
private void construct() {
setDozerMapper(this.mapper);
}
private static void setDozerMapper(Mapper dozerMapper) {
Dozer.dozerMapper = dozerMapper;
}
@NonNull
public static <T> T convert(@NonNull Object source, @NonNull Class<T> clazz) {
return dozerMapper.map(source, clazz);
}
@Nullable
public static <T> List<T> convert(@Nullable List<?> source, @NonNull Class<T> clazz) {
return (List)((List)Optional.ofNullable(source).orElse(Collections.emptyList())).stream().map((bean) -> {
return dozerMapper.map(bean, clazz);
}).collect(Collectors.toList());
}
}
1.2 @Postconstruct注解
@PostConstruct说明:
加上该注解的方法会在项目启动的时候执行,可以理解为Spring容器在对类自动初始化全局的单一实例的过程中,执行完一个Bean的构造方法后会执行该Bean的@PostConstruct方法(如果有),然后初始化下一个Bean。可作为一些数据的常规化加载,比如数据字典之类的。
被@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行
一般加载顺序
@PostConstruct和@Autowired、构造函数的执行顺序
构造方法 > @Autowired > @PostConstruct
@PostConstruct注意事项:
被注解方法不得有任何参数;
被注解方法返回值为void;
被注解方法不得抛出已检查异常;
被注解方法需是非静态方法;
此方法只会被执行一次;
耗时长的逻辑可放到独立线程中执行,减少Spring容器初始化时间
原文链接:https://blog.csdn.net/libralee233/article/details/122681608
1.3 函数式编程
在该自定义工具类里,他分别提供了单个对象和list对象的处理,其中list的处理方法值得我学习,通过Optional.ofNullable(source).orElse(Collections.emptyList()判断list是否为空,为空则返回一个空的list,从而不会出现空指针异常
2.S3存储库
S3是亚马逊旗下的对象存储服务
2.1官方获取所有对象信息代码实例
public static void listBucketObjects(S3Client s3, String bucketName ) {
try {
ListObjectsRequest listObjects = ListObjectsRequest
.builder()
.bucket(bucketName)
.build();
ListObjectsResponse res = s3.listObjects(listObjects);
List<S3Object> objects = res.contents();
for (S3Object myValue : objects) {
System.out.print("\n The name of the key is " + myValue.key());
System.out.print("\n The object is " + calKb(myValue.size()) + " KBs");
System.out.print("\n The owner is " + myValue.owner());
}
} catch (S3Exception e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
//convert bytes to kbs.
private static long calKb(Long val) {
return val/1024;
}
2.2 S3ObjectSummary类源码
通过一下源码我知道了在我们项目总的getall接口实则是在获取所有存储对象的信息的key
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.amazonaws.services.s3.model;
import java.io.Serializable;
import java.util.Date;
public class S3ObjectSummary implements Serializable {
protected String bucketName;
protected String key;
protected String eTag;
protected long size;
protected Date lastModified;
protected String storageClass;
protected Owner owner;
public S3ObjectSummary() {
}
public String getBucketName() {
return this.bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
public String getKey() {
return this.key;
}
public void setKey(String key) {
this.key = key;
}
public String getETag() {
return this.eTag;
}
public void setETag(String eTag) {
this.eTag = eTag;
}
public long getSize() {
return this.size;
}
public void setSize(long size) {
this.size = size;
}
public Date getLastModified() {
return this.lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
public Owner getOwner() {
return this.owner;
}
public void setOwner(Owner owner) {
this.owner = owner;
}
public String getStorageClass() {
return this.storageClass;
}
public void setStorageClass(String storageClass) {
this.storageClass = storageClass;
}
public String toString() {
return "S3ObjectSummary{bucketName='" + this.bucketName + '\'' + ", key='" + this.key + '\'' + ", eTag='" + this.eTag + '\'' + ", size=" + this.size + ", lastModified=" + this.lastModified + ", storageClass='" + this.storageClass + '\'' + ", owner=" + this.owner + '}';
}
}
2.3自定义获取所有S3存储对象key的接口
public List<String> getAll() {
AmazonS3 client = this.createClient();
//我猜测是这句向S3服务器发送请求获取信息 /狗头
ObjectListing objectListing = client.listObjects(new ListObjectsRequest().withBucketName(options.getBucketName()));
//这句是获取S3对象信息变成列表
List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
//这句是获取S3对象的key
return objectSummaries.stream().map(e -> e.getKey()).collect(Collectors.toList());
}
2.4下载文件后返回给前端
该代码通过key将文件下载下来之后用hutool工具类将文件转化成字节流,再将文件放入响应体中回传给前端
@Override
public void download(HttpServletResponse response, String fileKey) {
try {
InputStream inputStream = s3FileManage.download(fileKey);
byte[] bytes = IoUtil.readBytes(inputStream);
OutputStream outputStream = response.getOutputStream();
/*String filename = fileKey.substring(fileKey.lastIndexOf("/"));
OutputStream outputStream = new FileOutputStream("C://Workspace//" + filename);*/
IoUtil.write(outputStream, true, bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
3.@Transactional的默认回滚错误类型
spring的@Transactional注解可以很方便的开启事务,但是默认只在遇到运行时异常和Error时才会回滚
4.从程序的任何地方拿到token
目前我对下面代码的看法是可以从请求的任何地方拿到该请求的请求头
private String getHeaderAttributes(String header) {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
return request.getHeader(header);
}
Function.identity()
返回他自己,相当于t -> t 一般再stream流中使用
https://blog.csdn.net/m0_45899013/article/details/118542159
Collectors.toMap()
使用toMap()函数之后,返回的就是一个Map了,自然会需要key和value。
toMap()的第一个参数就是用来生成key值的,第二个参数就是用来生成value值的。
第三个参数用在key值冲突的情况下:如果新元素产生的key在Map中已经出现过了,第三个参数就会定义解决的办法。
在.collect(Collectors.toMap(Person::getId, v -> v, (a,b)->a))中:
第一个参数:Person:getId表示选择Person的getId作为map的key值;
第二个参数:v->v表示选择将原来的对象作为Map的value值
第三个参数:(a,b)->a中,如果a与b的key值相同,选择a作为那个key所对应的value值。
原文链接:https://blog.csdn.net/qq_38826019/article/details/109401567
System.gc()
让JVM进行垃圾回收,但是只回收应该回收的
简单工厂+配置文件解除耦合
配置文件 该文件的名称为下面的bean.properties
american=org.example.config_factory.AmericanCoffee
latte=org.example.config_factory.LatteCoffee
工厂类
package com.itheima.pattern.factory.config_factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Properties;
import java.util.Set;
public class CoffeeFactory {
//加载配置文件,获取配置文件中配置的全类名,并创建该类的对象进行存储
//1,定义容器对象存储咖啡对象
private static HashMap<String,Coffee> map = new HashMap<String, Coffee>();
//2,加载配置文件, 只需要加载一次
static {
//2.1 创建Properties对象
Properties p = new Properties();
//2.2 调用p对象中的load方法进行配置文件的加载
InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
p.load(is);
//从p集合中获取全类名并创建对象
Set<Object> keys = p.keySet();
for (Object key : keys) {
String className = p.getProperty((String) key);
//通过反射技术创建对象
Class clazz = Class.forName(className);
Coffee coffee = (Coffee) clazz.newInstance();
System.out.println("className");
//将名称和对象存储到容器中
map.put((String)key,coffee);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//根据名称获取对象
public static Coffee createCoffee(String name) {
return map.get(name);
}
}