1.如果对精度要求不高的情况下使用如下方式获得系统时间戳。原理连接
System.out.println(LocalDateTime.now());
2.如果需要获得格式化的时间,或者将字符串转换成日期格式,按如下方式进行书写。原理连接
public class TestMain {
public static final DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
public static void main(String[] args) {
String test=TestMain.dateTimeFormatter.format(LocalDateTime.now());
System.out.println(test);
}
3.在线程中可以使用threadlocal放置线程中共享的信息。
public class UserInfoThreadlocal {
private static final ThreadLocal<Long> threaslocal = new ThreadLocal<>();
public static void put(Long userId) {
remove();
threaslocal.set(userId);
}
public static Long get() {
return threaslocal.get();
}
public static void remove() {
threaslocal.remove();
}
}
这是本人在项目中使用的方式,在对jwt进行权限验证通过以后会将一些线程共享的信息放入ThreadLocal中,springsecurity实际上使用的也是threadlocal进行权限验证。
4.为了让事务机制起作用,当service调用service方法的时候选择创建新的service,例如AService非事务方法需要调用事务方法,则创建一个Bservice,然后将BService注入到AService中。
5.数据库中的小数使用Decimal,mysql中的Decimal采用的是字符串存贮的方式,在java中使用BigDecimal进行运算,BigDecimal底层使用BigInt存储数据,BigInt使用int[]数组来存储数据。
6.可以使用枚举类定义常量。
public enum TransStatusEnum {
SUCCSEE(10, "交易成功"),
LOADING(20, "交易中"),
FAIL(30, "交易失败"),
CancelOrder(40,"撤单"),
OrderFinish(50, "售卖结束");
private Integer status;
private String desc;
private TransStatusEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public static TransStatusEnum getEnumByStatus(Integer code) {
for (TransStatusEnum temp : TransStatusEnum.values()) {
if (code == temp.getStatus()) {
return temp;
}
}
return TransStatusEnum.LOADING;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static String getDesc(Integer i){
return getEnumByStatus(i).getDesc();
}
}
7.使用拦截器和注解结合的方式来完成业务。
/**
* 不校验token
* @see
*/
@Documented
@Inherited
@Target({
ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoVerificationToken {
}
@Component
@Slf4j
public class TokenInterceptor extends HandlerInterceptorAdapter {
@Autowired
private TokenService tokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 获取方法上的注解
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
PenguinLogThreadLocal.remove();
if (method.isAnnotationPresent(NoVerificationToken.class)) {
return true;
}
8.使用一次性token来防止接口的幂等性
@PostMapping("/repeatLimNo")
@ApiOperation(value = "获取请求序列", notes = "获取请求序列--拦截重复请求")
public Outcome<String> getToken(@RequestHeader(value = "token") String token, HttpServletRequest request) {
return Outcome.success("", repeatLimiterSeq.generateSeq());
}
该接口返回一个唯一的请求序列放在redis中,请求一次失效,在需要防止接口幂等性的接口上传送,且该字段为必传字段。
@Override
public String generateSeq() {
//使用UUID生成 token
String token = UUID.randomUUID().toString();
token=token.replaceAll("-","");
//存入Redis,key:token,过期时间10分钟
redisUtil.set("repeatLimNo::"+token,token,20*60);
PenguinLogThreadLocal.setParam(token);
return token;
}