1.如果有对象返回已有对象,没有创建新对象
QuesionnairResult result = this.get(id).map(QuesionnairMapper.INSTANCE::toResult).orElseGet(QuesionnairResult::new);
2.类加上 @Transactional(readOnly = true)只读数据
创建更新删除方法加上 表示异常就回滚
@Transactional(rollbackFor = Exception.class)
3.流式计算的坑,属性名需要大小(注解是mybatis的名字)不然得不到属性
@Column(name = "q_title")private String QTitle;weekendCriteria.andEqualTo(Quesionnair::getQTitle, "用车");
4.命名规范不要 一个字母加一个单词,这样lombok生成错误 qTitle(x) quesTitle(对)
5.代理生成的代码需要清除后运行,特别是实体类名字更改,导致其他实体类名字也更改,转换实体类生成的代码出错
git需要打钩再把时间提交上去
6.swagger访问页面是http://localhost:8080//swagger-ui/index.html#/
7.判断字符串先判断null,后判断空
if ( param.getTitle() != null && !(param.getTitle()).equals("") ) {
8.springmvc识别不出date对象,使用字符串最方便
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private String createTime; //而且mybatis支持
9.jrebel 注解和静态页面刷新不了需要重启
10.使用雪花策略,比自增长好,可以解决分布式自增长导致id重复的问题
public class BaseAutoIdEntity extends BaseEntity {@Id@KeySql(genId = CustomerIdGenerator.class)private Long id;public BaseAutoIdEntity(Long id) {this.id = id;}public Long getId() {return this.id;}public void setId(final Long id) {this.id = id;}public boolean equals(final Object o) {if (o == this) {return true;} else if (!(o instanceof BaseAutoIdEntity)) {return false;} else {BaseAutoIdEntity other = (BaseAutoIdEntity)o;if (!other.canEqual(this)) {return false;} else {Object this$id = this.getId();Object other$id = other.getId();if (this$id == null) {if (other$id != null) {return false;}} else if (!this$id.equals(other$id)) {return false;}return true;}}}protected boolean canEqual(final Object other) {return other instanceof BaseAutoIdEntity;}public int hashCode() {int PRIME = true;int result = 1;Object $id = this.getId();int result = result * 59 + ($id == null ? 43 : $id.hashCode());return result;}public String toString() {return "BaseAutoIdEntity(id=" + this.getId() + ")";}public BaseAutoIdEntity() {}
}
//继承即可,不能写id字段,因为父类已经指定了
11.前端拉取项目需要用 全局安装git,package-lock.json要删除不然安装不了
12.注解可能导错包 导致传不了数据
@RequestBody
13.以前数据库自增长id想返回 需要写配置文件和mapper,雪花id恰好解决问题 可自己手动生成根据表和列名
//雪花自增长
CustomerIdGenerator customerIdGenerator = new CustomerIdGenerator();
Long aLong = customerIdGenerator.genId("q_useranswer", "id");
qUseranswerSaveParam.setId(aLong);
//mysql自带的自增长
<insert id="insertAdvantage" parameterType="SysAdvantage" useGeneratedKeys="true" keyProperty="advantageId">insert into sys_advantage(<if test="advantageId != null and advantageId != 0">advantage_id,</if><if test="advantageName != null and advantageName != ''">advantage_name,</if><if test="advantageSort != null and advantageSort != ''">advantage_sort,</if><if test="status != null and status != ''">status,</if><if test="remark != null and remark != ''">remark,</if><if test="createBy != null and createBy != ''">create_by,</if>create_time)values(<if test="advantageId != null and advantageId != 0">#{advantageId},</if><if test="advantageName != null and advantageName != ''">#{advantageName},</if><if test="advantageSort != null and advantageSort != ''">#{advantageSort},</if><if test="status != null and status != ''">#{status},</if><if test="remark != null and remark != ''">#{remark},</if><if test="createBy != null and createBy != ''">#{createBy},</if>sysdate())</insert>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 全局参数 --><settings><!-- 使全局的映射器启用或禁用缓存 --><setting name="cacheEnabled" value="true" /><!-- 允许JDBC 支持自动生成主键 --><setting name="useGeneratedKeys" value="true" /><!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 --><setting name="defaultExecutorType" value="SIMPLE" /><!-- 指定 MyBatis 所用日志的具体实现 --><setting name="logImpl" value="SLF4J" /><!-- 使用驼峰命名法转换字段 --><!-- <setting name="mapUnderscoreToCamelCase" value="true"/> --></settings></configuration>
14.动态sql判断int是否为空
<!-- 判断 int 类型参数是否为空 -->
<if test="param != null and param != 0"><!-- 如果参数不为空,则执行相应的 SQL 语句 -->#{param}
</if>
15.加密方式
1.对称加密 用相同的秘钥加密解密 DES AES2.非对称加密 使用公钥加密 私钥解密 3.散列加密 MD5 SHA 不可逆 4.消息认证码 MAC 秘钥和消息生成固定长度的字符串,验证信息完整性和真实性 HMAC5.数字签名 私钥加密 公钥解密, 也属于一种特殊的对称加密
//注意,长度必须是16的倍数,使用hash不影响原来位数,和hash配合使用
//我使用了AES(DES的升级)分块加密
//使用MD5和AES混合加密
public class AESUtil {private static final String ALGORITHM = "AES";public static String encrypt(String data,String md5Key) throws Exception {SecretKeySpec keySpec = new SecretKeySpec(md5Key.getBytes(), ALGORITHM);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, keySpec);byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(encryptedBytes);}public static String decrypt(String encryptedData,String md5Key) throws Exception {SecretKeySpec keySpec = new SecretKeySpec(md5Key.getBytes(), ALGORITHM);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, keySpec);byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));return new String(decryptedBytes, StandardCharsets.UTF_8);}public static void main(String[] args) throws Exception {String originalData = "Hello, World!xxxxxx";System.out.println("Original Data: " + originalData);String s = MD5Utils.md5Hex(originalData.getBytes());String s1 = MD5Utils.md5Hex(s.getBytes());String encryptedData = AESUtil.encrypt(originalData,s1);System.out.println("Encrypted Data: " + encryptedData);String decryptedData = AESUtil.decrypt(encryptedData,s1);System.out.println("Decrypted Data: " + decryptedData);}
}
public class AESKeyGenerator {public static String generateAESKeyFromUUID() {UUID uuid = UUID.randomUUID();ByteBuffer bb = ByteBuffer.wrap(new byte[16]);bb.putLong(uuid.getMostSignificantBits());bb.putLong(uuid.getLeastSignificantBits());byte[] keyBytes = bb.array();SecretKeySpec aes = new SecretKeySpec(keyBytes, "AES");return bytesToHex(aes.getEncoded());}public static void main(String[] args) {String s = AESKeyGenerator.generateAESKeyFromUUID();System.out.println(s);}private static String bytesToHex(byte[] bytes) {StringBuilder result = new StringBuilder();for (byte b : bytes) {result.append(String.format("%02X", b));}return result.toString();}
}
16.对数据库数据进行加密,废掉了mysql的模糊查询功能? 敏感的加密数据需要查询(特殊情况可能需要使用触发器解决,最后使用了加密较为隐私的手机号)
17.git查询代码量,直接在gitlab查看变化数量,git的指定了但是不能查(查出了全部代码)
18.前端想要post发送请求,后端请求题接收不到get的参数,用rest风格可以
19.跨域,访问任何路径都会200,需要debug
20.以字段名perPage 为准,注解名字无效的
public class PageableParam {("页码,不传是默认为1")private Integer page = 1;("每页数量,不传是默认为10")("per_page")private Integer perPage = 10;
- pom文件设置仓库(实用)
<repositories><repository><id>aliyunmaven</id><name>Aliyun Maven Repository</name><url>https://maven.aliyun.com/repository/public</url></repository>
</repositories>
22.给前端最好提供内网穿透效率比较高(免费内网穿透的网站)
//网上有大量教程
https://ngrok.com/