├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── company
│ │ └── project
│ │ ├── Application.java
│ │ ├── configurer
│ │ ├── MybatisConfigurer.java
│ │ └── WebMvcConfigurer.java
│ │ └── core
│ │ ├── AbstractService.java
│ │ ├── Mapper.java
│ │ ├── ProjectConstant.java
│ │ ├── Result.java
│ │ ├── ResultCode.java
│ │ ├── ResultGenerator.java
│ │ ├── Service.java
│ │ └── ServiceException.java
└── resources
│ ├── application-dev.properties
│ ├── application-prod.properties
│ ├── application-test.properties
│ ├── application.properties
│ └── banner.txt
└── test
├── java
├── CodeGenerator.java
└── com
│ └── conpany
│ └── project
│ └── Tester.java
└── resources
├── demo-user.sql
└── generator
└── template
├── controller-restful.ftl
├── controller.ftl
├── service-impl.ftl
└── service.ftl
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
3 | ### STS ###
4 | .apt_generated
5 | .classpath
6 | .factorypath
7 | .project
8 | .settings
9 | .springBeans
10 |
11 | ### IntelliJ IDEA ###
12 | .idea
13 | *.iws
14 | *.iml
15 | *.ipr
16 |
17 | ### NetBeans ###
18 | nbproject/private/
19 | build/
20 | nbbuild/
21 | dist/
22 | nbdist/
23 | .nb-gradle/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | [](https://github.com/lihengming/spring-boot-api-project-seed/releases)
3 | ## 简介
4 | Spring Boot API Project Seed 是一个基于Spring Boot & MyBatis的种子项目,用于快速构建中小型API、RESTful API项目,该种子项目已经有过多个真实项目的实践,稳定、简单、快速,使我们摆脱那些重复劳动,专注于业务代码的编写,减少加班。下面是一个简单的使用演示,看如何基于本项目在短短几十秒钟内实现一套简单的API,并运行提供服务。
5 |
6 | [](http://v.youku.com/v_show/id_XMjg1NjYwNDgxNg==.html?spm=a2h3j.8428770.3416059.1)
7 | ## 特征&提供
8 | - 最佳实践的项目结构、配置文件、精简的POM([查看项目结构图](https://github.com/lihengming/java-codes/blob/master/shared-resources/github-images/project-struct.png))
9 | - 统一响应结果封装及生成工具
10 | - 统一异常处理
11 | - 简单的接口签名认证
12 | - 常用基础方法抽象封装
13 | - 使用Druid Spring Boot Starter 集成Druid数据库连接池与监控
14 | - 使用FastJsonHttpMessageConverter,提高JSON序列化速度
15 | - 集成MyBatis、通用Mapper插件、PageHelper分页插件,实现单表业务零SQL
16 | - 提供代码生成器根据表名生成对应的Model、Mapper、MapperXML、Service、ServiceImpl、Controller等基础代码,其中Controller模板默认提供POST和RESTful两套,根据需求在```CodeGenerator.genController(tableName)```方法中自己选择,默认使用POST模板。代码模板可根据实际项目的需求来扩展,由于每个公司业务都不太一样,所以只提供了一些比较基础、通用的模板,**主要是提供一个思路**来减少重复代码的编写,我在实际项目的使用中,其实根据公司业务的抽象编写了大量的模板。另外,使用模板也有助于保持团队代码风格的统一
17 | - 另有彩蛋,待你探索
18 |
19 | ## 快速开始
20 | 1. 克隆项目
21 | 2. 对```test```包内的代码生成器```CodeGenerator```进行配置,主要是JDBC,因为要根据表名来生成代码
22 | 3. 如果只是想根据上面的演示来亲自试试的话可以使用```test resources```目录下的```demo-user.sql```,否则忽略该步
23 | 3. 输入表名,运行```CodeGenerator.main()```方法,生成基础代码(可能需要刷新项目目录才会出来)
24 | 4. 根据业务在基础代码上进行扩展
25 | 5. 对开发环境配置文件```application-dev.properties```进行配置,启动项目,Have Fun!
26 |
27 | ## 开发建议
28 | - 表名,建议使用小写,多个单词使用下划线拼接
29 | - Model内成员变量建议与表字段数量对应,如需扩展成员变量(比如连表查询)建议创建DTO,否则需在扩展的成员变量上加```@Transient```注解,详情见[通用Mapper插件文档说明](https://mapperhelper.github.io/docs/2.use/)
30 | - 建议业务失败直接使用```ServiceException("message")```抛出,由统一异常处理器来封装业务失败的响应结果,比如```throw new ServiceException("该手机号已被注册")```,会直接被封装为```{"code":400,"message":"该手机号已被注册"}```返回,无需自己处理,尽情抛出
31 | - 需要工具类的话建议先从```apache-commons-*```和```guava```中找,实在没有再造轮子或引入类库,尽量精简项目
32 | - 开发规范建议遵循阿里巴巴Java开发手册([最新版下载](https://github.com/alibaba/p3c))
33 | - 建议在公司内部使用[ShowDoc](https://github.com/star7th/showdoc)、[SpringFox-Swagger2](https://github.com/springfox/springfox) 、[RAP](https://github.com/thx/RAP)等开源项目来编写、管理API文档
34 |
35 | ## 技术选型&文档
36 | - Spring Boot([查看Spring Boot学习&使用指南](http://www.jianshu.com/p/1a9fd8936bd8))
37 | - MyBatis([查看官方中文文档](http://www.mybatis.org/mybatis-3/zh/index.html))
38 | - MyBatisb通用Mapper插件([查看官方中文文档](https://mapperhelper.github.io/docs/))
39 | - MyBatis PageHelper分页插件([查看官方中文文档](https://pagehelper.github.io/))
40 | - Druid Spring Boot Starter([查看官方中文文档](https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter/))
41 | - Fastjson([查看官方中文文档](https://github.com/Alibaba/fastjson/wiki/%E9%A6%96%E9%A1%B5))
42 | - 其他略
43 |
44 | ## License
45 | 无,纯粹开源分享,感谢大家 [Star](https://github.com/lihengming/spring-boot-api-project-seed/stargazers) & [Fork](https://github.com/lihengming/spring-boot-api-project-seed/network/members) 的支持。
46 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.github.lihengming
8 | spring-boot-api-project-seed
9 | 1.0
10 | jar
11 |
12 |
13 | 1.8
14 |
15 |
16 |
17 |
18 | org.springframework.boot
19 | spring-boot-starter-parent
20 | 1.5.13.RELEASE
21 |
22 |
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-jdbc
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-test
36 | test
37 |
38 |
39 |
40 | commons-codec
41 | commons-codec
42 |
43 |
44 | org.apache.commons
45 | commons-lang3
46 | 3.6
47 |
48 |
49 | com.google.guava
50 | guava
51 | 23.0
52 |
53 |
54 |
55 | mysql
56 | mysql-connector-java
57 | runtime
58 |
59 |
60 |
61 | org.mybatis
62 | mybatis-spring
63 | 1.3.1
64 |
65 |
66 | org.mybatis
67 | mybatis
68 | 3.4.5
69 |
70 |
71 | tk.mybatis
72 | mapper
73 | 3.4.2
74 |
75 |
76 | com.github.pagehelper
77 | pagehelper
78 | 4.2.1
79 |
80 |
81 |
82 | com.alibaba
83 | fastjson
84 | 1.2.47
85 |
86 |
87 |
88 | com.alibaba
89 | druid-spring-boot-starter
90 | 1.1.10
91 |
92 |
93 |
94 | org.freemarker
95 | freemarker
96 | 2.3.23
97 | test
98 |
99 |
100 | org.mybatis.generator
101 | mybatis-generator-core
102 | 1.3.5
103 | test
104 |
105 |
106 |
107 |
108 |
109 |
110 | org.springframework.boot
111 | spring-boot-maven-plugin
112 |
113 |
114 | maven-compiler-plugin
115 |
116 | ${java.version}
117 | ${java.version}
118 | UTF-8
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | aliyun-repos
127 | http://maven.aliyun.com/nexus/content/groups/public/
128 |
129 | false
130 |
131 |
132 |
133 |
134 |
135 |
136 | aliyun-plugin
137 | http://maven.aliyun.com/nexus/content/groups/public/
138 |
139 | false
140 |
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/Application.java:
--------------------------------------------------------------------------------
1 | package com.company.project;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 | public static void main(String[] args) {
9 | SpringApplication.run(Application.class, args);
10 | }
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/configurer/MybatisConfigurer.java:
--------------------------------------------------------------------------------
1 | package com.company.project.configurer;
2 |
3 | import com.github.pagehelper.PageHelper;
4 | import org.apache.ibatis.plugin.Interceptor;
5 | import org.apache.ibatis.session.SqlSessionFactory;
6 | import org.mybatis.spring.SqlSessionFactoryBean;
7 | import org.springframework.beans.factory.annotation.Qualifier;
8 | import org.springframework.boot.autoconfigure.AutoConfigureAfter;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Conditional;
11 | import org.springframework.context.annotation.Configuration;
12 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
13 | import org.springframework.core.io.support.ResourcePatternResolver;
14 | import tk.mybatis.spring.mapper.MapperScannerConfigurer;
15 |
16 | import javax.annotation.Resource;
17 | import javax.sql.DataSource;
18 | import java.util.Properties;
19 |
20 | import static com.company.project.core.ProjectConstant.*;
21 |
22 | /**
23 | * Mybatis & Mapper & PageHelper 配置
24 | */
25 | @Configuration
26 | public class MybatisConfigurer {
27 |
28 | @Bean
29 | public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception {
30 | SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
31 | factory.setDataSource(dataSource);
32 | factory.setTypeAliasesPackage(MODEL_PACKAGE);
33 |
34 | //配置分页插件,详情请查阅官方文档
35 | PageHelper pageHelper = new PageHelper();
36 | Properties properties = new Properties();
37 | properties.setProperty("pageSizeZero", "true");//分页尺寸为0时查询所有纪录不再执行分页
38 | properties.setProperty("reasonable", "true");//页码<=0 查询第一页,页码>=总页数查询最后一页
39 | properties.setProperty("supportMethodsArguments", "true");//支持通过 Mapper 接口参数来传递分页参数
40 | pageHelper.setProperties(properties);
41 |
42 | //添加插件
43 | factory.setPlugins(new Interceptor[]{pageHelper});
44 |
45 | //添加XML目录
46 | ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
47 | factory.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
48 | return factory.getObject();
49 | }
50 |
51 | @Bean
52 | public MapperScannerConfigurer mapperScannerConfigurer() {
53 | MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
54 | mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
55 | mapperScannerConfigurer.setBasePackage(MAPPER_PACKAGE);
56 |
57 | //配置通用Mapper,详情请查阅官方文档
58 | Properties properties = new Properties();
59 | properties.setProperty("mappers", MAPPER_INTERFACE_REFERENCE);
60 | properties.setProperty("notEmpty", "false");//insert、update是否判断字符串类型!='' 即 test="str != null"表达式内是否追加 and str != ''
61 | properties.setProperty("IDENTITY", "MYSQL");
62 | mapperScannerConfigurer.setProperties(properties);
63 |
64 | return mapperScannerConfigurer;
65 | }
66 |
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/configurer/WebMvcConfigurer.java:
--------------------------------------------------------------------------------
1 | package com.company.project.configurer;
2 |
3 | import java.io.IOException;
4 | import java.nio.charset.Charset;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.Collections;
8 | import java.util.List;
9 |
10 | import javax.servlet.ServletException;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 |
14 | import com.alibaba.fastjson.JSON;
15 | import com.alibaba.fastjson.serializer.SerializerFeature;
16 | import com.alibaba.fastjson.support.config.FastJsonConfig;
17 | import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
18 |
19 | import com.company.project.core.Result;
20 | import com.company.project.core.ResultCode;
21 | import com.company.project.core.ServiceException;
22 | import org.apache.commons.codec.digest.DigestUtils;
23 | import org.apache.commons.lang3.StringUtils;
24 | import org.slf4j.Logger;
25 | import org.slf4j.LoggerFactory;
26 | import org.springframework.beans.factory.annotation.Value;
27 | import org.springframework.context.annotation.Configuration;
28 | import org.springframework.http.MediaType;
29 | import org.springframework.http.converter.HttpMessageConverter;
30 | import org.springframework.web.method.HandlerMethod;
31 | import org.springframework.web.servlet.HandlerExceptionResolver;
32 | import org.springframework.web.servlet.ModelAndView;
33 | import org.springframework.web.servlet.NoHandlerFoundException;
34 | import org.springframework.web.servlet.config.annotation.CorsRegistry;
35 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
36 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
37 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
38 |
39 | /**
40 | * Spring MVC 配置
41 | */
42 | @Configuration
43 | public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
44 |
45 | private final Logger logger = LoggerFactory.getLogger(WebMvcConfigurer.class);
46 | @Value("${spring.profiles.active}")
47 | private String env;//当前激活的配置文件
48 |
49 | //使用阿里 FastJson 作为JSON MessageConverter
50 | @Override
51 | public void configureMessageConverters(List> converters) {
52 | FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
53 | FastJsonConfig config = new FastJsonConfig();
54 | config.setSerializerFeatures(SerializerFeature.WriteMapNullValue);//保留空的字段
55 | //SerializerFeature.WriteNullStringAsEmpty,//String null -> ""
56 | //SerializerFeature.WriteNullNumberAsZero//Number null -> 0
57 | // 按需配置,更多参考FastJson文档哈
58 |
59 | converter.setFastJsonConfig(config);
60 | converter.setDefaultCharset(Charset.forName("UTF-8"));
61 | converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
62 | converters.add(converter);
63 | }
64 |
65 |
66 | //统一异常处理
67 | @Override
68 | public void configureHandlerExceptionResolvers(List exceptionResolvers) {
69 | exceptionResolvers.add(new HandlerExceptionResolver() {
70 | public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
71 | Result result = new Result();
72 | if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误”
73 | result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
74 | logger.info(e.getMessage());
75 | } else if (e instanceof NoHandlerFoundException) {
76 | result.setCode(ResultCode.NOT_FOUND).setMessage("接口 [" + request.getRequestURI() + "] 不存在");
77 | } else if (e instanceof ServletException) {
78 | result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
79 | } else {
80 | result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");
81 | String message;
82 | if (handler instanceof HandlerMethod) {
83 | HandlerMethod handlerMethod = (HandlerMethod) handler;
84 | message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
85 | request.getRequestURI(),
86 | handlerMethod.getBean().getClass().getName(),
87 | handlerMethod.getMethod().getName(),
88 | e.getMessage());
89 | } else {
90 | message = e.getMessage();
91 | }
92 | logger.error(message, e);
93 | }
94 | responseResult(response, result);
95 | return new ModelAndView();
96 | }
97 |
98 | });
99 | }
100 |
101 | //解决跨域问题
102 | @Override
103 | public void addCorsMappings(CorsRegistry registry) {
104 | //registry.addMapping("/**");
105 | }
106 |
107 | //添加拦截器
108 | @Override
109 | public void addInterceptors(InterceptorRegistry registry) {
110 | //接口签名认证拦截器,该签名认证比较简单,实际项目中可以使用Json Web Token或其他更好的方式替代。
111 | if (!"dev".equals(env)) { //开发环境忽略签名认证
112 | registry.addInterceptor(new HandlerInterceptorAdapter() {
113 | @Override
114 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
115 | //验证签名
116 | boolean pass = validateSign(request);
117 | if (pass) {
118 | return true;
119 | } else {
120 | logger.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}",
121 | request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));
122 |
123 | Result result = new Result();
124 | result.setCode(ResultCode.UNAUTHORIZED).setMessage("签名认证失败");
125 | responseResult(response, result);
126 | return false;
127 | }
128 | }
129 | });
130 | }
131 | }
132 |
133 | private void responseResult(HttpServletResponse response, Result result) {
134 | response.setCharacterEncoding("UTF-8");
135 | response.setHeader("Content-type", "application/json;charset=UTF-8");
136 | response.setStatus(200);
137 | try {
138 | response.getWriter().write(JSON.toJSONString(result));
139 | } catch (IOException ex) {
140 | logger.error(ex.getMessage());
141 | }
142 | }
143 |
144 | /**
145 | * 一个简单的签名认证,规则:
146 | * 1. 将请求参数按ascii码排序
147 | * 2. 拼接为a=value&b=value...这样的字符串(不包含sign)
148 | * 3. 混合密钥(secret)进行md5获得签名,与请求的签名进行比较
149 | */
150 | private boolean validateSign(HttpServletRequest request) {
151 | String requestSign = request.getParameter("sign");//获得请求签名,如sign=19e907700db7ad91318424a97c54ed57
152 | if (StringUtils.isEmpty(requestSign)) {
153 | return false;
154 | }
155 | List keys = new ArrayList(request.getParameterMap().keySet());
156 | keys.remove("sign");//排除sign参数
157 | Collections.sort(keys);//排序
158 |
159 | StringBuilder sb = new StringBuilder();
160 | for (String key : keys) {
161 | sb.append(key).append("=").append(request.getParameter(key)).append("&");//拼接字符串
162 | }
163 | String linkString = sb.toString();
164 | linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);//去除最后一个'&'
165 |
166 | String secret = "Potato";//密钥,自己修改
167 | String sign = DigestUtils.md5Hex(linkString + secret);//混合密钥md5
168 |
169 | return StringUtils.equals(sign, requestSign);//比较
170 | }
171 |
172 | private String getIpAddress(HttpServletRequest request) {
173 | String ip = request.getHeader("x-forwarded-for");
174 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
175 | ip = request.getHeader("Proxy-Client-IP");
176 | }
177 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
178 | ip = request.getHeader("WL-Proxy-Client-IP");
179 | }
180 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
181 | ip = request.getHeader("HTTP_CLIENT_IP");
182 | }
183 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
184 | ip = request.getHeader("HTTP_X_FORWARDED_FOR");
185 | }
186 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
187 | ip = request.getRemoteAddr();
188 | }
189 | // 如果是多级代理,那么取第一个ip为客户端ip
190 | if (ip != null && ip.indexOf(",") != -1) {
191 | ip = ip.substring(0, ip.indexOf(",")).trim();
192 | }
193 |
194 | return ip;
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/AbstractService.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core;
2 |
3 |
4 | import org.apache.ibatis.exceptions.TooManyResultsException;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import tk.mybatis.mapper.entity.Condition;
7 |
8 | import java.lang.reflect.Field;
9 | import java.lang.reflect.ParameterizedType;
10 | import java.util.List;
11 |
12 | /**
13 | * 基于通用MyBatis Mapper插件的Service接口的实现
14 | */
15 | public abstract class AbstractService implements Service {
16 |
17 | @Autowired
18 | protected Mapper mapper;
19 |
20 | private Class modelClass; // 当前泛型真实类型的Class
21 |
22 | public AbstractService() {
23 | ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
24 | modelClass = (Class) pt.getActualTypeArguments()[0];
25 | }
26 |
27 | public void save(T model) {
28 | mapper.insertSelective(model);
29 | }
30 |
31 | public void save(List models) {
32 | mapper.insertList(models);
33 | }
34 |
35 | public void deleteById(Integer id) {
36 | mapper.deleteByPrimaryKey(id);
37 | }
38 |
39 | public void deleteByIds(String ids) {
40 | mapper.deleteByIds(ids);
41 | }
42 |
43 | public void update(T model) {
44 | mapper.updateByPrimaryKeySelective(model);
45 | }
46 |
47 | public T findById(Integer id) {
48 | return mapper.selectByPrimaryKey(id);
49 | }
50 |
51 | @Override
52 | public T findBy(String fieldName, Object value) throws TooManyResultsException {
53 | try {
54 | T model = modelClass.newInstance();
55 | Field field = modelClass.getDeclaredField(fieldName);
56 | field.setAccessible(true);
57 | field.set(model, value);
58 | return mapper.selectOne(model);
59 | } catch (ReflectiveOperationException e) {
60 | throw new ServiceException(e.getMessage(), e);
61 | }
62 | }
63 |
64 | public List findByIds(String ids) {
65 | return mapper.selectByIds(ids);
66 | }
67 |
68 | public List findByCondition(Condition condition) {
69 | return mapper.selectByCondition(condition);
70 | }
71 |
72 | public List findAll() {
73 | return mapper.selectAll();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/Mapper.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core;
2 |
3 | import tk.mybatis.mapper.common.BaseMapper;
4 | import tk.mybatis.mapper.common.ConditionMapper;
5 | import tk.mybatis.mapper.common.IdsMapper;
6 | import tk.mybatis.mapper.common.special.InsertListMapper;
7 |
8 | /**
9 | * 定制版MyBatis Mapper插件接口,如需其他接口参考官方文档自行添加。
10 | */
11 | public interface Mapper
12 | extends
13 | BaseMapper,
14 | ConditionMapper,
15 | IdsMapper,
16 | InsertListMapper {
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/ProjectConstant.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core;
2 |
3 | /**
4 | * 项目常量
5 | */
6 | public final class ProjectConstant {
7 | public static final String BASE_PACKAGE = "com.company.project";//生成代码所在的基础包名称,可根据自己公司的项目修改(注意:这个配置修改之后需要手工修改src目录项目默认的包路径,使其保持一致,不然会找不到类)
8 |
9 | public static final String MODEL_PACKAGE = BASE_PACKAGE + ".model";//生成的Model所在包
10 | public static final String MAPPER_PACKAGE = BASE_PACKAGE + ".dao";//生成的Mapper所在包
11 | public static final String SERVICE_PACKAGE = BASE_PACKAGE + ".service";//生成的Service所在包
12 | public static final String SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";//生成的ServiceImpl所在包
13 | public static final String CONTROLLER_PACKAGE = BASE_PACKAGE + ".web";//生成的Controller所在包
14 |
15 | public static final String MAPPER_INTERFACE_REFERENCE = BASE_PACKAGE + ".core.Mapper";//Mapper插件基础接口的完全限定名
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/Result.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core;
2 |
3 | import com.alibaba.fastjson.JSON;
4 |
5 | /**
6 | * 统一API响应结果封装
7 | */
8 | public class Result {
9 | private int code;
10 | private String message;
11 | private T data;
12 |
13 | public Result setCode(ResultCode resultCode) {
14 | this.code = resultCode.code();
15 | return this;
16 | }
17 |
18 | public int getCode() {
19 | return code;
20 | }
21 |
22 | public String getMessage() {
23 | return message;
24 | }
25 |
26 | public Result setMessage(String message) {
27 | this.message = message;
28 | return this;
29 | }
30 |
31 | public T getData() {
32 | return data;
33 | }
34 |
35 | public Result setData(T data) {
36 | this.data = data;
37 | return this;
38 | }
39 |
40 | @Override
41 | public String toString() {
42 | return JSON.toJSONString(this);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/ResultCode.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core;
2 |
3 | /**
4 | * 响应码枚举,参考HTTP状态码的语义
5 | */
6 | public enum ResultCode {
7 | SUCCESS(200),//成功
8 | FAIL(400),//失败
9 | UNAUTHORIZED(401),//未认证(签名错误)
10 | NOT_FOUND(404),//接口不存在
11 | INTERNAL_SERVER_ERROR(500);//服务器内部错误
12 |
13 | private final int code;
14 |
15 | ResultCode(int code) {
16 | this.code = code;
17 | }
18 |
19 | public int code() {
20 | return code;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/ResultGenerator.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core;
2 |
3 | /**
4 | * 响应结果生成工具
5 | */
6 | public class ResultGenerator {
7 | private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
8 |
9 | public static Result genSuccessResult() {
10 | return new Result()
11 | .setCode(ResultCode.SUCCESS)
12 | .setMessage(DEFAULT_SUCCESS_MESSAGE);
13 | }
14 |
15 | public static Result genSuccessResult(T data) {
16 | return new Result()
17 | .setCode(ResultCode.SUCCESS)
18 | .setMessage(DEFAULT_SUCCESS_MESSAGE)
19 | .setData(data);
20 | }
21 |
22 | public static Result genFailResult(String message) {
23 | return new Result()
24 | .setCode(ResultCode.FAIL)
25 | .setMessage(message);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/Service.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core;
2 |
3 | import org.apache.ibatis.exceptions.TooManyResultsException;
4 | import tk.mybatis.mapper.entity.Condition;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * Service 层 基础接口,其他Service 接口 请继承该接口
10 | */
11 | public interface Service {
12 | void save(T model);//持久化
13 | void save(List models);//批量持久化
14 | void deleteById(Integer id);//通过主鍵刪除
15 | void deleteByIds(String ids);//批量刪除 eg:ids -> “1,2,3,4”
16 | void update(T model);//更新
17 | T findById(Integer id);//通过ID查找
18 | T findBy(String fieldName, Object value) throws TooManyResultsException; //通过Model中某个成员变量名称(非数据表中column的名称)查找,value需符合unique约束
19 | List findByIds(String ids);//通过多个ID查找//eg:ids -> “1,2,3,4”
20 | List findByCondition(Condition condition);//根据条件查找
21 | List findAll();//获取所有
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/ServiceException.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core;
2 |
3 | /**
4 | * 服务(业务)异常如“ 账号或密码错误 ”,该异常只做INFO级别的日志记录 @see WebMvcConfigurer
5 | */
6 | public class ServiceException extends RuntimeException {
7 | public ServiceException() {
8 | }
9 |
10 | public ServiceException(String message) {
11 | super(message);
12 | }
13 |
14 | public ServiceException(String message, Throwable cause) {
15 | super(message, cause);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/resources/application-dev.properties:
--------------------------------------------------------------------------------
1 | # 开发环境配置
2 | # 数据源配置,请修改为你项目的实际配置
3 | spring.datasource.url=jdbc:mysql://localhost:3306/test
4 | spring.datasource.username=root
5 | spring.datasource.password=123456
6 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
7 |
--------------------------------------------------------------------------------
/src/main/resources/application-prod.properties:
--------------------------------------------------------------------------------
1 | # 生产环境配置
2 |
--------------------------------------------------------------------------------
/src/main/resources/application-test.properties:
--------------------------------------------------------------------------------
1 | # 测试环境配置
2 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.profiles.active=dev
2 | # 所有环境通用的配置,放在这里
3 |
4 | # 404 交给异常处理器处理
5 | spring.mvc.throw-exception-if-no-handler-found=true
6 | spring.resources.add-mappings=false
7 |
--------------------------------------------------------------------------------
/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////
2 | // _ooOoo_ //
3 | // o8888888o //
4 | // 88" . "88 //
5 | // (| ^_^ |) //
6 | // O\ = /O //
7 | // ____/`---'\____ //
8 | // .' \\| |// `. //
9 | // / \\||| : |||// \ //
10 | // / _||||| -:- |||||- \ //
11 | // | | \\\ - /// | | //
12 | // | \_| ''\---/'' | | //
13 | // \ .-\__ `-` ___/-. / //
14 | // ___`. .' /--.--\ `. . ___ //
15 | // ."" '< `.___\_<|>_/___.' >'"". //
16 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | //
17 | // \ \ `-. \_ __\ /__ _/ .-` / / //
18 | // ========`-.____`-.___\_____/___.-`____.-'======== //
19 | // `=---=' //
20 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
21 | // 佛祖保佑 永不宕机 永无BUG //
22 | ////////////////////////////////////////////////////////////////////
--------------------------------------------------------------------------------
/src/test/java/CodeGenerator.java:
--------------------------------------------------------------------------------
1 | import com.google.common.base.CaseFormat;
2 | import freemarker.template.TemplateExceptionHandler;
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.mybatis.generator.api.MyBatisGenerator;
5 | import org.mybatis.generator.config.*;
6 | import org.mybatis.generator.internal.DefaultShellCallback;
7 |
8 | import java.io.File;
9 | import java.io.FileWriter;
10 | import java.io.IOException;
11 | import java.text.SimpleDateFormat;
12 | import java.util.*;
13 |
14 | import static com.company.project.core.ProjectConstant.*;
15 |
16 | /**
17 | * 代码生成器,根据数据表名称生成对应的Model、Mapper、Service、Controller简化开发。
18 | */
19 | public class CodeGenerator {
20 | //JDBC配置,请修改为你项目的实际配置
21 | private static final String JDBC_URL = "jdbc:mysql://localhost:3306/test";
22 | private static final String JDBC_USERNAME = "root";
23 | private static final String JDBC_PASSWORD = "123456";
24 | private static final String JDBC_DIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
25 |
26 | private static final String PROJECT_PATH = System.getProperty("user.dir");//项目在硬盘上的基础路径
27 | private static final String TEMPLATE_FILE_PATH = PROJECT_PATH + "/src/test/resources/generator/template";//模板位置
28 |
29 | private static final String JAVA_PATH = "/src/main/java"; //java文件路径
30 | private static final String RESOURCES_PATH = "/src/main/resources";//资源文件路径
31 |
32 | private static final String PACKAGE_PATH_SERVICE = packageConvertPath(SERVICE_PACKAGE);//生成的Service存放路径
33 | private static final String PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(SERVICE_IMPL_PACKAGE);//生成的Service实现存放路径
34 | private static final String PACKAGE_PATH_CONTROLLER = packageConvertPath(CONTROLLER_PACKAGE);//生成的Controller存放路径
35 |
36 | private static final String AUTHOR = "CodeGenerator";//@author
37 | private static final String DATE = new SimpleDateFormat("yyyy/MM/dd").format(new Date());//@date
38 |
39 | public static void main(String[] args) {
40 | genCode("输入表名");
41 | //genCodeByCustomModelName("输入表名","输入自定义Model名称");
42 | }
43 |
44 | /**
45 | * 通过数据表名称生成代码,Model 名称通过解析数据表名称获得,下划线转大驼峰的形式。
46 | * 如输入表名称 "t_user_detail" 将生成 TUserDetail、TUserDetailMapper、TUserDetailService ...
47 | * @param tableNames 数据表名称...
48 | */
49 | public static void genCode(String... tableNames) {
50 | for (String tableName : tableNames) {
51 | genCodeByCustomModelName(tableName, null);
52 | }
53 | }
54 |
55 | /**
56 | * 通过数据表名称,和自定义的 Model 名称生成代码
57 | * 如输入表名称 "t_user_detail" 和自定义的 Model 名称 "User" 将生成 User、UserMapper、UserService ...
58 | * @param tableName 数据表名称
59 | * @param modelName 自定义的 Model 名称
60 | */
61 | public static void genCodeByCustomModelName(String tableName, String modelName) {
62 | genModelAndMapper(tableName, modelName);
63 | genService(tableName, modelName);
64 | genController(tableName, modelName);
65 | }
66 |
67 |
68 | public static void genModelAndMapper(String tableName, String modelName) {
69 | Context context = new Context(ModelType.FLAT);
70 | context.setId("Potato");
71 | context.setTargetRuntime("MyBatis3Simple");
72 | context.addProperty(PropertyRegistry.CONTEXT_BEGINNING_DELIMITER, "`");
73 | context.addProperty(PropertyRegistry.CONTEXT_ENDING_DELIMITER, "`");
74 |
75 | JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
76 | jdbcConnectionConfiguration.setConnectionURL(JDBC_URL);
77 | jdbcConnectionConfiguration.setUserId(JDBC_USERNAME);
78 | jdbcConnectionConfiguration.setPassword(JDBC_PASSWORD);
79 | jdbcConnectionConfiguration.setDriverClass(JDBC_DIVER_CLASS_NAME);
80 | context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);
81 |
82 | PluginConfiguration pluginConfiguration = new PluginConfiguration();
83 | pluginConfiguration.setConfigurationType("tk.mybatis.mapper.generator.MapperPlugin");
84 | pluginConfiguration.addProperty("mappers", MAPPER_INTERFACE_REFERENCE);
85 | context.addPluginConfiguration(pluginConfiguration);
86 |
87 | JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
88 | javaModelGeneratorConfiguration.setTargetProject(PROJECT_PATH + JAVA_PATH);
89 | javaModelGeneratorConfiguration.setTargetPackage(MODEL_PACKAGE);
90 | context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);
91 |
92 | SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
93 | sqlMapGeneratorConfiguration.setTargetProject(PROJECT_PATH + RESOURCES_PATH);
94 | sqlMapGeneratorConfiguration.setTargetPackage("mapper");
95 | context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);
96 |
97 | JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
98 | javaClientGeneratorConfiguration.setTargetProject(PROJECT_PATH + JAVA_PATH);
99 | javaClientGeneratorConfiguration.setTargetPackage(MAPPER_PACKAGE);
100 | javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
101 | context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);
102 |
103 | TableConfiguration tableConfiguration = new TableConfiguration(context);
104 | tableConfiguration.setTableName(tableName);
105 | if (StringUtils.isNotEmpty(modelName))tableConfiguration.setDomainObjectName(modelName);
106 | tableConfiguration.setGeneratedKey(new GeneratedKey("id", "Mysql", true, null));
107 | context.addTableConfiguration(tableConfiguration);
108 |
109 | List warnings;
110 | MyBatisGenerator generator;
111 | try {
112 | Configuration config = new Configuration();
113 | config.addContext(context);
114 | config.validate();
115 |
116 | boolean overwrite = true;
117 | DefaultShellCallback callback = new DefaultShellCallback(overwrite);
118 | warnings = new ArrayList();
119 | generator = new MyBatisGenerator(config, callback, warnings);
120 | generator.generate(null);
121 | } catch (Exception e) {
122 | throw new RuntimeException("生成Model和Mapper失败", e);
123 | }
124 |
125 | if (generator.getGeneratedJavaFiles().isEmpty() || generator.getGeneratedXmlFiles().isEmpty()) {
126 | throw new RuntimeException("生成Model和Mapper失败:" + warnings);
127 | }
128 | if (StringUtils.isEmpty(modelName)) modelName = tableNameConvertUpperCamel(tableName);
129 | System.out.println(modelName + ".java 生成成功");
130 | System.out.println(modelName + "Mapper.java 生成成功");
131 | System.out.println(modelName + "Mapper.xml 生成成功");
132 | }
133 |
134 | public static void genService(String tableName, String modelName) {
135 | try {
136 | freemarker.template.Configuration cfg = getConfiguration();
137 |
138 | Map data = new HashMap<>();
139 | data.put("date", DATE);
140 | data.put("author", AUTHOR);
141 | String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName;
142 | data.put("modelNameUpperCamel", modelNameUpperCamel);
143 | data.put("modelNameLowerCamel", tableNameConvertLowerCamel(tableName));
144 | data.put("basePackage", BASE_PACKAGE);
145 |
146 | File file = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE + modelNameUpperCamel + "Service.java");
147 | if (!file.getParentFile().exists()) {
148 | file.getParentFile().mkdirs();
149 | }
150 | cfg.getTemplate("service.ftl").process(data,
151 | new FileWriter(file));
152 | System.out.println(modelNameUpperCamel + "Service.java 生成成功");
153 |
154 | File file1 = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE_IMPL + modelNameUpperCamel + "ServiceImpl.java");
155 | if (!file1.getParentFile().exists()) {
156 | file1.getParentFile().mkdirs();
157 | }
158 | cfg.getTemplate("service-impl.ftl").process(data,
159 | new FileWriter(file1));
160 | System.out.println(modelNameUpperCamel + "ServiceImpl.java 生成成功");
161 | } catch (Exception e) {
162 | throw new RuntimeException("生成Service失败", e);
163 | }
164 | }
165 |
166 | public static void genController(String tableName, String modelName) {
167 | try {
168 | freemarker.template.Configuration cfg = getConfiguration();
169 |
170 | Map data = new HashMap<>();
171 | data.put("date", DATE);
172 | data.put("author", AUTHOR);
173 | String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName;
174 | data.put("baseRequestMapping", modelNameConvertMappingPath(modelNameUpperCamel));
175 | data.put("modelNameUpperCamel", modelNameUpperCamel);
176 | data.put("modelNameLowerCamel", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, modelNameUpperCamel));
177 | data.put("basePackage", BASE_PACKAGE);
178 |
179 | File file = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_CONTROLLER + modelNameUpperCamel + "Controller.java");
180 | if (!file.getParentFile().exists()) {
181 | file.getParentFile().mkdirs();
182 | }
183 | //cfg.getTemplate("controller-restful.ftl").process(data, new FileWriter(file));
184 | cfg.getTemplate("controller.ftl").process(data, new FileWriter(file));
185 |
186 | System.out.println(modelNameUpperCamel + "Controller.java 生成成功");
187 | } catch (Exception e) {
188 | throw new RuntimeException("生成Controller失败", e);
189 | }
190 |
191 | }
192 |
193 | private static freemarker.template.Configuration getConfiguration() throws IOException {
194 | freemarker.template.Configuration cfg = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_23);
195 | cfg.setDirectoryForTemplateLoading(new File(TEMPLATE_FILE_PATH));
196 | cfg.setDefaultEncoding("UTF-8");
197 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
198 | return cfg;
199 | }
200 |
201 | private static String tableNameConvertLowerCamel(String tableName) {
202 | return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName.toLowerCase());
203 | }
204 |
205 | private static String tableNameConvertUpperCamel(String tableName) {
206 | return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toLowerCase());
207 |
208 | }
209 |
210 | private static String tableNameConvertMappingPath(String tableName) {
211 | tableName = tableName.toLowerCase();//兼容使用大写的表名
212 | return "/" + (tableName.contains("_") ? tableName.replaceAll("_", "/") : tableName);
213 | }
214 |
215 | private static String modelNameConvertMappingPath(String modelName) {
216 | String tableName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, modelName);
217 | return tableNameConvertMappingPath(tableName);
218 | }
219 |
220 | private static String packageConvertPath(String packageName) {
221 | return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName);
222 | }
223 |
224 | }
225 |
--------------------------------------------------------------------------------
/src/test/java/com/conpany/project/Tester.java:
--------------------------------------------------------------------------------
1 | package com.conpany.project;
2 |
3 |
4 | import com.company.project.Application;
5 | import org.junit.runner.RunWith;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.test.annotation.Rollback;
8 | import org.springframework.test.context.junit4.SpringRunner;
9 | import org.springframework.transaction.annotation.Transactional;
10 |
11 | /**
12 | * 单元测试继承该类即可
13 | */
14 | @RunWith(SpringRunner.class)
15 | @SpringBootTest(classes = Application.class)
16 | @Transactional
17 | @Rollback
18 | public abstract class Tester {}
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/test/resources/demo-user.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat MySQL Data Transfer
3 |
4 | Source Server : Localhost
5 | Source Server Version : 50713
6 | Source Host : localhost:3306
7 | Source Database : test
8 |
9 | Target Server Type : MYSQL
10 | Target Server Version : 50713
11 | File Encoding : 65001
12 |
13 | Date: 2017-06-23 14:25:27
14 | */
15 |
16 | SET FOREIGN_KEY_CHECKS=0;
17 |
18 | -- ----------------------------
19 | -- Table structure for user
20 | -- ----------------------------
21 | DROP TABLE IF EXISTS `user`;
22 | CREATE TABLE `user` (
23 | `id` int(11) NOT NULL AUTO_INCREMENT,
24 | `username` varchar(255) NOT NULL,
25 | `password` varchar(255) NOT NULL,
26 | `nick_name` varchar(255) DEFAULT NULL,
27 | `sex` int(1) DEFAULT NULL,
28 | `register_date` datetime NOT NULL,
29 | PRIMARY KEY (`id`)
30 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
31 |
32 | -- ----------------------------
33 | -- Records of user
34 | -- ----------------------------
35 | INSERT INTO `user` VALUES ('1', '89921218@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆', '1', '2017-06-23 14:24:23');
36 | INSERT INTO `user` VALUES ('2', '2@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-2', '1', '2017-06-23 14:24:23');
37 | INSERT INTO `user` VALUES ('3', '3@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-3', '1', '2017-06-23 14:24:23');
38 | INSERT INTO `user` VALUES ('4', '4@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-4', '1', '2017-06-23 14:24:23');
39 | INSERT INTO `user` VALUES ('5', '5@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-5', '1', '2017-06-23 14:24:23');
40 | INSERT INTO `user` VALUES ('6', '6@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-6', '1', '2017-06-23 14:24:23');
41 | INSERT INTO `user` VALUES ('7', '7@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-7', '1', '2017-06-23 14:24:23');
42 | INSERT INTO `user` VALUES ('8', '8@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-8', '1', '2017-06-23 14:24:23');
43 | INSERT INTO `user` VALUES ('9', '9@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-9', '1', '2017-06-23 14:24:23');
44 | INSERT INTO `user` VALUES ('10', '10@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-10', '1', '2017-06-23 14:24:23');
45 | SET FOREIGN_KEY_CHECKS=1;
46 |
--------------------------------------------------------------------------------
/src/test/resources/generator/template/controller-restful.ftl:
--------------------------------------------------------------------------------
1 | package ${basePackage}.web;
2 |
3 | import ${basePackage}.core.Result;
4 | import ${basePackage}.core.ResultGenerator;
5 | import ${basePackage}.model.${modelNameUpperCamel};
6 | import ${basePackage}.service.${modelNameUpperCamel}Service;
7 | import com.github.pagehelper.PageHelper;
8 | import com.github.pagehelper.PageInfo;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | import javax.annotation.Resource;
12 | import java.util.List;
13 |
14 | /**
15 | * Created by ${author} on ${date}.
16 | */
17 | @RestController
18 | @RequestMapping("${baseRequestMapping}")
19 | public class ${modelNameUpperCamel}Controller {
20 | @Resource
21 | private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service;
22 |
23 | @PostMapping
24 | public Result add(@RequestBody ${modelNameUpperCamel} ${modelNameLowerCamel}) {
25 | ${modelNameLowerCamel}Service.save(${modelNameLowerCamel});
26 | return ResultGenerator.genSuccessResult();
27 | }
28 |
29 | @DeleteMapping("/{id}")
30 | public Result delete(@PathVariable Integer id) {
31 | ${modelNameLowerCamel}Service.deleteById(id);
32 | return ResultGenerator.genSuccessResult();
33 | }
34 |
35 | @PutMapping
36 | public Result update(@RequestBody ${modelNameUpperCamel} ${modelNameLowerCamel}) {
37 | ${modelNameLowerCamel}Service.update(${modelNameLowerCamel});
38 | return ResultGenerator.genSuccessResult();
39 | }
40 |
41 | @GetMapping("/{id}")
42 | public Result detail(@PathVariable Integer id) {
43 | ${modelNameUpperCamel} ${modelNameLowerCamel} = ${modelNameLowerCamel}Service.findById(id);
44 | return ResultGenerator.genSuccessResult(${modelNameLowerCamel});
45 | }
46 |
47 | @GetMapping
48 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) {
49 | PageHelper.startPage(page, size);
50 | List<${modelNameUpperCamel}> list = ${modelNameLowerCamel}Service.findAll();
51 | PageInfo pageInfo = new PageInfo(list);
52 | return ResultGenerator.genSuccessResult(pageInfo);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/resources/generator/template/controller.ftl:
--------------------------------------------------------------------------------
1 | package ${basePackage}.web;
2 | import ${basePackage}.core.Result;
3 | import ${basePackage}.core.ResultGenerator;
4 | import ${basePackage}.model.${modelNameUpperCamel};
5 | import ${basePackage}.service.${modelNameUpperCamel}Service;
6 | import com.github.pagehelper.PageHelper;
7 | import com.github.pagehelper.PageInfo;
8 | import org.springframework.web.bind.annotation.PostMapping;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RequestParam;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import javax.annotation.Resource;
14 | import java.util.List;
15 |
16 | /**
17 | * Created by ${author} on ${date}.
18 | */
19 | @RestController
20 | @RequestMapping("${baseRequestMapping}")
21 | public class ${modelNameUpperCamel}Controller {
22 | @Resource
23 | private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service;
24 |
25 | @PostMapping("/add")
26 | public Result add(${modelNameUpperCamel} ${modelNameLowerCamel}) {
27 | ${modelNameLowerCamel}Service.save(${modelNameLowerCamel});
28 | return ResultGenerator.genSuccessResult();
29 | }
30 |
31 | @PostMapping("/delete")
32 | public Result delete(@RequestParam Integer id) {
33 | ${modelNameLowerCamel}Service.deleteById(id);
34 | return ResultGenerator.genSuccessResult();
35 | }
36 |
37 | @PostMapping("/update")
38 | public Result update(${modelNameUpperCamel} ${modelNameLowerCamel}) {
39 | ${modelNameLowerCamel}Service.update(${modelNameLowerCamel});
40 | return ResultGenerator.genSuccessResult();
41 | }
42 |
43 | @PostMapping("/detail")
44 | public Result detail(@RequestParam Integer id) {
45 | ${modelNameUpperCamel} ${modelNameLowerCamel} = ${modelNameLowerCamel}Service.findById(id);
46 | return ResultGenerator.genSuccessResult(${modelNameLowerCamel});
47 | }
48 |
49 | @PostMapping("/list")
50 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) {
51 | PageHelper.startPage(page, size);
52 | List<${modelNameUpperCamel}> list = ${modelNameLowerCamel}Service.findAll();
53 | PageInfo pageInfo = new PageInfo(list);
54 | return ResultGenerator.genSuccessResult(pageInfo);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/resources/generator/template/service-impl.ftl:
--------------------------------------------------------------------------------
1 | package ${basePackage}.service.impl;
2 |
3 | import ${basePackage}.dao.${modelNameUpperCamel}Mapper;
4 | import ${basePackage}.model.${modelNameUpperCamel};
5 | import ${basePackage}.service.${modelNameUpperCamel}Service;
6 | import ${basePackage}.core.AbstractService;
7 | import org.springframework.stereotype.Service;
8 | import org.springframework.transaction.annotation.Transactional;
9 |
10 | import javax.annotation.Resource;
11 |
12 |
13 | /**
14 | * Created by ${author} on ${date}.
15 | */
16 | @Service
17 | @Transactional
18 | public class ${modelNameUpperCamel}ServiceImpl extends AbstractService<${modelNameUpperCamel}> implements ${modelNameUpperCamel}Service {
19 | @Resource
20 | private ${modelNameUpperCamel}Mapper ${modelNameLowerCamel}Mapper;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/resources/generator/template/service.ftl:
--------------------------------------------------------------------------------
1 | package ${basePackage}.service;
2 | import ${basePackage}.model.${modelNameUpperCamel};
3 | import ${basePackage}.core.Service;
4 |
5 |
6 | /**
7 | * Created by ${author} on ${date}.
8 | */
9 | public interface ${modelNameUpperCamel}Service extends Service<${modelNameUpperCamel}> {
10 |
11 | }
12 |
--------------------------------------------------------------------------------