基于SpringBoot的CodeGenerator

背景

目前组织上对于一个基础的crud的框架需求较多 因此选择了SpringBoot作为基础选型。

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

目前的结构基于 SpringBoot [base]+ mybatis[orm] + dubbo[soa] + shiro[rbac] + kisso[sso] + orika[mapping] +swagger[doc] +easypoi [word]

代码

在介绍生成器之前先简单介绍如下几个抽象接口或者超类

实体对象

package com.f6car.base.common;
public class Po implements java.io.Serializable {
    private static final long serialVersionUID = 5350639685728778721L;
}

页面展示对象

package com.f6car.base.common;
 
public class Vo implements java.io.Serializable {
 
    private static final long serialVersionUID = -3138610557784823876L;
}

页面搜索对象

/**
 * @author qixiaobo
 */
//非线程安全
 
public class So implements java.io.Serializable, Pagable, Sortable {
 
    private static final long serialVersionUID = -828171499994153332L;
 
    private int currentPage;
    private int pageSize = PAGESIZE.s.pageSize;
    private boolean enableCount;
    private List<Sort> sorts;
 
 
    @Override
    public int getCurrentPage() {
        return currentPage;
    }
 
    @Override
    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }
 
    @Override
    public int getPageSize() {
        return pageSize;
    }
 
    @Override
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }
 
    @Override
    public boolean isEnableCount() {
        return enableCount;
    }
 
    @Override
    public void setEnableCount(boolean enableCount) {
        this.enableCount = enableCount;
    }
 
    @Override
    public List<Sort> getSorts() {
        return sorts;
    }
 
    public void setSorts(List<Sort> sorts) {
        this.sorts = sorts;
    }
 
    @Override
    public void addSort(Sort sort) {
        if (sorts != null) {
            sorts = new ArrayList<>();
        }
        sorts.add(sort);
    }
 
    public static enum PAGESIZE {
        xs(5), s(10), m(20), l(30), xl(50), xxl(100), xxxl(1000);
        private int pageSize;
 
        PAGESIZE(int pageSize) {
            this.pageSize = pageSize;
        }
 
        public int getPageSize() {
            return pageSize;
        }
    }
}
/**
 * Created by qixiaobo on 2016/11/24.
 */
public interface Pagable {
 
    public int getCurrentPage();
 
    public void setCurrentPage(int currentPage);
 
    public int getPageSize();
 
    public void setPageSize(int pagesize);
 
    public boolean isEnableCount();
 
    public void setEnableCount(boolean enable);
 
 
}
/**
 * Created by qixiaobo on 2016/11/24.
 */
public interface Sortable {
 
    List<Sort> getSorts();
 
    void addSort(Sort sort);
 
}
/**
 * Created by qixiaobo on 2016/11/24.
 */
public class Sort implements Serializable {
 
    private static final long serialVersionUID = 7739709965769082011L;
    private static final String DEFAULT_PREFIX = "p";
    private static final String SQL_DOT = ".";
    private String orderField;
    private OrderType orderType = OrderType.ASC;
    private boolean enablePrefix = true;
 
    private Sort() {
    }
 
    private Sort(String orderField, OrderType orderType, boolean enablePrefix) {
        assert orderField != null;
        this.orderField = orderField;
        this.orderType = orderType;
        this.enablePrefix = enablePrefix;
    }
 
 
    private Sort(String orderField) {
        this(orderField, OrderType.ASC, true);
    }
 
    public static Sort valueOf(String sortString) {
 
        return new Sort(sortString);
    }
 
    public static Sort valueOf(String sortKey, OrderType orderType) {
        return new Sort(sortKey, orderType, true);
    }
 
    public static Sort valueOf(String sortKey, OrderType orderType, boolean enablePrefix) {
        return new Sort(sortKey, orderType, enablePrefix);
    }
 
    public String getOrderField() {
        if (orderField.contains(SQL_DOT) || !enablePrefix) {
            return orderField;
        } else {
            return DEFAULT_PREFIX + SQL_DOT + orderField;
        }
    }
 
    public void setOrderField(String orderField) {
        this.orderField = orderField;
    }
 
    public OrderType getOrderType() {
        return orderType;
    }
 
    public void setOrderType(OrderType orderType) {
        this.orderType = orderType;
    }
 
    public boolean isEnablePrefix() {
        return enablePrefix;
    }
 
    public void setEnablePrefix(boolean enablePrefix) {
        this.enablePrefix = enablePrefix;
    }
 
    @Override
    public String toString() {
        return getOrderField() + " " + orderType;
    }
}

统一回复格式

public class Result {
    private int code;
    private String message;
    private Object data;
 
    public Result setCode(ResultCode resultCode) {
        this.code = resultCode.code;
        return this;
    }
 
    public int getCode() {
        return code;
    }
 
    public Result setCode(int code) {
        this.code = code;
        return this;
    }
 
    public String getMessage() {
        return message;
    }
 
    public Result setMessage(String message) {
        this.message = message;
        return this;
    }
 
    public Object getData() {
        return data;
    }
 
    public Result setData(Object data) {
        this.data = data;
        return this;
    }
 
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Result{");
        sb.append("code=").append(code);
        sb.append(", message='").append(message).append('\'');
        sb.append(", data=").append(data);
        sb.append('}');
        return sb.toString();
    }
}

public enum ResultCode {
    SUCCESS(200),//成功
    FAIL(400),//失败
    UNAUTHORIZED(401),//未认证(签名错误)
    NOT_FOUND(404),//接口不存在
    INTERNAL_SERVER_ERROR(500);//服务器内部错误
 
    public int code;
 
    ResultCode(int code) {
        this.code = code;
    }
}
public class ResultGenerator {
    private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
 
    public static Result genSuccessResult() {
        return new Result()
                .setCode(ResultCode.SUCCESS)
                .setMessage(DEFAULT_SUCCESS_MESSAGE);
    }
 
    public static Result genSuccessResult(Object data) {
        return new Result()
                .setCode(ResultCode.SUCCESS)
                .setMessage(DEFAULT_SUCCESS_MESSAGE)
                .setData(data);
    }
 
    public static Result genFailResult(String message) {
        return new Result()
                .setCode(ResultCode.FAIL)
                .setMessage(message);
    }
}

抽象Mapper

package com.f6car.base.core;
 
import com.f6car.base.common.Po;
import tk.mybatis.mapper.common.BaseMapper;
import tk.mybatis.mapper.common.ConditionMapper;
import tk.mybatis.mapper.common.IdsMapper;
import tk.mybatis.mapper.common.special.InsertListMapper;
 
public interface Mapper<T extends Po>
        extends
        BaseMapper<T>,
        ConditionMapper<T>,
        IdsMapper<T>,
        InsertListMapper<T> {
}

抽象Service

public abstract class AbstractService<T extends Po, V extends Vo, S extends So> implements Service<V, S> {
 
    @Autowired
    protected Mapper<T> mapper;
    @Resource
    protected OrikaMapper orikaMapper;
    protected Class<V> voClazz;
    protected Class<T> poClazz;
 
    public AbstractService() {
        TypeToken<T> poType = new TypeToken<T>(getClass()) {
        };
        TypeToken<V> voType = new TypeToken<V>(getClass()) {
        };
        poClazz = (Class<T>) poType.getRawType();
        voClazz = (Class<V>) voType.getRawType();
    }
 
    @Override
    public int save(V model) {
        Preconditions.checkArgument(model != null);
        T po = orikaMapper.convert(model, poClazz);
        return mapper.insertSelective(po);
    }
 
    @Override
    public int save(List<V> models) {
        Preconditions.checkArgument(models != null && !models.isEmpty());
        List<T> ts = orikaMapper.convertList(models, poClazz);
        return mapper.insertList(ts);
    }
 
    @Override
    public int deleteById(Serializable id) {
        Preconditions.checkArgument(id != null);
        return mapper.deleteByPrimaryKey(id);
    }
 
    @Override
    public int deleteByIds(String ids) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(ids));
        return mapper.deleteByIds(ids);
    }
 
    @Override
    public int update(V model) {
        Preconditions.checkArgument(model != null);
        T po = orikaMapper.convert(model, poClazz);
        return mapper.updateByPrimaryKeySelective(po);
    }
 
    @Override
    public V findById(Serializable id) {
        Preconditions.checkArgument(id != null);
        return orikaMapper.convert(mapper.selectByPrimaryKey(id), voClazz);
    }
 
 
    @Override
    public List<V> findByIds(String ids) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(ids));
        return orikaMapper.convertList(mapper.selectByIds(ids), voClazz);
    }
 
    @Override
    public List<V> findAll() {
        return orikaMapper.convertList(mapper.selectAll(), voClazz);
    }
 
}

很明显此处实现了基于泛型的注入

Service接口

/**
 * Service 层 基础接口,其他Service 接口 请继承该接口
 */
public interface Service<V extends Vo, S extends So> {
    int save(V model);//持久化
 
    int save(List<V> models);//批量持久化
 
    int deleteById(Serializable id);//通过主鍵刪除
 
    int deleteByIds(String ids);//批量刪除 eg:ids -> “1,2,3,4”
 
    int update(V model);//更新
 
    V findById(Serializable id);//通过ID查找
 
 
    List<V> findByIds(String ids);//通过多个ID查找//eg:ids -> “1,2,3,4”
 
    List<V> findAll();//获取所有
 
}

service层次并没有提供po的 泛型 各位可以思考这是为啥?

抽象Controller

/**
 * @author qixiaobo
 */
public abstract class AbstractRestController<V extends Vo, S extends So> {
 
    @Autowired
    private Service<V, S> service;
 
 
    @PostMapping()
    @ApiOperation(value = "新建实体", notes = "")
    public Result add(@RequestBody V vo) {
        service.save(vo);
        return ResultGenerator.genSuccessResult();
    }
 
    @DeleteMapping("/{id}")
    @ApiOperation(value = "删除实体", notes = "")
    public Result delete(@PathVariable Serializable id) {
        service.deleteById(id);
        return ResultGenerator.genSuccessResult();
    }
 
 
    @PutMapping
    @ApiOperation(value = "更新实体", notes = "")
    public Result update(@RequestBody V vo) {
        service.update(vo);
        return ResultGenerator.genSuccessResult();
    }
 
    @GetMapping
    @ApiOperation(value = "获取实体列表", notes = "")
    public Result list(S so) {
        PageHelper.startPage(so.getCurrentPage(), so.getPageSize());
        List<V> list = service.findAll();
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }
 
    @GetMapping("/{id}")
    @ApiOperation(value = "获取单个实体", notes = "")
    public Result detail(@PathVariable Serializable id) {
        V vo = service.findById(id);
        return ResultGenerator.genSuccessResult(vo);
    }
 
    @DeleteMapping("/batch")
    @ApiOperation(value = "批量删除实体", notes = "")
    public Result batchDelete(@RequestParam String ids) {
        service.deleteByIds(ids);
        return ResultGenerator.genSuccessResult();
    }
 
    @GetMapping("/batch")
    @ApiOperation(value = "批量获取实体", notes = "")
    public Result batchDetail(@RequestParam String ids) {
        List<V> vos = service.findByIds(ids);
        return ResultGenerator.genSuccessResult(vos);
    }
 
    @PostMapping("/batch")
    @ApiOperation(value = "批量新建实体", notes = "")
    public Result add(@RequestBody List<V> vos) {
        service.save(vos);
        return ResultGenerator.genSuccessResult();
    }
 
}

生成器

public class CodeGenerator {
    private static final String JDBC_URL = "jdbc:mysql://192.168.1.7:3306/f6dms_20160522";
    private static final String JDBC_USERNAME = "root";
    private static final String JDBC_PASSWORD = "root";
    private static final String JDBC_DIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
 
    public static final ThreadLocal<List<Field>> PO_FIELDS = new ThreadLocal<>();
    private static final String PROJECT_PATH = System.getProperty("user.dir");
    private static final String TEMPLATE_FILE_PATH = PROJECT_PATH + "/src/test/resources/template";
    private static final String JAVA_PATH = "/src/main/java";
    private static final String RESOURCES_PATH = "/src/main/resources";
    private static final String PACKAGE_PATH_SERVICE = packageConvertPath(SERVICE_PACKAGE);
    private static final String PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(SERVICE_IMPL_PACKAGE);
    private static final String PACKAGE_PATH_SO = packageConvertPath(SO_PACKAGE);
    private static final String PACKAGE_PATH_VO = packageConvertPath(VO_PACKAGE);
    private static final String PACKAGE_PATH_CONTROLLER = packageConvertPath(CONTROLLER_PACKAGE);
    private static final String AUTHOR = "qixiaobo";
    private static final Splitter TABLE_NAME_SPLITTER = Splitter.on(UNDER_LINE).trimResults().omitEmptyStrings();
    private static final String DATE = new DateTime().toString("yyyy-MM-dd");
    private static final List<String> VO_EXCLUED_FIELD_NAMES = Lists.newArrayList("creator", "modifier", "modifiedtime", "creationtime");
    private static final Joiner PATH_JOINER = Joiner.on("/");
    private static GroupTemplate gt;
 
    static {
        ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader("template");
        org.beetl.core.Configuration cfg = null;
        try {
            cfg = org.beetl.core.Configuration.defaultConfiguration();
        } catch (IOException e) {
            e.printStackTrace();
        }
        gt = new GroupTemplate(resourceLoader, cfg);
    }
 
    public static void main(String[] args) throws IOException {
        genCode("tb_user", "tb_org", "tb_menu", "tb_org_mac");
    }
 
    /**
     * 通过数据表名称生成代码,Model 名称通过解析数据表名称获得,下划线转大驼峰的形式。
     * 如输入表名称 "t_user_detail" 将生成 TUserDetail、TUserDetailMapper、TUserDetailService ...
     *
     * @param tableNames 数据表名称...
     */
    public static void genCode(String... tableNames) throws IOException {
        for (String tableName : tableNames) {
            genCodeByCustomModelName(tableName, null);
        }
    }
 
    /**
     * 通过数据表名称,和自定义的 Model 名称生成代码
     * 如输入表名称 "t_user_detail" 和自定义的 Model 名称 "User" 将生成 User、UserMapper、UserService ...
     *
     * @param tableName 数据表名称
     * @param modelName 自定义的 Model 名称
     */
    public static void genCodeByCustomModelName(String tableName, String modelName) throws IOException {
        String subPackage = "";
        List<String> strings = TABLE_NAME_SPLITTER.splitToList(tableName);
        if (strings.size() >= 2) {
            if (strings.get(0).length() <= 2) {
                subPackage = strings.get(1);
            }
        }
 
        genModelAndMapper(tableName, modelName, subPackage);
        genService(tableName, modelName, subPackage);
        genController(tableName, modelName, subPackage);
    }
 
 
    public static void genModelAndMapper(String tableName, String modelName, String subPackageName) {
        Context context = new Context(ModelType.FLAT);
        context.setId("f6car");
        context.setTargetRuntime("MyBatis3Simple");
        context.addProperty(PropertyRegistry.CONTEXT_BEGINNING_DELIMITER, "`");
        context.addProperty(PropertyRegistry.CONTEXT_ENDING_DELIMITER, "`");
 
        JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
        jdbcConnectionConfiguration.setConnectionURL(JDBC_URL);
        jdbcConnectionConfiguration.setUserId(JDBC_USERNAME);
        jdbcConnectionConfiguration.setPassword(JDBC_PASSWORD);
        jdbcConnectionConfiguration.setDriverClass(JDBC_DIVER_CLASS_NAME);
        context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);
        JavaTypeResolverConfiguration javaTypeResolverConfiguration = new JavaTypeResolverConfiguration();
        javaTypeResolverConfiguration.setConfigurationType(F6JavaTypeResolverDefaultImpl.class.getName());
        context.setJavaTypeResolverConfiguration(javaTypeResolverConfiguration);
        PluginConfiguration pluginConfiguration = new PluginConfiguration();
        pluginConfiguration.setConfigurationType(F6MapperPlugin.class.getName());
        pluginConfiguration.addProperty("mappers", MAPPER_INTERFACE_REFERENCE);
        context.addPluginConfiguration(pluginConfiguration);
 
        JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
        javaModelGeneratorConfiguration.setTargetProject(PROJECT_PATH + Module.model.moduleDir + JAVA_PATH);
        String javaPackage = MODEL_PACKAGE;
        String mapperPackage = MAPPER_PACKAGE;
        String xmlPackage = "mapper";
        if (!Strings.isNullOrEmpty(subPackageName)) {
            javaPackage += ("." + subPackageName);
            mapperPackage += ("." + subPackageName);
            xmlPackage += ("/" + subPackageName);
        }
        javaModelGeneratorConfiguration.setTargetPackage(javaPackage);
        context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);
 
        SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
        sqlMapGeneratorConfiguration.setTargetProject(PROJECT_PATH + Module.dao.moduleDir + RESOURCES_PATH);
        sqlMapGeneratorConfiguration.setTargetPackage(xmlPackage);
        context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);
 
        JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
        javaClientGeneratorConfiguration.setTargetProject(PROJECT_PATH + Module.dao.moduleDir + JAVA_PATH);
        javaClientGeneratorConfiguration.setTargetPackage(mapperPackage);
        javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
        context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);
 
        TableConfiguration tableConfiguration = new TableConfiguration(context);
        tableConfiguration.setTableName(tableName);
        if (!Strings.isNullOrEmpty(modelName)) {
            tableConfiguration.setDomainObjectName(modelName);
        }
        tableConfiguration.setGeneratedKey(new GeneratedKey("id", "Mysql", true, null));
        context.addTableConfiguration(tableConfiguration);
 
        List<String> warnings;
        MyBatisGenerator generator;
        try {
            Configuration config = new Configuration();
            config.addContext(context);
            config.validate();
 
            boolean overwrite = true;
            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            warnings = new ArrayList<>();
            generator = new MyBatisGenerator(config, callback, warnings);
            generator.generate(null);
        } catch (Exception e) {
            throw new RuntimeException("生成Model和Mapper失败", e);
        }
 
        if (generator.getGeneratedJavaFiles().isEmpty() || generator.getGeneratedXmlFiles().isEmpty()) {
            throw new RuntimeException("生成Model和Mapper失败:" + warnings);
        }
        if (StringUtils.isEmpty(modelName)) {
            modelName = tableNameConvertUpperCamel(tableName);
        }
        System.out.println(modelName + ".java 生成成功");
        System.out.println(modelName + "Mapper.java 生成成功");
        System.out.println(modelName + "Mapper.xml 生成成功");
    }
 
    public static void genService(String tableName, String modelName, String subPackage) throws IOException {
 
        Map<String, Object> data = new HashMap<>();
        data.put("date", DATE);
        data.put("author", AUTHOR);
        String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName;
        data.put("modelNameUpperCamel", modelNameUpperCamel);
        data.put("modelNameLowerCamel", tableNameConvertLowerCamel(tableName));
        data.put("basePackage", BASE_PACKAGE);
        String servicePackageDir = PROJECT_PATH + Module.service.moduleDir + JAVA_PATH + PACKAGE_PATH_SERVICE;
        String serviceImplPackageDir = PROJECT_PATH + Module.serviceimpl.moduleDir + JAVA_PATH + PACKAGE_PATH_SERVICE_IMPL;
        String soPackageDir = PROJECT_PATH + Module.dto.moduleDir + JAVA_PATH + PACKAGE_PATH_SO;
        String voPackageDir = PROJECT_PATH + Module.dto.moduleDir + JAVA_PATH + PACKAGE_PATH_VO;
        if (!Strings.isNullOrEmpty(subPackage)) {
            data.put("subPackage", "." + subPackage);
            servicePackageDir += ("/" + subPackage + "/");
            serviceImplPackageDir += ("/" + subPackage + "/");
            soPackageDir += ("/" + subPackage + "/");
            voPackageDir += ("/" + subPackage + "/");
        }
 
 
        generateByTemplate(gt, "/service.beetl", servicePackageDir + modelNameUpperCamel + "Service.java", data);
        generateByTemplate(gt, "/service-impl.beetl", serviceImplPackageDir + modelNameUpperCamel + "ServiceImpl.java", data);
        data.put("fields", getVoFields());
        generateByTemplate(gt, "/so.beetl", soPackageDir + modelNameUpperCamel + "So.java", data);
        generateByTemplate(gt, "/vo.beetl", voPackageDir + modelNameUpperCamel + "Vo.java", data);
 
 
    }
 
    private static Collection<Field> getVoFields() {
        if (PO_FIELDS.get().isEmpty()) {
            return Collections.emptyList();
        } else {
            return Collections2.filter(PO_FIELDS.get(), new Predicate<Field>() {
                @Override
                public boolean apply(Field input) {
                    if (VO_EXCLUED_FIELD_NAMES.contains(input.getName())) {
                        return false;
                    }
                    return true;
                }
            });
        }
    }
 
    private static void generateByTemplate(GroupTemplate groupTemplate, String templateFile, String filename, Map data) throws IOException {
        File serviceFile = new File(filename);
        if (!serviceFile.getParentFile().exists()) {
            serviceFile.getParentFile().mkdirs();
        }
        Template template = groupTemplate.getTemplate(templateFile);
        template.binding(data);
        template.renderTo(new FileWriter(serviceFile));
 
        System.out.println(filename + "生成成功");
    }
 
    public static void genController(String tableName, String modelName, String subPackage) throws IOException {
 
        Map<String, Object> data = new HashMap<>();
        data.put("date", DATE);
        data.put("author", AUTHOR);
        String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName;
        List<String> strings = TABLE_NAME_SPLITTER.splitToList(tableName.toLowerCase());
        if (strings.size() >= 2) {
            if (strings.get(0).length() <= 2) {
                strings = Lists.newArrayList(strings);
                strings.remove(0);
            }
            data.put("baseRequestMapping", PATH_JOINER.join(strings));
        }
        if (!data.containsKey("baseRequestMapping")) {
            data.put("baseRequestMapping", modelNameConvertMappingPath(modelNameUpperCamel));
        }
        data.put("modelNameUpperCamel", modelNameUpperCamel);
        data.put("modelNameLowerCamel", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, modelNameUpperCamel));
        data.put("basePackage", BASE_PACKAGE);
        String controllerPackageDir = PROJECT_PATH + Module.web.moduleDir + JAVA_PATH + PACKAGE_PATH_CONTROLLER;
        if (!Strings.isNullOrEmpty(subPackage)) {
            data.put("subPackage", "." + subPackage);
            controllerPackageDir += ("/" + subPackage + "/");
        }
 
        generateByTemplate(gt, "/controller.beetl", controllerPackageDir + modelNameUpperCamel + "Controller.java", data);
        PO_FIELDS.remove();
    }
 
    private static String tableNameConvertLowerCamel(String tableName) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName.toLowerCase());
    }
 
    private static String tableNameConvertUpperCamel(String tableName) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toLowerCase());
 
    }
 
    private static String tableNameConvertMappingPath(String tableName) {
        tableName = tableName.toLowerCase();
        return "/" + (tableName.contains("_") ? tableName.replaceAll("_", "/") : tableName);
    }
 
    private static String modelNameConvertMappingPath(String modelName) {
        String tableName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, modelName);
        return tableNameConvertMappingPath(tableName);
    }
 
    private static String packageConvertPath(String packageName) {
        return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName);
    }
 
    private static enum Module {
        dao("/dao"), web("/web"), service("/service"), serviceimpl("/serviceimpl"), dto("/dto"), model("/model");
        private String moduleDir;
 
        Module(String moduleDir) {
            this.moduleDir = moduleDir;
        }
    }
}

基于我们系统中使用uuid_short 必须使用bigint unsigned (20) 目前Java中并无基础数据类型可以对应 所以使用了String类型

public class F6JavaTypeResolverDefaultImpl extends JavaTypeResolverDefaultImpl {
    public F6JavaTypeResolverDefaultImpl() {
        super();
        //bigint unsigned!
        typeMap.put(Types.BIGINT, new JdbcTypeInformation("BIGINT",
                new FullyQualifiedJavaType(String.class.getName())));
    }
}

生成器模板

vo

package com.f6car.base.vo${subPackage!};
 
import com.f6car.base.common.Vo;
import java.util.Date;
import java.math.BigDecimal;
 
 
/**
 * Created by ${author} on ${date}.
 */
public class ${modelNameUpperCamel}Vo extends Vo {
 
    private static final long serialVersionUID = -6920934492324729614L;
 
     <%
        for(field in fields){
        %>
    private ${ field.type.shortName}   ${field.name};
 
        <%}%>
 
    <%
    for(field in fields){
    %>
     <%
                var firstChar = strutil.subStringTo(field.name,0,1);
                var firstChar_upper =  strutil.toUpperCase(firstChar);
                var fieldNameWithUpper = strutil.replace (field.name,firstChar,firstChar_upper);
            %>
    public void set${fieldNameWithUpper}(${ field.type.shortName} ${field.name}) {
            this.${field.name} = ${field.name};
       }
 
    public ${ field.type.shortName} get${fieldNameWithUpper}() {
          return ${field.name};
      }
 
 
    <%}%>
 
 
 
 
}

so

package com.f6car.base.so${subPackage!};
 
import com.f6car.base.common.So;
 
/**
 * Created by ${author} on ${date}.
 */
public class ${modelNameUpperCamel}So extends So {
 
    private static final long serialVersionUID = -6920934492324729614L;
}

service

package ${basePackage}.service${subPackage!};
import ${basePackage}.vo${subPackage!}.${modelNameUpperCamel}Vo;
import ${basePackage}.so${subPackage!}.${modelNameUpperCamel}So;
 
import ${basePackage}.common.Service;
 
 
/**
 * Created by ${author} on ${date}.
 */
public interface ${modelNameUpperCamel}Service extends Service<${modelNameUpperCamel}Vo,${modelNameUpperCamel}So> {
 
}

service-impl

package ${basePackage}.service.impl${subPackage!};
 
import ${basePackage}.dao${subPackage!}.${modelNameUpperCamel}Mapper;
import ${basePackage}.po${subPackage!}.${modelNameUpperCamel};
import ${basePackage}.vo${subPackage!}.${modelNameUpperCamel}Vo;
import ${basePackage}.so${subPackage!}.${modelNameUpperCamel}So;
import ${basePackage}.service${subPackage!}.${modelNameUpperCamel}Service;
import ${basePackage}.core.AbstractService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
 
 
/**
 * Created by ${author} on ${date}.
 */
 @Service
 @Transactional(rollbackFor = Exception.class)
public class ${modelNameUpperCamel}ServiceImpl extends AbstractService<${modelNameUpperCamel},${modelNameUpperCamel}Vo,${modelNameUpperCamel}So> implements ${modelNameUpperCamel}Service {
    @Resource
    private ${modelNameUpperCamel}Mapper ${modelNameLowerCamel}Mapper;
}

controller

package ${basePackage}.controller${subPackage!};
import ${basePackage}.common.Result;
import ${basePackage}.common.ResultGenerator;
import ${basePackage}.vo${subPackage!}.${modelNameUpperCamel}Vo;
import ${basePackage}.so${subPackage!}.${modelNameUpperCamel}So;
import ${basePackage}.service${subPackage!}.${modelNameUpperCamel}Service;
import ${basePackage}.controller.base.AbstractRestController;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.web.bind.annotation.*;
 
import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
 
/**
* Created by ${author} on ${date}.
*/
@RestController
@RequestMapping("${baseRequestMapping}")
public class ${modelNameUpperCamel}Controller extends AbstractRestController<${modelNameUpperCamel}Vo, ${modelNameUpperCamel}So> {
    @Resource
    private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service;
 
 
}

当运行生成器比如传入

genCode("tb_user", "tb_org", "tb_menu", "tb_org_mac");

生成如下

package com.f6car.base.po.user;
 
import com.f6car.base.common.Po;
import java.util.Date;
import javax.persistence.*;
 
@Table(name = "tb_user")
public class TbUser extends Po {
    /**
     * 主键
     */
    @Id
    @Column(name = "pk_id")
    private String pkId;
 
    /**
     * 用户名
     */
    private String username;
 
    @Column(name = "cell_phone")
    private String cellPhone;
 
    /**
     * 密码
     */
    private String password;
 
    /**
     * 是否管理员
     */
    @Column(name = "is_admin")
    private Byte isAdmin;
 
    /**
     * 角色ID
     */
    @Column(name = "id_role")
    private String idRole;
 
    /**
     * 创建人
     */
    private String creator;
 
    /**
     * 修改人
     */
    private String modifier;
 
    /**
     * 修改日期
     */
    private Date modifiedtime;
 
    /**
     * 创建日期
     */
    private Date creationtime;
 
    /**
     * 组织
     */
    @Column(name = "id_own_org")
    private String idOwnOrg;
 
    /**
     * 员工ID
     */
    @Column(name = "id_employee")
    private String idEmployee;
 
    @Column(name = "is_del")
    private Byte isDel;
 
    /**
     * 向导默认开关:0默认关闭,1默认打开
     */
    @Column(name = "is_guide_open")
    private Byte isGuideOpen;
 
    /**
     * 维小宝用户ID
     */
    @Column(name = "id_wxb_user")
    private String idWxbUser;
 
    /**
     * 维小宝店铺ID
     */
    @Column(name = "id_wxb_station")
    private String idWxbStation;
 
    private String openid;
 
    /**
     * 是否限定PC登录设备 0 不选中 1 选中
     */
    @Column(name = "limit_mac")
    private Byte limitMac;
 
    /**
     * 获取主键
     *
     * @return pk_id - 主键
     */
    public String getPkId() {
        return pkId;
    }
 
    /**
     * 设置主键
     *
     * @param pkId 主键
     */
    public void setPkId(String pkId) {
        this.pkId = pkId;
    }
 
    /**
     * 获取用户名
     *
     * @return username - 用户名
     */
    public String getUsername() {
        return username;
    }
 
    /**
     * 设置用户名
     *
     * @param username 用户名
     */
    public void setUsername(String username) {
        this.username = username;
    }
 
    /**
     * @return cell_phone
     */
    public String getCellPhone() {
        return cellPhone;
    }
 
    /**
     * @param cellPhone
     */
    public void setCellPhone(String cellPhone) {
        this.cellPhone = cellPhone;
    }
 
    /**
     * 获取密码
     *
     * @return password - 密码
     */
    public String getPassword() {
        return password;
    }
 
    /**
     * 设置密码
     *
     * @param password 密码
     */
    public void setPassword(String password) {
        this.password = password;
    }
 
    /**
     * 获取是否管理员
     *
     * @return is_admin - 是否管理员
     */
    public Byte getIsAdmin() {
        return isAdmin;
    }
 
    /**
     * 设置是否管理员
     *
     * @param isAdmin 是否管理员
     */
    public void setIsAdmin(Byte isAdmin) {
        this.isAdmin = isAdmin;
    }
 
    /**
     * 获取角色ID
     *
     * @return id_role - 角色ID
     */
    public String getIdRole() {
        return idRole;
    }
 
    /**
     * 设置角色ID
     *
     * @param idRole 角色ID
     */
    public void setIdRole(String idRole) {
        this.idRole = idRole;
    }
 
    /**
     * 获取创建人
     *
     * @return creator - 创建人
     */
    public String getCreator() {
        return creator;
    }
 
    /**
     * 设置创建人
     *
     * @param creator 创建人
     */
    public void setCreator(String creator) {
        this.creator = creator;
    }
 
    /**
     * 获取修改人
     *
     * @return modifier - 修改人
     */
    public String getModifier() {
        return modifier;
    }
 
    /**
     * 设置修改人
     *
     * @param modifier 修改人
     */
    public void setModifier(String modifier) {
        this.modifier = modifier;
    }
 
    /**
     * 获取修改日期
     *
     * @return modifiedtime - 修改日期
     */
    public Date getModifiedtime() {
        return modifiedtime;
    }
 
    /**
     * 设置修改日期
     *
     * @param modifiedtime 修改日期
     */
    public void setModifiedtime(Date modifiedtime) {
        this.modifiedtime = modifiedtime;
    }
 
    /**
     * 获取创建日期
     *
     * @return creationtime - 创建日期
     */
    public Date getCreationtime() {
        return creationtime;
    }
 
    /**
     * 设置创建日期
     *
     * @param creationtime 创建日期
     */
    public void setCreationtime(Date creationtime) {
        this.creationtime = creationtime;
    }
 
    /**
     * 获取组织
     *
     * @return id_own_org - 组织
     */
    public String getIdOwnOrg() {
        return idOwnOrg;
    }
 
    /**
     * 设置组织
     *
     * @param idOwnOrg 组织
     */
    public void setIdOwnOrg(String idOwnOrg) {
        this.idOwnOrg = idOwnOrg;
    }
 
    /**
     * 获取员工ID
     *
     * @return id_employee - 员工ID
     */
    public String getIdEmployee() {
        return idEmployee;
    }
 
    /**
     * 设置员工ID
     *
     * @param idEmployee 员工ID
     */
    public void setIdEmployee(String idEmployee) {
        this.idEmployee = idEmployee;
    }
 
    /**
     * @return is_del
     */
    public Byte getIsDel() {
        return isDel;
    }
 
    /**
     * @param isDel
     */
    public void setIsDel(Byte isDel) {
        this.isDel = isDel;
    }
 
    /**
     * 获取向导默认开关:0默认关闭,1默认打开
     *
     * @return is_guide_open - 向导默认开关:0默认关闭,1默认打开
     */
    public Byte getIsGuideOpen() {
        return isGuideOpen;
    }
 
    /**
     * 设置向导默认开关:0默认关闭,1默认打开
     *
     * @param isGuideOpen 向导默认开关:0默认关闭,1默认打开
     */
    public void setIsGuideOpen(Byte isGuideOpen) {
        this.isGuideOpen = isGuideOpen;
    }
 
    /**
     * 获取维小宝用户ID
     *
     * @return id_wxb_user - 维小宝用户ID
     */
    public String getIdWxbUser() {
        return idWxbUser;
    }
 
    /**
     * 设置维小宝用户ID
     *
     * @param idWxbUser 维小宝用户ID
     */
    public void setIdWxbUser(String idWxbUser) {
        this.idWxbUser = idWxbUser;
    }
 
    /**
     * 获取维小宝店铺ID
     *
     * @return id_wxb_station - 维小宝店铺ID
     */
    public String getIdWxbStation() {
        return idWxbStation;
    }
 
    /**
     * 设置维小宝店铺ID
     *
     * @param idWxbStation 维小宝店铺ID
     */
    public void setIdWxbStation(String idWxbStation) {
        this.idWxbStation = idWxbStation;
    }
 
    /**
     * @return openid
     */
    public String getOpenid() {
        return openid;
    }
 
    /**
     * @param openid
     */
    public void setOpenid(String openid) {
        this.openid = openid;
    }
 
    /**
     * 获取是否限定PC登录设备 0 不选中 1 选中
     *
     * @return limit_mac - 是否限定PC登录设备 0 不选中 1 选中
     */
    public Byte getLimitMac() {
        return limitMac;
    }
 
    /**
     * 设置是否限定PC登录设备 0 不选中 1 选中
     *
     * @param limitMac 是否限定PC登录设备 0 不选中 1 选中
     */
    public void setLimitMac(Byte limitMac) {
        this.limitMac = limitMac;
    }
}
package com.f6car.base.vo.user;
 
import com.f6car.base.common.Vo;
import java.util.Date;
import java.math.BigDecimal;
 
 
/**
 * Created by qixiaobo on 2017-11-21.
 */
public class TbUserVo extends Vo {
 
    private static final long serialVersionUID = -6920934492324729614L;
 
    private String   pkId;
 
    private String   username;
 
    private String   cellPhone;
 
    private String   password;
 
    private Byte   isAdmin;
 
    private String   idRole;
 
    private String   idOwnOrg;
 
    private String   idEmployee;
 
    private Byte   isDel;
 
    private Byte   isGuideOpen;
 
    private String   idWxbUser;
 
    private String   idWxbStation;
 
    private String   openid;
 
    private Byte   limitMac;
 
 
    public void setPkId(String pkId) {
            this.pkId = pkId;
       }
 
    public String getPkId() {
          return pkId;
      }
 
 
    public void setUsername(String username) {
            this.username = username;
       }
 
    public String getUsername() {
          return username;
      }
 
 
    public void setCellPhone(String cellPhone) {
            this.cellPhone = cellPhone;
       }
 
    public String getCellPhone() {
          return cellPhone;
      }
 
 
    public void setPassword(String password) {
            this.password = password;
       }
 
    public String getPassword() {
          return password;
      }
 
 
    public void setIsAdmIn(Byte isAdmin) {
            this.isAdmin = isAdmin;
       }
 
    public Byte getIsAdmIn() {
          return isAdmin;
      }
 
 
    public void setIdRole(String idRole) {
            this.idRole = idRole;
       }
 
    public String getIdRole() {
          return idRole;
      }
 
 
    public void setIdOwnOrg(String idOwnOrg) {
            this.idOwnOrg = idOwnOrg;
       }
 
    public String getIdOwnOrg() {
          return idOwnOrg;
      }
 
 
    public void setIdEmployee(String idEmployee) {
            this.idEmployee = idEmployee;
       }
 
    public String getIdEmployee() {
          return idEmployee;
      }
 
 
    public void setIsDel(Byte isDel) {
            this.isDel = isDel;
       }
 
    public Byte getIsDel() {
          return isDel;
      }
 
 
    public void setIsGuIdeOpen(Byte isGuideOpen) {
            this.isGuideOpen = isGuideOpen;
       }
 
    public Byte getIsGuIdeOpen() {
          return isGuideOpen;
      }
 
 
    public void setIdWxbUser(String idWxbUser) {
            this.idWxbUser = idWxbUser;
       }
 
    public String getIdWxbUser() {
          return idWxbUser;
      }
 
 
    public void setIdWxbStatIon(String idWxbStation) {
            this.idWxbStation = idWxbStation;
       }
 
    public String getIdWxbStatIon() {
          return idWxbStation;
      }
 
 
    public void setOpenid(String openid) {
            this.openid = openid;
       }
 
    public String getOpenid() {
          return openid;
      }
 
 
    public void setLimitMac(Byte limitMac) {
            this.limitMac = limitMac;
       }
 
    public Byte getLimitMac() {
          return limitMac;
      }
 
 
 
 
 
 
}
package com.f6car.base.so.user;
 
import com.f6car.base.common.So;
 
/**
 * Created by qixiaobo on 2017-11-21.
 */
public class TbUserSo extends So {
 
    private static final long serialVersionUID = -6920934492324729614L;
}
package com.f6car.base.service.user;
import com.f6car.base.vo.user.TbUserVo;
import com.f6car.base.so.user.TbUserSo;
 
import com.f6car.base.common.Service;
 
 
/**
 * Created by qixiaobo on 2017-11-21.
 */
public interface TbUserService extends Service<TbUserVo,TbUserSo> {
 
}

package com.f6car.base.service.impl.user;
 
import com.f6car.base.dao.user.TbUserMapper;
import com.f6car.base.po.user.TbUser;
import com.f6car.base.vo.user.TbUserVo;
import com.f6car.base.so.user.TbUserSo;
import com.f6car.base.service.user.TbUserService;
import com.f6car.base.core.AbstractService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
 
 
/**
 * Created by qixiaobo on 2017-11-21.
 */
 @Service
 @Transactional(rollbackFor = Exception.class)
public class TbUserServiceImpl extends AbstractService<TbUser,TbUserVo,TbUserSo> implements TbUserService {
    @Resource
    private TbUserMapper tbUserMapper;
}
package com.f6car.base.controller.user;
import com.f6car.base.common.Result;
import com.f6car.base.common.ResultGenerator;
import com.f6car.base.vo.user.TbUserVo;
import com.f6car.base.so.user.TbUserSo;
import com.f6car.base.service.user.TbUserService;
import com.f6car.base.controller.base.AbstractRestController;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.web.bind.annotation.*;
 
import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
 
/**
* Created by qixiaobo on 2017-11-21.
*/
@RestController
@RequestMapping("user")
public class TbUserController extends AbstractRestController<TbUserVo, TbUserSo> {
    @Resource
    private TbUserService tbUserService;
 
 
}

声明

本代码基于 https://github.com/lihengming/spring-boot-api-project-seed 改造

感谢这位小伙伴~~~

本人项目 https://github.com/qixiaobo/zeus

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SpringSpace.cn

Spring Boot 2.0 项目实现自同步AD域账号 顶

在通过Spring Boot的自动化装配功能及JDK自带的LDAP模块,可通过如下几个简单步骤实现业务系统自动同步AD域账号功能。

2383
来自专栏Hongten

apache的开源项目-模板引擎(Velocity)_学习了两天就上手啦_源码下载

首先,如果你对Velocity不是很了解,还是建议你去apache的官方网站上去走走....

1131
来自专栏java、Spring、技术分享

Spring Import 三种用法与源码解读

  最近在看Spring Cloud相关的源码,每次引入一个新的starter,发现都会加一些enable的注解,比如:@EnableDiscoveryClie...

2264
来自专栏F_Alex

(四)SpringBoot2.0基础篇- 多数据源,JdbcTemplate和JpaRepository

3554
来自专栏Android相关

Android使用MultiDex发生ClassNotFoundException

在Method与Filed数超限的背景下,我们将多工程拆分成多个Dex打到Apk中解决该问题,但是在使用MultiDex的时候,还会遇到一些问题。 在启动的时...

1472
来自专栏码匠的流水账

聊聊resilience4j的CircuitBreakerConfig

本文主要研究一下resilience4j的CircuitBreakerConfig

2382
来自专栏清晨我上码

spring mvc 国际化的几种方案

通过设置浏览器请求测试:http://localhost:8080/xxx/nation/test

6043
来自专栏hbbliyong

5步搭建GO环境

Easy Go Programming Setup for Windows Dec 23, 2014 I’ve had to do this more t...

4007
来自专栏一个会写诗的程序员的博客

第16章 Spring Boot + Kotlin: 下一代 Java 服务端开发

2017-11-22 11:55:17.205 INFO 14721 --- [ main] org.hibernate.Version ...

1521
来自专栏Android源码框架分析

获取Android设备DeviceId与反Xposed Hook技术

APP开发中常需要获取设备的DeviceId,以应对刷单,目前常用的几个设备识别码主要有IMEI(国际移动设备身份码 International Mobile ...

3262

扫码关注云+社区