广行天下车GO项目经验

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 AES
   2.非对称加密 使用公钥加密 私钥解密 
   3.散列加密 MD5 SHA 不可逆 
   4.消息认证码 MAC 秘钥和消息生成固定长度的字符串,验证信息完整性和真实性 HMAC
   5.数字签名 私钥加密 公钥解密, 也属于一种特殊的对称加密

//注意,长度必须是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;
  1. 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/

你可能感兴趣的:(微服务,后端,微服务,Java)