针对Model类的代码修剪器

直接用Mybatis Generator生成的Model类大概是这样的

package com.spldeolin.demoapp.po;

import java.util.Date;
import javax.persistence.*;

@Table(name = "a_table")
public class ATable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "inserted_at")
    private Date insertedAt;

    @Column(name = "updated_at")
    private Date updatedAt;

    @Column(name = "deleted_at")
    private Date deletedAt;

    @Column(name = "a_name")
    private String aName;

    /**
     * @return id
     */
    public Long getId() {
        return id;
    }

    /**
     * @param id
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return inserted_at
     */
    public Date getInsertedAt() {
        return insertedAt;
    }

    /**
     * @param insertedAt
     */
    public void setInsertedAt(Date insertedAt) {
        this.insertedAt = insertedAt;
    }

    /**
     * @return updated_at
     */
    public Date getUpdatedAt() {
        return updatedAt;
    }

    /**
     * @param updatedAt
     */
    public void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }

    /**
     * @return deleted_at
     */
    public Date getDeletedAt() {
        return deletedAt;
    }

    /**
     * @param deletedAt
     */
    public void setDeletedAt(Date deletedAt) {
        this.deletedAt = deletedAt;
    }

    /**
     * @return a_name
     */
    public String getaName() {
        return aName;
    }

    /**
     * @param aName
     */
    public void setaName(String aName) {
        this.aName = aName;
    }
}

在项目配置了lombok的情况下,里面的getter和setter都是不必要的。同时,作为一个Model类,每一个的对象都是很有可能存入到Redis之类缓存里面的,所以为让每一个Model类都实现Serializable接口也是不错的注意。可以写一个“代码修剪器”应对这样的需求。

/**
 * 代码修剪器,对通过代码生成器生成代码,进行简化<br>
* 这个工具类适合在Mybatis Generator使用完之后直接运行,不适合处理被开发人员修改的model类。
*
* @author Deolin
*/ public class CodeTrimmer { /** * 【1】model类所在包的绝对路径 */ private static final String MODEL_PACKAGE_ABSOLUTE_PATH = ""; public static void main(String[] args) { /** * 【2】需要被处理的model类名,不填则处理所有 */ trimModels(); } private static void trimModels(String... targetFilenames) { List<String> filenames = Arrays.asList(targetFilenames); // 遍历文件 File folder = new File(MODEL_PACKAGE_ABSOLUTE_PATH); List<File> files = new ArrayList<>(); interceptFiles(files, folder); for (File file : files) { if (filenames.size() != 0 && !filenames.contains(fileName(file))) { continue; } try { trimOneModel(file); } catch (Exception ignored) {} } } private static void interceptFiles(List<File> files, File folder) { for (File file : folder.listFiles()) { if (file.isDirectory()) { interceptFiles(files, file); } else if ("java".equals(fileExtension(file))) { files.add(file); } else { // nothing } } } private static void trimOneModel(File file) throws Exception { // 读java文件 FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); List<String> inputLines = new ArrayList<>(); String tempLine; while ((tempLine = br.readLine()) != null) { inputLines.add(tempLine); } br.close(); fr.close(); // 读完毕,开始处理 Collections.reverse(inputLines); List<String> outputLines = new ArrayList<>(); boolean meetPublicClassEver = false; boolean meetImportEver = false; outputLines.add("}"); for (String inputLine : inputLines) { // public class if (StringUtils.trimToEmpty(inputLine).startsWith("public class")) { outputLines.add(""); outputLines.add(" private static final long serialVersionUID = 1L;"); outputLines.add(addImplements(inputLine)); addTableAnnouncement(inputLine, outputLines); addClassAnnotation(outputLines); addImport(outputLines); meetPublicClassEver = true; continue; } // @Table if (StringUtils.trimToEmpty(inputLine).startsWith("@Table")) { // 遇到@Table则不要 continue; } // Getter, Setter 方法签名与方法体 if (isMethodSignOrBody(inputLine)) { continue; } // 如果ignoreJavaDoc未被改变过(遇到类声明之前),且第一次遇到private,则都不再处理JavaDoc if (!meetPublicClassEver) { String lineContent = StringUtils.trimToEmpty(inputLine); if (!lineContent.startsWith("private") && !lineContent.startsWith("*/") && !lineContent.startsWith("*") && !lineContent.startsWith("/**") && !lineContent.equals("")) { throw new RuntimeException("java文件中存在非getter、setter方法,跳过处理。"); } if (lineContent.startsWith("private")) { meetPublicClassEver = true; } } // Getter, Setter 方法注释 if (!meetPublicClassEver && isJavaDoc(inputLine)) { continue; } outputLines.add(inputLine); } Collections.reverse(outputLines); // 处理完毕,开始写。 FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw); for (String outputLine : outputLines) { bw.write(outputLine + System.getProperty("line.separator")); } bw.close(); fw.close(); } private static boolean isMethodSignOrBody(String line) { line = StringUtils.trimToEmpty(line); if (StringUtils.startsWithIgnoreCase(line, "public")) { if (!StringUtils.startsWithIgnoreCase(line, "public class")) { return true; } } if (StringUtils.startsWithIgnoreCase(line, "return")) { return true; } if (StringUtils.startsWithIgnoreCase(line, "this.")) { return true; } if (StringUtils.startsWithIgnoreCase(line, "}")) { return true; } return false; } private static boolean isJavaDoc(String line) { line = StringUtils.trimToEmpty(line); if (StringUtils.startsWithIgnoreCase(line, "/**") || StringUtils.startsWithIgnoreCase(line, "*") || StringUtils.startsWithIgnoreCase(line, "*/")) { return true; } return false; } private static void addClassAnnotation(List<String> lines) { lines.add("@NoArgsConstructor"); lines.add("@EqualsAndHashCode"); lines.add("@ToString"); lines.add("@Setter"); lines.add("@Getter"); } private static void addImport(List<String> lines) { lines.add("import lombok.ToString;"); lines.add("import lombok.Setter;"); lines.add("import lombok.NoArgsConstructor;"); lines.add("import lombok.Getter;"); lines.add("import lombok.EqualsAndHashCode;"); lines.add("import java.io.Serializable;"); } private static String addImplements(String line) { line = StringUtils.stripEnd(line, "{"); line += "implements Serializable {"; return line; } private static void addTableAnnouncement(String line, List<String> lines) { String className = StringUtils.trimToEmpty(line).replace("public class ", "").replace(" {", ""); String tableAnnouncement = "@Table(name = "" + camelToUnderline(className) + "")"; lines.add(tableAnnouncement); } private static String fileName(File file) { String fileFullName = file.getName(); return fileFullName.substring(0, fileFullName.lastIndexOf(".")); } private static String fileExtension(File file) { String fileFullName = file.getName(); return fileFullName.substring(fileFullName.lastIndexOf(".") + 1); } private static String camelToUnderline(String camelCaseName) { StringBuilder result = new StringBuilder(); if (camelCaseName != null && camelCaseName.length() > 0) { result.append(camelCaseName.substring(0, 1).toLowerCase()); for (int i = 1; i < camelCaseName.length(); i++) { char ch = camelCaseName.charAt(i); if (Character.isUpperCase(ch)) { result.append("_"); result.append(Character.toLowerCase(ch)); } else { result.append(ch); } } } return result.toString(); } }

处理完的类中会有很多不必要的空行,只有在IDEA选中model包,Reformat Code即可。

最终效果是这样的。

package com.spldeolin.demoapp.po;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@Table(name = "a_table")
public class ATable implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "inserted_at")
    private Date insertedAt;

    @Column(name = "updated_at")
    private Date updatedAt;

    @Column(name = "deleted_at")
    private Date deletedAt;

    @Column(name = "a_name")
    private String aName;

}
原文地址:https://www.cnblogs.com/deolin/p/8206845.html