不知不觉一个月就过去了,看了四月份的记录真的是惨不忍睹,居然就在四月一日那天跟新了而已,难道后面的日子我都没有学到什么吗,还是自己忘记写了。话不多说,先开始这个月的记录。希望收获满满。
《---------------------------------------2020/5/7-----------------------------------》
开发心得:1、参数校验可以放在controller
一、mybatis-plus 和postgres 插入数据时自增id的问题。
1、插入数据时报数据类型不匹配
解决方法:在实体的自增id里加上id自增的注解 @TableId(type = IdType.INPUT)
但是有一次在主键增加了以上的注解后还是会报同样的错误,于是修改了配置文件,才不报错,type = IdType.INPUT可加可不加,或者是把@TableId(type = IdType.INPUT)修改为@TableId(type = IdType.AUTO)
mybatis-plus.global-config.db-config.id-type=auto
2、插入自增id调动增长,间隔为2,也就是相当于插入了两次,但是以第二次的为准
解决方法:nextval改为currval
<selectKey keyProperty="deviceId" order="AFTER" resultType="java.lang.Integer">
select currval('device_id_seq'::regclass) as deviceId
</selectKey>
3、插入数据后如何获取生成的id,insertSelective()
解决方法:
在xml方法里添加以下代码,AFTER是指先插入数据再获取id,BEFORE是指
<selectKey keyProperty="deviceId" order="AFTER" resultType="java.lang.Integer">
select currval('device_id_seq'::regclass) as deviceId
</selectKey>
二、java利用反射获取值和设置值
1、获取实体字段的值
private Object genericGetter(String field, Object source) {
String getter = "get".concat(upperFirst(field));
Class<?> clazz = source.getClass();
Object code = null;
try {
Method method = clazz.getDeclaredMethod(getter);
code = method.invoke(source);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
return null;
}
return code;
}
2、设置实体字段的值
private static void genericSetter(String field, String value, Object target) {
String setter = "set".concat(upperFirst(field));
Class<?> clazz = target.getClass();
try {
Method method = clazz.getDeclaredMethod(setter, String.class);
method.invoke(target, value);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
}
}
upperFirst()方法是把字符串首字母边大写
private static String upperFirst(String letter){
return letter.substring(0, 1).toUpperCase()+letter.substring(1);
}
最后使用Entity.getDeviceId();
《---------------------------------------2020/5/7-----------------------------------》
开发心得:1、养成习惯在业务逻辑里打日志。log.info();为了以后看日志方便,好排查问题。
《---------------------------------------2020/5/13-----------------------------------》
一、shiro里的登录拦截
当请求/oauth/authorize的时候会被user_login拦截,然后去到UserLoginValidateFilter(),执行里面的onAccessDenied()或者是isAccessAllowed()方法。
以下解释一下AccessControlFilter里面的几个重要的方法:
isAccessAllowed方法和onAccessDenied方法,只要两者有一个可以就可以了,从名字中我们也可以理解,他的逻辑是这样:先调用isAccessAllowed,如果返回的是true,则直接放行执行后面的filter和servlet,如果返回的是false,则继续执行后面的onAccessDenied方法,如果后面返回的是true则也可以有权限继续执行后面的filter和servelt。只有两个函数都返回false才会阻止后面的filter和servlet的执行
preHandler:类似于AOP中的前置增强;在拦截器链执行之前执行;如果返回true则继续拦截器链;否则中断后续的拦截器链的执行直接返回;进行预处理(如基于表单的身份验证、授权)
postHandle:类似于AOP中的后置返回增强;在拦截器链执行完成后执行;进行后处理(如记录执行时间之类的);
afterCompletion:类似于AOP中的后置最终增强;即不管有没有异常都会执行;可以进行清理资源(如接触Subject与线程的绑定之类的);
二、通过session判断是不是同一个会话,通过session判断用户登录
1、登录成功后设置userId到session,返回浏览器。二次请求时通过获取session来判断用户是否登录。
设置session里的属性
Object userIdObj = WebUtils.getSessionAttribute(request, SessionConfig.ATTRIBUTE_USER_ID);
获取session里的属性
Object userIdObj = WebUtils.getSessionAttribute(request, SessionConfig.ATTRIBUTE_USER_ID);```