经过了昨天纠结技术选型,和一大堆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. JDBC简单查询数据库

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6543890367761089031/ 1.我们先新建一个数据库作为测试库 数据库名称为test.测试表为perso ...

  2. 【原创】美团二面:聊聊你对 Kafka Consumer 的架构设计

    在上一篇中我们详细聊了关于 Kafka Producer 内部的底层原理设计思想和细节, 本篇我们主要来聊聊 Kafka Consumer 即消费者的内部底层原理设计思想. 1.Consumer之总体 ...

  3. 【记录一个问题】android opencl c++: 不要Context, CommandQueue类的赋值函数

    一开始代码中这样写了: cl::Context ctx = cl::Context(CL_DEVICE_TYPE_GPU, NULL); cl::CommandQueue queue= cl::Com ...

  4. 利用SelectPdf插件将网页生成PDF

    简介 适用于.NET Framework和.NET Core的HTML至PDF转换器 SelectPdf提供的在线html到pdf转换器使用.NET的Select.Pdf库中的html到pdf转换器. ...

  5. gin中multipart/urlencoded表单

    package main import ( "github.com/gin-gonic/gin" ) func main() { router := gin.Default() r ...

  6. Druid未授权访问实战利用

    Druid未授权访问实战利用 ​ 最近身边的同学都开始挖src了,而且身边接触到的挖src的网友也是越来越多.作者也是在前几天开始了挖src之路.惊喜又遗憾的是第一次挖src就挖到了一家互联网公司的R ...

  7. IDEA构建Maven项目过慢的解决方法

    创建Maven项目时在此页面添加 archetypeCatalog internal 即可

  8. python整数运算--4

    #!/usr/bin/python #coding=utf-8 i=1 j=3 print(i*j) print(i**j)

  9. JDBC 连接DRUID 连接池!

    一.1.创建一个floder目录,[名称lib] 2. 导入mysql.jar包和 druid.jar 包.---------->bulid path 二.创建  sourcefolder 目录 ...

  10. 微信小程序之video组件与cover-view组件和cover-image组件灵活应用

    前言:最近忙着赶项目,没时间更博:希望和大家一起学习一起进步. 本人遇到的坑,以及爬出坑的方法:在某个微信小程序项目中,有这样一个需求:在滑块swiper组件和swiper-item组件中嵌套vide ...