一、跨域 CorsConfig
package com.wang.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOrigins("http://localhost:8080","http://localhost:5175","http://127.0.0.1:8080", "http://172.16.10.200:8081", "http://172.16.10.201:8081")
// 设置允许的请求方式
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// 设置允许的header属性
.allowedHeaders("*")
// 是否允许cookie
.allowCredentials(true)
// 设置允许跨域的时长
.maxAge(3600);
}
}
2.DateUtils
package com.wang.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author: WANGZI
* @Date: 2023/5/24 14:01:53
*/
public class DateUtils {
/**
* 时间返回字符串 做文件名
*/
public static String getDateStringFileName() {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd-HH.mm.ss");
// 设置时区为中国标准时间
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
String format = simpleDateFormat.format(date);
return format;
}
/**
* 时间返回字符串
*/
public static String getDateString() {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 设置时区为中国标准时间
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
String format = simpleDateFormat.format(date);
return format;
}
/**
* 时间返回Date
*
* @return
*/
public static Date getDate() {
Date date = new Date();
return date;
}
}
3.对象映射器 JacksonObjectMapper
package com.wang.utils;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
4. 返回对象 R / ResponseEntity(spring默认使用fackjson)
package com.wang.utils;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
/**
* 通用返回结果,服务端响应的数据最终都会封装成此对象
* @param <T>
*/
@Data
public class R<T> {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
private Map map = new HashMap(); //动态数据
public static <T> R<T> success(T object) { //成功方法
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) { //失败方法
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) { //操作动态数据
this.map.put(key, value);
return this;
}
}
//alibaba fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.19.graal</version>
</dependency>
6.logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- <property name="LOG_HOME" value="/SoftwareHeiMa/IdeaProject/WorkProject/cleartbluserintensivepositiontype/log/name_%d{yyyy-MM-dd}_log"/>-->
<property name="LOG_HOME" value="./log/bigDataUtils_%d{yyyy-MM-dd}_log"/>
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%thread] [%-30.30logger{30}] %msg%n"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%magenta(%date{yyyy-MM-dd HH:mm:ss.SSS}) %highlight([%-5level]) %green(${PID:- }) %blue([%thread]) %cyan(%-30logger{50}) %boldMagenta(--->) %boldYellow(%msg) %n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/name1_%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%thread] %logger{50} - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<logger name="org.springframework" level="INFO"/>
<logger name="com.hl.magic" level="INFO"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
7.BeanUtils由于不支持深拷贝对象中的对象,使用MapStruct替代
<!-- MapStruct依赖替代beanUtils-->
<!-- MapStruct依赖-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<!-- MapStruct 注解处理器-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
<scope>provided</scope>
</dependency>
定义MapStruct映射接口
package com.wang.domain.mapStruct;
import com.wang.domain.ExamType;
import com.wang.domain.ExamTypeVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.lang.annotation.Target;
/**
* @Author: WANGZITAO
* @Msg:
*/
@Mapper
public interface ExamTypeStruct {
ExamTypeStruct INSTANCE = Mappers.getMapper(ExamTypeStruct.class);
@Mappings({
@Mapping(target = "id", source = "id"),
@Mapping(target = "username", source = "name"),
@Mapping(target = "description", source = "description"),
})
//source 转 target
ExamTypeVO toTarget(ExamType source);
/*
1.将映射一个值到目标对象的 username 属性上。
source: source 属性指定了源对象中的一个属性或方法。这个属性或方法的值将被转换或映射到目标对象的指定属性上。
@Mapping(target = "username", source = "name")
2.将源对象的 name 属性的值映射到目标对象的 username 属性上。
如果源和目标属性的名字相同,你可以省略 source 属性,MapStruct 会自动匹配。
@Mapping(target = "username")
将源对象的 username 属性的值映射到目标对象的 username 属性上,因为它们的名字相同,所以可以省略 source 属性。
*/
}
/*
也可以在MapStruct映射接口中中写上方法实现转换指定操作逻辑
*/
package com.wang.domain.mapStruct;
import com.wang.domain.ExamType;
import com.wang.domain.ExamTypeVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.lang.annotation.Target;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
* @Author: WANGZITAO
* @Date: 2024/8/28 10:41
* @E-mail: wzt_coder@163.com
* @Msg:
*/
@Mapper
public interface ExamTypeStruct {
ExamTypeStruct INSTANCE = Mappers.getMapper(ExamTypeStruct.class);
@Mappings({
@Mapping(target = "sourceDate", source = "targetDate",expression = "java(source.getTargetDate())")
})
ExamTypeVO toTarget(ExamType source);
//实现需要的转换逻辑
default LocalDate formatDate(String sourceDate) {
//实现需要的转换逻辑,其他属性同理
return LocalDate.parse(sourceDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
}
//方法使用
ExamTypeVO target = ExamTypeStruct.INSTANCE.toTarget(examType);
target.getName();