项目总结-01
1、数据库标准:
**更新时间的默认设置:不要让数据库来控制。** 不要让数据脱离自己的控制
2、 创建时间和更新时间,用mybatis plus的handler进行统一管理。
@Component public class MyHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.setFieldValByName("updateTime", new Date(), metaObject); this.setFieldValByName("createTime", new Date(), metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime", new Date(), metaObject); }
3.、更新的原理。
<if 某个自段!=null>
某个字段= #{字段的值}
</if>
4、我们接受前端的参数一般用dto 放到dto的包下。 vo是后端返回给前端。
5、在注册的时候,防止重名。1、可以在数据库使用唯一索引 2、在前端做校验(先查询后插入)
6、密码不能明文存储,防止被托库。必须要托名,去除敏感信息(密码,手机号,身份证等)。密码建议使用非对称加密, 手机号,身份证使用对称加密。
MD5 hash算法。 ----非对称加密。 可以通过彩虹表破解。 密码生成的hash值是固定的。
一般建议用:我们可以通过bean对象处理。
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); //加密 String encode = bCryptPasswordEncoder.encode(m); //解密 boolean matches = bCryptPasswordEncoder.matches(m, encode);
7、关于dto 与do vo的关系 我们接受一般称作为dto 返回页面一般用vo 各种o之间不要用继承。
8、统一返回值
{
"code":状态码,
"msg":"信息提示",
"data": T
}
data:object 或者 list
9、参数校验。有非空校验 email格式校验 长度校验
导入包:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
10、统一异常处理:
1、分参数校验异常和统一异常。在统一异常里还可以区分各个细节。
@ControllerAdvice public class ValidateHandler extends ResponseEntityExceptionHandler { @Override protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors(); StringBuilder builder = new StringBuilder(); fieldErrors.stream().forEach(x->builder.append("参数:").append(x.getField()).append("错误信息:").append(x.getDefaultMessage())); return new ResponseEntity<>(new ResultWrapper<>().setCode(110).setMessage(builder.toString()),HttpStatus.OK); } } /** * 统一异常处理 * 处理逻辑为首先进行参数校验 参数校验有异常到统一处理这看看有没有异常 * 有的话直接捕获 * 没有的话进入到validateHandler里面捕获信息 * 然后程序到controller里面执行,有异常直接捕获。 * * */ @RestControllerAdvice public class GlobleException { @ExceptionHandler(ArithmeticException.class) public ResultWrapper customException(){ return new ResultWrapper().setCode(301).setMessage("统一异常"); } }
11、在接口中,能用Integer就用。不用int。Integer代表没有参加考试,int表示考试的分数为0
12、重写父类的快捷键 ctrl+o
13、前端到后端校验发展
在单体项目的时候,我们可以登录到后端以后,后端会生成一个jessionid到前端,前端存起来。然后每次前端请求,把jessionId带过去。然后校验。后来有了多台服务器以后,那么把sessionid存放到第三方,比如说redis里。然后每次取redis查询校验。
由此这样做不便于水平扩张。由于没有带的jessionId是由状态的。
由此有了token。我们每次只管发送请求,一视同仁。jwt
14、jwt生成token
在jwt生成的token时我们可以通过解码工具可以看到加密的内容。此图可以看到token分为三部分。第一部分header是 加密的算法 第二部分是加密的内容。这两部分都是通过base64进行了编码,所以可以解码看到。
第三部分是通过 第一部分的算法进行了(第二部分内容+盐)生成了非对称的密钥然后通过64为编码以后生成的字符串(我们可以把这部分称为签名)
15、常见的加密算法 非对称加密就是生成一堆公钥和私钥密钥对。然后公钥加密 私钥解密。 对称加密就是通过同样的密钥进行加解密。 散列算法是不可逆的。 base64 是编码规则。
md5 不可逆。sha系列。
Base64 是编码器,可以编码,可以解码。
散列算法:md5,sha 系列。
对称加密:DES,3DES,AES
非对称加密:公加私解,私加公解。
16、生成token的工具类: 可以设置token的过期时间。
public static String createToken(String subject){ String token = Jwts.builder().setSubject(subject) .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) .signWith(SignatureAlgorithm.HS256, secret) .compact(); return token; } public static String parseToken(String token){ Claims body = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); String subject = body.getSubject(); return subject; }
17、将key -value格式字符串转为转换为map
map = JSONObject.parseObject(JSONObject.toJSONString(object), Map.class);
18、怎么来不断刷新token的有效期呢?
1、我们可以每次请求需要接口的时候,都返回一个最新的token,再次请求的时候把最新的token带过来,那么可以实现一直刷新token的有效期,这样就会实现性能较低,因为会有很多token。
2、我们可以把token设置为永久有效,然后把token放到redis里面。每次请求来的时候,去redis看看token是否有效,如果有效,重新设置token的有效期。达到token一直不失效的效果。
19、对某些修改接口需要鉴权,查询token是否过期?通过拦截器或者aop来实现。然后通过统一异常类来处理。
20、单点登录:就是一个设备登录以后,别的系统也可以登录。两个系统共享jwt的密钥,这个密钥可以放到redis里来实现。 还有一种单点登录的理解:就是只有一个设备可以登录。
21、token续期模型:
21、spring 提供了两个反射类可以操作
Spring AnnotationUtils AnnocationElementUtils
22. 注解
@RequiredArgsConstructor和@NonNull可以指定构造方法 @NoArgsConstructor指定无参构造方法
可以在类中指定get方法判断返回指定的结果:
通过构造方法,出入不同的枚举,返回不同的时间
public double getTotalTime() { double seconds = 0; switch (chargingCategoryEnum) { case Forecast: seconds = route.getDuration(); break; case Settlement: seconds = Duration.ofMillis(order.getPassengerGetoffTime().getTime() - order.getReceivePassengerTime().getTime()).getSeconds(); break; case RealTime: seconds = Duration.ofMillis(currentPriceRequestDto.getEndTime() - currentPriceRequestDto.getStartTime()).getSeconds(); break; default: break; } return seconds; }
23. @SneakyThrows注解 是解决throws Exception抛出的问题。
24. String转为json对象的问题
String ruleJson = orderRuleMirror.getRule(); log.info("orderId={}, RuleJson={}", orderId, ruleJson); ObjectMapper objectMapper = new ObjectMapper(); rule = objectMapper.readValue(ruleJson, Rule.class);
25. 通过:区分获取指定类型的key。通过不同的常量组装为不同的rediskey
/**
* 生成redis的key
*
* @param orderId 订单ID
* @return redis的key
*/
private String generateKey(Integer orderId) {
return String.format("%s:%s:%s", OrderRuleNames.PREFIX, OrderRuleNames.RULE, orderId);
}
26.将对象转为字符串 和25一样便于反序列化
mapper.writeValueAsString(rule)
本文来自博客园,作者:Jerry&Ming,转载请注明原文链接:https://www.cnblogs.com/jerry-ming/articles/16155555.html