经过了昨天纠结技术选型,和一大堆xml配置,终于把架子搭好了。因为最近一次做java项目也在好多年以前了(毕竟用了pytohn以后谁也不想再回来java了),java的生态发生了长足的进步,本来想从原来的项目里面拿过来一些,发现除了java还剩下一点兼容性,其他的基本都淘汰了。太悲剧了!连个轮子都没。边学边做吧!好在几个月前又背了一次java课,虽然一些新技术看文档还能应付。spring虽然有改变但是也不大,mybatis也还能凑合用。开始码代码才发现一个非常悲剧的问题。tomcat依然不支持热加载,这肯定是不行了,必须解决。因为ssm的各种依赖加起来几十个包,修改个东西跑起来既然要20多秒 。写代码的时间都没加载的时间长好吧?于是网上开始找,虽然东西多但是哥一个都没成功,有因为依赖的,有版本的,话说这个java都用上maven了为啥版本管理还是这么烂,不过也不能埋怨java,其实在版本管理上其他语言也都是一丘之貉!!于是乎发现了jetty这个货,正好没用过,对于我这样的尝鲜党必须试试,经过一番折腾终于搞定了,鉴于版本和jar包的版本问题,至少这个我的配置成功了!

 <build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.7.RC0</version>
<configuration>
<!--自动扫描文件改变并进行热部署的时间间隔,单位为秒。默认值为0,这代表着禁用扫描并热部署,只有一个大于0的配置可以使它生效。-->
<scanIntervalSeconds>10</scanIntervalSeconds>
<!--可选择的配置,如果没有设置,Jetty将创建ServerConnector实例来监听8080端口。-->
<httpConnector>
<!--port:连接监听的端口,默认8080;-->
<port>8080</port>
</httpConnector>
<webApp>
<!--你web应用的根路径(访问路径)。默认设置为“/”,如果你可以设置一个路径在“/”下面,例如/mycontext-->
<contextPath>/exam</contextPath>
</webApp>
<!-- scanTargetPatterns 可选。如果你想扫描有一长串的额外文件,通过使用模式匹配表达式制定它们更加方便,它可以用来替代 <scanTargets>参数的枚举展示。这个参数包含一组<scanTargetPattern>。每一个都是由一个<directory>和<includes>[或者<excludes>]参数来指定文件的匹配模式。-->
<scanTargetPatterns>
<scanTargetPattern>
<directory>src/main/webapp</directory>
<excludes>
<exclude>**/*.jsp</exclude>
</excludes>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</scanTargetPattern>
</scanTargetPatterns>
<!-- 设置系统属性
你可以为插件的执行操作按name/value成对的方式指定系统属性。 在别的文件中 通过 ${configuration.path} 取值--> </configuration>
</plugin>

修改以后idea按ctrl+f9即可重新构建,终于不用重新启动容器了。然后开始增删查改起来!
  毕竟是java一定都不虚,这玩意依然是所有语言里最繁琐的。撸两个页面已经好半天了。如果可以尽量推荐你用python,或者note.js。不要浪费生命!在写表insert的时候有个createTime字段,基本上每个表都有着字段,一个一个赋值有觉得太麻烦,也是想到python里面有装饰器这样的工具可以搞定这样的需求,那java中注解和装饰器差不多会不会有相应的解决 方法呢!goole一圈果然有,就是定义注解方式,然后在mybatis里面增加一个拦截器,拦截到以后使用反射机制拿到被注解的字段设置属性。东西不多,但是是一个很好地解释注解使用方式以及反射的好例子。这里贴上来,以后可以回顾看看!

//定义注解  
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateTime {
String value() default "";
} @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface UpdateTime{
String value() default "";
}
//部分代码  在需要写入时间的字段上添加自己定义的注解

   private String email;
private String phoneNum;
@CreateTime //我是注解 对 我
private Date createTime;
private String createTimeStr;
private int createBy;
private int fieldId;
private String fieldName;
private Date lastLoginTime;
private String lastLoginTimeStr;
import org.aopalliance.intercept.Invocation;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.lang.reflect.Field;
import java.util.Date;
import java.util.Properties; // 这个必须把引入的包也展示出来 因为我刚开始就引包错了 如果用的同学尽量看仔细
//Object parameter = invocation.getArgs()[1]; 获取执行对象
// 通过反射获取对象所有的Field
// 遍历所有Field,查看是否有指定注解
// 如果有@CreateTime或者@UpdateTime注解,则设置最新时间 @Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class CustomInterceptor implements Interceptor { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Override
public Object intercept(org.apache.ibatis.plugin.Invocation invocation) throws Throwable { MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; // 获取 SQL 命令
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); // 获取参数
Object parameter = invocation.getArgs()[1]; // 获取私有成员变量
Field[] declaredFields = parameter.getClass().getDeclaredFields(); for (Field field : declaredFields) {
if (field.getAnnotation(CreateTime.class) != null) { //如果注解上CreateTime
if (SqlCommandType.INSERT.equals(sqlCommandType)) { // insert 语句插入 createTime
System.out.println("经过");
field.setAccessible(true);
field.set(parameter, new Date());
}
} if (field.getAnnotation(UpdateTime.class) != null) { // insert 或 update 语句插入 updateTime
if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
field.setAccessible(true);
field.set(parameter, new Date());
}
}
} return invocation.proceed();
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
} @Override
public void setProperties(Properties properties) { }

测试就不贴了 !保准成功!

燃尽图

暑假撸系统3- petty热更新 mybatis自动填充时间字段!的更多相关文章

  1. mybatis自动填充时间字段

    对于实体中的created_on和updated_on来说,它没有必要被开发人员去干预,因为它已经足够说明使用场景了,即在插入数据和更新数据时,记录当前时间,这对于mybatis来说,通过拦截器是可以 ...

  2. mysql每次update数据,自动更新对应表中时间字段

    mysql 已经创建完成表的情况下, 使得其中的时间字段 在每次 uodate 数据的时候 自动更新事件, 运行如下sql ALTER TABLE tab_name MODIFY COLUMN upd ...

  3. 暑假撸系统1-先把git后悔药准备好!

    学校规定让暑假自己撸一款在线考试系统,其实的确需要一个款在线的考试系统系统,因为平时学校是使用Excel讲解选择题的.基于这个目标那么就话不多说.开干! 本来趁着项目想练练手,使用些新学习的技能看看, ...

  4. 暑假撸系统7- 熊孩子的捣乱!javascript保存前台状态!

    系统大体框架已经搭的差不多了, 往下就是技术性的美化以及修补了,但这也是最最耗费时间的.在这个过程就发现了一个有意思的需求,这里把思路以及解决方案总结下. 因为做的是考试系统,不管是大或者小的考试,本 ...

  5. 暑假撸系统5- Thymeleaf 常用标签的

    上次博客已经是三天前了,后期修补和细化的东西多了,进度没有前几天那么明显了.因为原来工作大多是后端居多,如果非要前台也会选择一些相对对ui依赖比较小的框架,比如extjs,所以这次的基础排版就费劲了, ...

  6. 暑假撸系统6- Thymeleaf ajax交互!

    本来用Thymeleaf也没想着深度使用ajax,就是用也是非常传统的ajax方式提交然后js控制修改下变量.闲来无事的时候看Thymeleaf的教程发现一哥们的实现方式,以及实现思路,堪称惊奇,先说 ...

  7. 关于webpack下热更新?&自动刷新?的小记(非vue-cli)

    写本随笔时:webpack4.6.0 为何标题用?号,因为老衲也不知是否用词正确,大概是这样的说法: webpack4.0引入生产模式和开发模式,在开发时使用 webpack 打包后不压缩,所以只需要 ...

  8. EF部分字段更新,自动忽略null字段

    某个项目里的update代码是类似这样的 public T Update<T>(T entity) where T : ModelBase { var set = this.Set< ...

  9. mybatis的判定时间字段问题 java.lang.IllegalArgumentException: invalid comparison: cn.hutool.core.date.DateTime and java.lang.String

    今天听组员说: mybatis在3.30版本及以上判定时间时 <if test="date_time != null and date_time != '' "> da ...

随机推荐

  1. BrowserSync 本地服务器的起用

    最简单粗暴的方法:进入项目根目录,执行命令browser-sync start --server --files "**"     监听所有

  2. 什么是css Modules

    具体请参考阮一峰老师的博客(http://www.ruanyifeng.com/blog/2016/06/css_modules.html)

  3. Python实战案例系列(一)

    本节目录 烟草扫码数据统计 奖学金统计 实战一.烟草扫码数据统计 1. 需求分析 根据扫码信息在数据库文件中匹配相应规格详细信息,并进行个数统计 条码库.xls 扫码.xlsx 一个条码对应多个规格名 ...

  4. 痞子衡嵌入式:我入选了2021年度与非网(eefocus)星选创作者Top10

    本周二「与非网」一个美女运营小姐姐加痞子衡微信,告知痞子衡评上了一个奖,让痞子衡把收件地址告诉她,她把证书寄过来. 昨天痞子衡收到了快递,拆开一看,原来是被评上了 与非网 2021 年度创作者,这个证 ...

  5. Sentry 开发者贡献指南 - Django Rest Framework(Serializers)

    Serializer 用于获取复杂的 python 模型并将它们转换为 json.序列化程序还可用于在验证传入数据后将 json 反序列化回 Python 模型. 在 Sentry,我们有两种不同类型 ...

  6. java 报错: MalformedURLException: unknow protocol: f

    问题: java 使用 URL 读取文件解读报错 MalformedURLException 1.使用 URL对象解析文件报错MalformedURLException: unknow protoco ...

  7. linux系统Kibana安装 汉化

    Elasticsearch官方系列软件Kibana,在控制台管理维护Elasticsearch. 这里注意Elasticsearch和Kibana的版本一定要一致. 官网下载地址 https://ww ...

  8. Fio使用和结果分析

    感谢,参考自:https://blog.51cto.com/qixue/1906768: 官方说明文档,很有用:https://fio.readthedocs.io/en/latest/index.h ...

  9. 【记录一个问题】opencv官网的opencv android sdk使用opencl并未用到GPU

    UMat u_mat;mat.copyTo(u_mat);cv::cvtColor(u_mat, cv::BGR2GARY);这样的代码反复执行,并未发现GPU占用提升.执行时间与不使用UMat相当. ...

  10. echart的x轴或y轴区间标签如何从大到小排列

    1.有时候我们做echart时,从后台接收返回回来的数据,没有按顺序排列,这里我遇到的是区间的值,看图 我这里是处理好了的,一开始,50-100这个区间在数组的最后一列,也就是在150-200后面的这 ...