最近看到一句话:自从用了mybatis-plus,泡妞时间一大把了。是不是很羡慕,听名字就知道plus就是mybatis增强版,就跟iphone和iphone-plus一样,iphone-plus肯定更好用。 现在我们就一起先了解一下代码生成器,官网上有模板,网上也有很多博客,但是拿下来后会发现,虽然生成表对应的各个类了,但是并没有具体的CRUD方法,现在我们就看看官方gitee上面的源码,试着搭建一个代码生成类。 一、先搭建一个项目,引入基本依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- jdbc --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.1.1</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.2.2</version> </dependency> </dependencies>二、代码生成器代码(有注释具体代表什么意思)
public class Generator { public static void main(String[] args) { AutoGenerator generator = new AutoGenerator(); // 全局变量配置 GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir"); //当前项目 gc.setOutputDir(projectPath+"/src/main/java"); // 输出路径 gc.setFileOverride(false); // 默认 false ,是否覆盖已生成文件 gc.setOpen(false); //默认true ,是否打开输出目录 gc.setEnableCache(false); // 默认false,是否开启二级缓存 gc.setAuthor("zhb"); // 作者 gc.setSwagger2(true); //默认false gc.setBaseResultMap(true); // 默认false gc.setDateType(DateType.TIME_PACK); // 时间策略 默认TIME_PACK gc.setBaseColumnList(true); //默认false 和basemodel相似 gc.setEntityName("%s"); gc.setControllerName("%sController"); gc.setServiceName("%sService"); gc.setServiceImplName("%sServiceImpl"); gc.setMapperName("%sMapper"); gc.setXmlName("%sMapper"); gc.setIdType(IdType.ID_WORKER_STR); // 指定生成的主键类型 generator.setGlobalConfig(gc); // 数据源配置 DataSourceConfig dc = new DataSourceConfig(); dc.setDbQuery(new MySqlQuery()); // 数据库信息查询 //默认mysql dc.setDbType(DbType.MYSQL);// 数据库类型 dc.setTypeConvert(new MySqlTypeConvert()); //类型转换 默认mysql dc.setUrl("jdbc:mysql://localhost/mybatis_plus?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&useSSL=false"); dc.setDriverName("com.mysql.cj.jdbc.Driver"); dc.setUsername("root"); dc.setPassword("123456"); generator.setDataSource(dc); // 包配置 PackageConfig pc = new PackageConfig(); pc.setParent("com.zhoubin.mybatisplus"); // pc.setModuleName(""); //此处是所属模块名称 // pc.setEntity("entity"); //默认entity,controller,service,service.impl,mapper,mapper.xml generator.setPackageInfo(pc); // 自定义配置 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; /** * 将xml生成到resource下面 */ String templatePath = "/templates/mapper.xml.ftl"; // framemark // 自定义输出配置 List<FileOutConfig> focList = new ArrayList<>(); // 自定义配置会被优先输出 focList.add(new FileOutConfig(templatePath) { @Override public String outputFile(TableInfo tableInfo) { // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!! return projectPath + "/src/main/resources/mapper/" // + pc.getModuleName() + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }); cfg.setFileOutConfigList(focList); generator.setCfg(cfg); // 配置模板 TemplateConfig tc = new TemplateConfig(); tc.setController("templates/controller.java");// /templates/entity.java 模板路径配置,默认再templates tc.setXml(""); generator.setTemplate(tc); // 数据库表配置 StrategyConfig sc = new StrategyConfig(); sc.setCapitalMode(false); //是否大写命名 默认false sc.setSkipView(true); //是否跳过试图 默认false sc.setNaming(NamingStrategy.underline_to_camel);// 表映射 驼峰命名 sc.setColumnNaming(NamingStrategy.underline_to_camel); // 字段映射 驼峰 sc.setEntityLombokModel(true); //默认false sc.setRestControllerStyle(true); // 默认false sc.setEntitySerialVersionUID(true); //默认true sc.setEntityColumnConstant(true); //默认false sc.setInclude("student"); //表名,用,隔开 需要生产 // sc.setExclude(""); // 不需要生成 二选一 sc.setEntityTableFieldAnnotationEnable(true); // 默认false 注释 sc.setControllerMappingHyphenStyle(false); //默认false sc.setLogicDeleteFieldName("status"); // 逻辑删除字段名称 generator.setStrategy(sc); // 模板引擎 generator.setTemplateEngine(new FreemarkerTemplateEngine()); generator.execute(); } }三、支持swagger2生成api文档
@Configuration @EnableSwagger2 public class Swagger2 { @Bean public Docket createRestApi(){ return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.zhoubin.mybatisplus.controller")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo(){ return new ApiInfoBuilder().title("mybaisplus") .description("mybatisplus学习测试") .contact("binzh303@163.com") .version("1.0") .build(); } }四、重写freemarker模板,生成CRUD接口,并生成api文档
package ${package.Controller}; import org.springframework.web.bind.annotation.*; <#if restControllerStyle> import org.springframework.web.bind.annotation.RestController; <#else> import org.springframework.stereotype.Controller; </#if> import org.springframework.beans.factory.annotation.Autowired; import io.swagger.annotations.Api; import io.swagger.annotations.*; import lombok.extern.slf4j.Slf4j; import java.util.*; import com.zhoubin.mybatisplus.common.ResultMessage; import ${package.Service}.${table.serviceName}; import ${package.Entity}.${table.entityName}; <#if superControllerClassPackage??> import ${superControllerClassPackage}; </#if> /** * <p> * ${table.comment!} 前端控制器 * </p> * * @author ${author} * @since ${date} */ <#if restControllerStyle> @RestController <#else> @Controller </#if> @Slf4j @Api(value = "${table.name}CRUD接口") @RequestMapping("<#if package.ModuleName??>/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>") <#if kotlin> class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if> <#else> <#if superControllerClass??> public class ${table.controllerName} extends ${superControllerClass} { <#else> public class ${table.controllerName} { </#if> @Autowired private ${table.serviceName} ${table.name}Service; @ApiOperation(value = "获取${table.name}列表",notes="") @ApiImplicitParam(name = "map", value = "${table.name}实体中的参数", required = true, dataType = "Map") @GetMapping("/") public String ${table.name}List(@RequestParam Map<String,Object> map) throws Exception { Collection<${table.entityName}> ${table.name}List = ${table.name}Service.listByMap(map); ResultMessage resultMessage = new ResultMessage(${table.name}List); return String.valueOf(resultMessage); } @ApiOperation(value = "修改${table.name}",notes="根据id修改${table.name}") @ApiImplicitParam(name = "${table.name}", value = "${table.name}实体", required = true, dataType = "Student") @PutMapping("/") public String ${table.name}Update(@RequestBody ${table.entityName} ${table.name}) throws Exception { Boolean flag = ${table.name}Service.updateById(${table.name}); ResultMessage resultMessage = new ResultMessage(flag); return String.valueOf(resultMessage); } @ApiOperation(value = "删除${table.name}",notes="根据id删除${table.name}") @ApiImplicitParam(name = "id", value = "${table.name}id", required = true, dataType = "<#list table.fields as field><#if field.keyFlag == true>${field.columnType?lower_case?cap_first}</#if></#list> ") @DeleteMapping("/{id}") public String ${table.name}Delete(@PathVariable <#list table.fields as field><#if field.keyFlag == true>${field.columnType?lower_case?cap_first}</#if></#list> id) throws Exception { // ${table} Boolean flag = ${table.name}Service.removeById(id); ResultMessage resultMessage = new ResultMessage(flag); return String.valueOf(resultMessage); } @ApiOperation(value = "添加${table.name}",notes="新增一条${table.name}") @ApiImplicitParam(name = "${table.name}", value = "${table.name}实体", required = true, dataType = "${table.name}") @PostMapping("") public String ${table.name}Add(@RequestBody ${table.entityName} ${table.name}) throws Exception { Boolean flag = ${table.name}Service.save(${table.name}); ResultMessage resultMessage = new ResultMessage(flag); return String.valueOf(resultMessage); } } </#if>然后运行生成器代码,接下来我们看看生成的CRUD接口
package com.zhoubin.mybatisplus.controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.RestController; import org.springframework.beans.factory.annotation.Autowired; import io.swagger.annotations.Api; import io.swagger.annotations.*; import lombok.extern.slf4j.Slf4j; import java.util.*; import com.zhoubin.mybatisplus.common.ResultMessage; import com.zhoubin.mybatisplus.service.StudentService; import com.zhoubin.mybatisplus.entity.Student; /** * <p> * 前端控制器 * </p> * * @author zhb * @since 2019-05-27 */ @RestController @Slf4j @Api(value = "studentCRUD接口") @RequestMapping("/student") public class StudentController { @Autowired private StudentService studentService; @ApiOperation(value = "获取student列表",notes="") @ApiImplicitParam(name = "map", value = "student实体中的参数", required = true, dataType = "Map") @GetMapping("/") public String studentList(@RequestParam Map<String,Object> map) throws Exception { Collection<Student> studentList = studentService.listByMap(map); ResultMessage resultMessage = new ResultMessage(studentList); return String.valueOf(resultMessage); } @ApiOperation(value = "修改student",notes="根据id修改student") @ApiImplicitParam(name = "student", value = "student实体", required = true, dataType = "Student") @PutMapping("/") public String studentUpdate(@RequestBody Student student) throws Exception { Boolean flag = studentService.updateById(student); ResultMessage resultMessage = new ResultMessage(flag); return String.valueOf(resultMessage); } @ApiOperation(value = "删除student",notes="根据id删除student") @ApiImplicitParam(name = "id", value = "studentid", required = true, dataType = "String") @DeleteMapping("/{id}") public String studentDelete(@PathVariable String id) throws Exception { Boolean flag = studentService.removeById(id); ResultMessage resultMessage = new ResultMessage(flag); return String.valueOf(resultMessage); } @ApiOperation(value = "添加student",notes="新增一条student") @ApiImplicitParam(name = "student", value = "student实体", required = true, dataType = "student") @PostMapping("") public String studentAdd(@RequestBody Student student) throws Exception { Boolean flag = studentService.save(student); ResultMessage resultMessage = new ResultMessage(flag); return String.valueOf(resultMessage); } }最后,再来看一下生成的api文档,在浏览器输入http://localhost:8080/swagger-ui.html,看看效果 总结: 1、如果需要别的接口,可以在freemarker模板中自定义生成类型,就可以生成你想要的接口。 2、关于@Repository、@Mapper、@MapperScan的几个注解的解释:@Repository是spring的注解,目的是将dao类注解成一个bean,交给spring管理。@Mapper是mybatis的注解,目的也是注成bean。@Mapper可以将xml和dao放在不同路径。@MapperScan注解在启动类上,注解了@MapperScan就不用重复在dao层注解@Mapper了。