暑假撸系统3- petty热更新 mybatis自动填充时间字段!

经过了昨天纠结技术选型,和一大堆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) {

    }


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

燃尽图

原文地址:https://www.cnblogs.com/liuadong/p/13280177.html