diff --git a/README.md b/README.md
index 5ad7d97a5..14d576c76 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,19 @@

[](https://github.com/lihengming/spring-boot-api-project-seed/releases)
+
## 简介
+基于原来的工程改动太大,所以自己fork过来进行了修改。主要修改点如下:
+
+1、SprintBoot升级到目前最新版本,2.1.3;
+
+2、HttpMessageConverter改为默认的Jackson;
+
+3、打包自动化并且添加一些启动和停止脚本,打包成一个tar.gz包;
+
+4、添加了一个DEMO,原则上应该删除掉,懒,就懒得删了。
+
+
+
Spring Boot API Project Seed 是一个基于Spring Boot & MyBatis的种子项目,用于快速构建中小型API、RESTful API项目,该种子项目已经有过多个真实项目的实践,稳定、简单、快速,使我们摆脱那些重复劳动,专注于业务代码的编写,减少加班。下面是一个简单的使用演示,看如何基于本项目在短短几十秒钟内实现一套简单的API,并运行提供服务。
[](http://v.youku.com/v_show/id_XMjg1NjYwNDgxNg==.html?spm=a2h3j.8428770.3416059.1)
@@ -15,7 +28,7 @@ Spring Boot API Project Seed 是一个基于Spring Boot & MyBatis的种子项目
- 集成MyBatis、通用Mapper插件、PageHelper分页插件,实现单表业务零SQL
- 提供代码生成器根据表名生成对应的Model、Mapper、MapperXML、Service、ServiceImpl、Controller等基础代码,其中Controller模板默认提供POST和RESTful两套,根据需求在```CodeGenerator.genController(tableName)```方法中自己选择,默认使用POST模板。代码模板可根据实际项目的需求来扩展,由于每个公司业务都不太一样,所以只提供了一些比较基础、通用的模板,**主要是提供一个思路**来减少重复代码的编写,我在实际项目的使用中,其实根据公司业务的抽象编写了大量的模板。另外,使用模板也有助于保持团队代码风格的统一
- 另有彩蛋,待你探索
-
+
## 快速开始
1. 克隆项目
2. 对```test```包内的代码生成器```CodeGenerator```进行配置,主要是JDBC,因为要根据表名来生成代码
@@ -23,7 +36,7 @@ Spring Boot API Project Seed 是一个基于Spring Boot & MyBatis的种子项目
3. 输入表名,运行```CodeGenerator.main()```方法,生成基础代码(可能需要刷新项目目录才会出来)
4. 根据业务在基础代码上进行扩展
5. 对开发环境配置文件```application-dev.properties```进行配置,启动项目,Have Fun!
-
+
## 开发建议
- 表名,建议使用小写,多个单词使用下划线拼接
- Model内成员变量建议与表字段数量对应,如需扩展成员变量(比如连表查询)建议创建DTO,否则需在扩展的成员变量上加```@Transient```注解,详情见[通用Mapper插件文档说明](https://mapperhelper.github.io/docs/2.use/)
@@ -31,7 +44,7 @@ Spring Boot API Project Seed 是一个基于Spring Boot & MyBatis的种子项目
- 需要工具类的话建议先从```apache-commons-*```和```guava```中找,实在没有再造轮子或引入类库,尽量精简项目
- 开发规范建议遵循阿里巴巴Java开发手册([最新版下载](https://github.com/alibaba/p3c))
- 建议在公司内部使用[ShowDoc](https://github.com/star7th/showdoc)、[SpringFox-Swagger2](https://github.com/springfox/springfox) 、[RAP](https://github.com/thx/RAP)等开源项目来编写、管理API文档
-
+
## 技术选型&文档
- Spring Boot([查看Spring Boot学习&使用指南](http://www.jianshu.com/p/1a9fd8936bd8))
- MyBatis([查看官方中文文档](http://www.mybatis.org/mybatis-3/zh/index.html))
diff --git a/pom.xml b/pom.xml
index 80cf9affc..2f7b321b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,13 +11,20 @@
1.8
+ UTF-8
+ 1.8
+ 1.8
+
+
+ 2.9.8
+
org.springframework.boot
spring-boot-starter-parent
- 1.5.13.RELEASE
+ 2.1.3.RELEASE
@@ -25,6 +32,12 @@
org.springframework.boot
spring-boot-starter-web
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
org.springframework.boot
@@ -70,7 +83,7 @@
tk.mybatis
mapper
- 3.4.2
+ 4.1.5
com.github.pagehelper
@@ -78,11 +91,30 @@
4.2.1
-
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ ${jackson.version}
+
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
com.alibaba
@@ -106,10 +138,6 @@
-
- org.springframework.boot
- spring-boot-maven-plugin
-
maven-compiler-plugin
@@ -118,6 +146,83 @@
UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+ ${project.artifactId}-${project.version}
+
+ *.xml
+ *.properties
+ */*.xml
+
+
+
+ true
+ com.company.project.AppStarter
+
+ lib/
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ unpack
+ package
+
+ unpack
+
+
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+
+
+
+
+
+
+
+
+ maven-assembly-plugin
+
+ seed-test
+
+ src/main/assembly/assembly.xml
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
diff --git a/src/main/assembly/assembly.xml b/src/main/assembly/assembly.xml
new file mode 100644
index 000000000..fc7610fd7
--- /dev/null
+++ b/src/main/assembly/assembly.xml
@@ -0,0 +1,55 @@
+
+
+ assembly
+
+ tar.gz
+
+
+ true
+
+
+ src/main/assembly/bin
+ bin
+ 0755
+
+
+ src/main/resources/
+
+ config
+ 0644
+
+
+
+
+ ${project.build.directory}
+ .
+
+ *.jar
+
+
+
+
+
+
+
+ false
+ lib
+
+
+
\ No newline at end of file
diff --git a/src/main/assembly/bin/dump.sh b/src/main/assembly/bin/dump.sh
new file mode 100644
index 000000000..29006a60f
--- /dev/null
+++ b/src/main/assembly/bin/dump.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+cd `dirname $0`
+BIN_DIR=`pwd`
+cd ..
+DEPLOY_DIR=`pwd`
+CONF_DIR=${DEPLOY_DIR}/config
+
+SERVER_NAME=`sed '/server.servlet.application-display-name/!d;s/.*=//' config/application.properties | tr -d '\r'`
+LOGS_FILE=`sed '/logging.path/!d;s/.*=//' config/application.properties | tr -d '\r'`
+
+if [ -z "$SERVER_NAME" ]; then
+ SERVER_NAME=`hostname`
+fi
+
+PIDS=`ps -ef | grep java | grep "$CONF_DIR" |awk '{print $2}'`
+if [ -z "$PIDS" ]; then
+ echo "ERROR: The $SERVER_NAME does not started!"
+ exit 1
+fi
+
+LOGS_DIR=""
+if [ -n "$LOGS_FILE" ]; then
+ LOGS_DIR=`dirname ${LOGS_FILE}`
+else
+ LOGS_DIR=$HOME/logs
+fi
+if [ ! -d ${LOGS_DIR} ]; then
+ mkdir ${LOGS_DIR}
+fi
+DUMP_DIR=${LOGS_DIR}/dump-${SERVER_NAME}
+if [ ! -d ${DUMP_DIR} ]; then
+ mkdir ${DUMP_DIR}
+fi
+DUMP_DATE=`date +%Y%m%d%H%M%S`
+DATE_DIR=${DUMP_DIR}/${DUMP_DATE}
+if [ ! -d ${DATE_DIR} ]; then
+ mkdir ${DATE_DIR}
+fi
+
+echo -e "Dumping the $SERVER_NAME ...\c"
+for PID in ${PIDS} ; do
+ jstack ${PID} > ${DATE_DIR}/jstack-${PID}.dump 2>&1
+ echo -e ".\c"
+ jinfo ${PID} > ${DATE_DIR}/jinfo-${PID}.dump 2>&1
+ echo -e ".\c"
+ jstat -gcutil ${PID} > ${DATE_DIR}/jstat-gcutil-${PID}.dump 2>&1
+ echo -e ".\c"
+ jstat -gccapacity ${PID} > ${DATE_DIR}/jstat-gccapacity-${PID}.dump 2>&1
+ echo -e ".\c"
+ jmap ${PID} > ${DATE_DIR}/jmap-${PID}.dump 2>&1
+ echo -e ".\c"
+ jmap -heap ${PID} > ${DATE_DIR}/jmap-heap-${PID}.dump 2>&1
+ echo -e ".\c"
+ jmap -histo ${PID} > ${DATE_DIR}/jmap-histo-${PID}.dump 2>&1
+ echo -e ".\c"
+ if [ -r /usr/sbin/lsof ]; then
+ /usr/sbin/lsof -p ${PID} > ${DATE_DIR}/lsof-${PID}.dump
+ echo -e ".\c"
+ fi
+done
+
+if [ -r /bin/netstat ]; then
+/bin/netstat -an > ${DATE_DIR}/netstat.dump 2>&1
+echo -e ".\c"
+fi
+if [ -r /usr/bin/iostat ]; then
+/usr/bin/iostat > ${DATE_DIR}/iostat.dump 2>&1
+echo -e ".\c"
+fi
+if [ -r /usr/bin/mpstat ]; then
+/usr/bin/mpstat > ${DATE_DIR}/mpstat.dump 2>&1
+echo -e ".\c"
+fi
+if [ -r /usr/bin/vmstat ]; then
+/usr/bin/vmstat > ${DATE_DIR}/vmstat.dump 2>&1
+echo -e ".\c"
+fi
+if [ -r /usr/bin/free ]; then
+/usr/bin/free -t > ${DATE_DIR}/free.dump 2>&1
+echo -e ".\c"
+fi
+if [ -r /usr/bin/sar ]; then
+/usr/bin/sar > ${DATE_DIR}/sar.dump 2>&1
+echo -e ".\c"
+fi
+if [ -r /usr/bin/uptime ]; then
+/usr/bin/uptime > ${DATE_DIR}/uptime.dump 2>&1
+echo -e ".\c"
+fi
+
+echo "OK!"
+echo "DUMP: $DATE_DIR"
diff --git a/src/main/assembly/bin/restart.sh b/src/main/assembly/bin/restart.sh
new file mode 100644
index 000000000..647ec1951
--- /dev/null
+++ b/src/main/assembly/bin/restart.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+cd `dirname $0`
+./stop.sh
+./start.sh
diff --git a/src/main/assembly/bin/server.sh b/src/main/assembly/bin/server.sh
new file mode 100644
index 000000000..90947a5de
--- /dev/null
+++ b/src/main/assembly/bin/server.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+cd `dirname $0`
+if [ "$1" = "start" ]; then
+ ./start.sh
+else
+ if [ "$1" = "stop" ]; then
+ ./stop.sh
+ else
+ if [ "$1" = "debug" ]; then
+ ./start.sh debug
+ else
+ if [ "$1" = "restart" ]; then
+ ./restart.sh
+ else
+ if [ "$1" = "dump" ]; then
+ ./dump.sh
+ else
+ echo "ERROR: Please input argument: start or stop or debug or restart or dump"
+ exit 1
+ fi
+ fi
+ fi
+ fi
+fi
diff --git a/src/main/assembly/bin/start.sh b/src/main/assembly/bin/start.sh
new file mode 100644
index 000000000..5d4602987
--- /dev/null
+++ b/src/main/assembly/bin/start.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+cd `dirname $0`
+BIN_DIR=`pwd`
+cd ..
+DEPLOY_DIR=`pwd`
+CONF_DIR=${DEPLOY_DIR}/config
+
+SERVER_NAME=`sed '/server.servlet.application-display-name/!d;s/.*=//' config/application.properties | tr -d '\r'`
+SERVER_PORT=`sed '/server.port/!d;s/.*=//' config/application.properties | tr -d '\r'`
+PROFILES_ACTIVE=`sed '/spring.profiles.active/!d;s/.*=//' config/application.properties | tr -d '\r'`
+LOGS_FILE=`sed '/logging.path/!d;s/.*=//' config/application.properties | tr -d '\r'`
+
+ACTIVE_FILE=application-"$PROFILES_ACTIVE".properties
+EXECUTE_FILE=spring-boot-api-project-seed-1.0.jar
+
+if [ -z "$SERVER_NAME" ]; then
+ SERVER_NAME=`hostname`
+fi
+
+PIDS=`ps -ef | grep java | grep "$CONF_DIR" |awk '{print $2}'`
+if [ -n "$PIDS" ]; then
+ echo "ERROR: The $SERVER_NAME already started!"
+ echo "PID: $PIDS"
+ exit 1
+fi
+
+if [ -n "$SERVER_PORT" ]; then
+ SERVER_PORT_COUNT=`netstat -tln | grep ${SERVER_PORT} | wc -l`
+ if [ ${SERVER_PORT_COUNT} -gt 0 ]; then
+ echo "ERROR: The $SERVER_NAME port $SERVER_PORT already used!"
+ exit 1
+ fi
+fi
+
+LOGS_DIR=""
+if [ -n "$LOGS_FILE" ]; then
+ LOGS_DIR=`dirname ${LOGS_FILE}`
+else
+ LOGS_DIR=$HOME/logs
+fi
+if [ ! -d ${LOGS_DIR} ]; then
+ mkdir ${LOGS_DIR}
+fi
+STDOUT_FILE=${LOGS_DIR}/stdout-${SERVER_NAME}.log
+
+LIB_DIR=${DEPLOY_DIR}/lib
+LIB_JARS=`ls ${LIB_DIR}|grep .jar|awk '{print "'${LIB_DIR}'/"$0}'|tr "\n" ":"`
+
+JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true "
+JAVA_DEBUG_OPTS=""
+if [ "$1" = "debug" ]; then
+ JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE \
+ -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n "
+fi
+JAVA_JMX_OPTS=""
+if [ "$1" = "jmx" ]; then
+ JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false \
+ -Dcom.sun.management.jmxremote.authenticate=false "
+fi
+JAVA_MEM_OPTS=""
+BITS=`java -version 2>&1 | grep -i 64-bit`
+if [ -n "$BITS" ]; then
+ JAVA_MEM_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC \
+ -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m \
+ -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
+else
+ JAVA_MEM_OPTS=" -server -Xms1g -Xmx1g -XX:SurvivorRatio=2 -XX:+UseParallelGC "
+fi
+
+echo -e "Starting the $SERVER_NAME ...\c"
+
+nohup java ${JAVA_OPTS} ${JAVA_MEM_OPTS} ${JAVA_DEBUG_OPTS} ${JAVA_JMX_OPTS} \
+-Dloader.path=${LIB_DIR},${CONF_DIR} -jar ${DEPLOY_DIR}/${EXECUTE_FILE} > ${STDOUT_FILE} 2>&1 &
+#-Dspring.config.location=${CONF_DIR}/application.properties,${CONF_DIR}/${ACTIVE_FILE} > ${STDOUT_FILE} 2>&1 &
+
+# 最长检测 1 分钟,可能的结果是标志文件不存在,这个要开发人员自己检查进程启动是否有问题.
+CHECK_MAX_COUNT=30
+COUNT=0
+while [ ${CHECK_MAX_COUNT} -gt 1 ]; do
+ echo -e ".\c"
+ sleep 2
+ if [ -n "$SERVER_PORT" ]; then
+ COUNT=`netstat -an | grep ${SERVER_PORT} | wc -l`
+ else
+ COUNT=`ps -ef | grep java | grep "$DEPLOY_DIR" | awk '{print $2}' | wc -l`
+ fi
+ if [ ${COUNT} -gt 0 ]; then
+ break
+ fi
+
+ ((CHECK_MAX_COUNT--))
+done
+
+echo "OK!"
+PIDS=`ps -ef | grep java | grep "$DEPLOY_DIR" | awk '{print $2}'`
+echo "PID: $PIDS"
+echo "STDOUT: $STDOUT_FILE"
diff --git a/src/main/assembly/bin/stop.sh b/src/main/assembly/bin/stop.sh
new file mode 100644
index 000000000..c0ee67a74
--- /dev/null
+++ b/src/main/assembly/bin/stop.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+cd `dirname $0`
+BIN_DIR=`pwd`
+cd ..
+DEPLOY_DIR=`pwd`
+CONF_DIR=${DEPLOY_DIR}/config
+
+SERVER_NAME=`sed '/server.servlet.application-display-name/!d;s/.*=//' config/application.properties | tr -d '\r'`
+
+if [ -z "$SERVER_NAME" ]; then
+ SERVER_NAME=`hostname`
+fi
+
+PIDS=`ps -ef | grep java | grep "$CONF_DIR" |awk '{print $2}'`
+if [ -z "$PIDS" ]; then
+ echo "ERROR: The $SERVER_NAME does not started!"
+ exit 1
+fi
+
+if [ "$1" != "skip" ]; then
+ ${BIN_DIR}/dump.sh
+fi
+
+echo -e "Stopping the $SERVER_NAME ...\c"
+for PID in ${PIDS} ; do
+ kill ${PID} > /dev/null 2>&1
+done
+
+COUNT=0
+while [ ${COUNT} -lt 1 ]; do
+ echo -e ".\c"
+ sleep 1
+ COUNT=1
+ for PID in ${PIDS} ; do
+ PID_EXIST=`ps -p ${PID} | grep java`
+ if [ -n "$PID_EXIST" ]; then
+ COUNT=0
+ break
+ fi
+ done
+done
+
+echo "OK!"
+echo "PID: $PIDS"
diff --git a/src/main/java/com/company/project/Application.java b/src/main/java/com/company/project/AppStarter.java
similarity index 50%
rename from src/main/java/com/company/project/Application.java
rename to src/main/java/com/company/project/AppStarter.java
index da17b6a1a..07e86c484 100644
--- a/src/main/java/com/company/project/Application.java
+++ b/src/main/java/com/company/project/AppStarter.java
@@ -2,11 +2,18 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.RequestMapping;
@SpringBootApplication
-public class Application {
+public class AppStarter {
+
+ @RequestMapping("/")
+ String home() {
+ return "Hello World!";
+ }
+
public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
+ SpringApplication.run(AppStarter.class, args);
}
}
diff --git a/src/main/java/com/company/project/configurer/WebMvcConfigurer.java b/src/main/java/com/company/project/configurer/MyWebMvcConfigurer.java
similarity index 55%
rename from src/main/java/com/company/project/configurer/WebMvcConfigurer.java
rename to src/main/java/com/company/project/configurer/MyWebMvcConfigurer.java
index c9460d3fc..6b9859352 100644
--- a/src/main/java/com/company/project/configurer/WebMvcConfigurer.java
+++ b/src/main/java/com/company/project/configurer/MyWebMvcConfigurer.java
@@ -1,21 +1,6 @@
package com.company.project.configurer;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.serializer.SerializerFeature;
-import com.alibaba.fastjson.support.config.FastJsonConfig;
-import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
-
+import com.company.project.core.CustomObjectMapper;
import com.company.project.core.Result;
import com.company.project.core.ResultCode;
import com.company.project.core.ServiceException;
@@ -25,100 +10,120 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
-import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+import javax.annotation.Resource;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
/**
* Spring MVC 配置
*/
@Configuration
-public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
+public class MyWebMvcConfigurer implements WebMvcConfigurer {
- private final Logger logger = LoggerFactory.getLogger(WebMvcConfigurer.class);
+ private final Logger logger = LoggerFactory.getLogger(MyWebMvcConfigurer.class);
+ /**
+ * 当前激活的配置文件
+ */
@Value("${spring.profiles.active}")
- private String env;//当前激活的配置文件
+ private String env;
- //使用阿里 FastJson 作为JSON MessageConverter
+ @Resource
+ private CustomObjectMapper objectMapper;
+
+ /**
+ * 使用Jackson作为JSON MessageConverter
+ *
+ * @param converters
+ */
@Override
public void configureMessageConverters(List> converters) {
- FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
- FastJsonConfig config = new FastJsonConfig();
- config.setSerializerFeatures(SerializerFeature.WriteMapNullValue);//保留空的字段
- //SerializerFeature.WriteNullStringAsEmpty,//String null -> ""
- //SerializerFeature.WriteNullNumberAsZero//Number null -> 0
- // 按需配置,更多参考FastJson文档哈
-
- converter.setFastJsonConfig(config);
- converter.setDefaultCharset(Charset.forName("UTF-8"));
- converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
+ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+ converter.setObjectMapper(objectMapper);
converters.add(converter);
}
- //统一异常处理
+ /**
+ * 统一异常处理
+ *
+ * @param exceptionResolvers
+ */
@Override
public void configureHandlerExceptionResolvers(List exceptionResolvers) {
- exceptionResolvers.add(new HandlerExceptionResolver() {
- public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
- Result result = new Result();
- if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误”
- result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
- logger.info(e.getMessage());
- } else if (e instanceof NoHandlerFoundException) {
- result.setCode(ResultCode.NOT_FOUND).setMessage("接口 [" + request.getRequestURI() + "] 不存在");
- } else if (e instanceof ServletException) {
- result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
+ exceptionResolvers.add((request, response, handler, e) -> {
+ Result result = new Result();
+ // 业务失败的异常,如“账号或密码错误”
+ if (e instanceof ServiceException) {
+ result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
+ logger.info(e.getMessage());
+ } else if (e instanceof NoHandlerFoundException) {
+ result.setCode(ResultCode.NOT_FOUND).setMessage("接口 [" + request.getRequestURI() + "] 不存在");
+ } else if (e instanceof ServletException) {
+ result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
+ } else {
+ result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");
+ String message;
+ if (handler instanceof HandlerMethod) {
+ HandlerMethod handlerMethod = (HandlerMethod) handler;
+ message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
+ request.getRequestURI(),
+ handlerMethod.getBean().getClass().getName(),
+ handlerMethod.getMethod().getName(),
+ e.getMessage());
} else {
- result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");
- String message;
- if (handler instanceof HandlerMethod) {
- HandlerMethod handlerMethod = (HandlerMethod) handler;
- message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s",
- request.getRequestURI(),
- handlerMethod.getBean().getClass().getName(),
- handlerMethod.getMethod().getName(),
- e.getMessage());
- } else {
- message = e.getMessage();
- }
- logger.error(message, e);
+ message = e.getMessage();
}
- responseResult(response, result);
- return new ModelAndView();
+ logger.error(message, e);
}
-
+ responseResult(response, result);
+ return new ModelAndView();
});
}
- //解决跨域问题
+ /**
+ * 解决跨域问题
+ *
+ * @param registry
+ */
@Override
public void addCorsMappings(CorsRegistry registry) {
//registry.addMapping("/**");
}
- //添加拦截器
+ /**
+ * 添加拦截器
+ */
@Override
public void addInterceptors(InterceptorRegistry registry) {
//接口签名认证拦截器,该签名认证比较简单,实际项目中可以使用Json Web Token或其他更好的方式替代。
- if (!"dev".equals(env)) { //开发环境忽略签名认证
+ //开发环境忽略签名认证
+ if (!"dev".equals(env)) {
registry.addInterceptor(new HandlerInterceptorAdapter() {
@Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//验证签名
boolean pass = validateSign(request);
if (pass) {
return true;
} else {
logger.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}",
- request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));
+ request.getRequestURI(), getIpAddress(request), objectMapper.toJSONString(request.getParameterMap()));
Result result = new Result();
result.setCode(ResultCode.UNAUTHORIZED).setMessage("签名认证失败");
@@ -135,7 +140,7 @@ private void responseResult(HttpServletResponse response, Result result) {
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.setStatus(200);
try {
- response.getWriter().write(JSON.toJSONString(result));
+ response.getWriter().write(objectMapper.toJSONString(result));
} catch (IOException ex) {
logger.error(ex.getMessage());
}
@@ -148,25 +153,33 @@ private void responseResult(HttpServletResponse response, Result result) {
* 3. 混合密钥(secret)进行md5获得签名,与请求的签名进行比较
*/
private boolean validateSign(HttpServletRequest request) {
- String requestSign = request.getParameter("sign");//获得请求签名,如sign=19e907700db7ad91318424a97c54ed57
+ // 获得请求签名,如sign=19e907700db7ad91318424a97c54ed57
+ String requestSign = request.getParameter("sign");
if (StringUtils.isEmpty(requestSign)) {
return false;
}
- List keys = new ArrayList(request.getParameterMap().keySet());
- keys.remove("sign");//排除sign参数
- Collections.sort(keys);//排序
+ List keys = new ArrayList<>(request.getParameterMap().keySet());
+ // 排除sign参数
+ keys.remove("sign");
+ // 排序
+ Collections.sort(keys);
StringBuilder sb = new StringBuilder();
for (String key : keys) {
- sb.append(key).append("=").append(request.getParameter(key)).append("&");//拼接字符串
+ // 拼接字符串
+ sb.append(key).append("=").append(request.getParameter(key)).append("&");
}
String linkString = sb.toString();
- linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);//去除最后一个'&'
+ // 去除最后一个'&'
+ linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);
- String secret = "Potato";//密钥,自己修改
- String sign = DigestUtils.md5Hex(linkString + secret);//混合密钥md5
+ // 密钥,自己修改
+ String secret = "Potato";
+ // 混合密钥md5
+ String sign = DigestUtils.md5Hex(linkString + secret);
- return StringUtils.equals(sign, requestSign);//比较
+ // 比较
+ return StringUtils.equals(sign, requestSign);
}
private String getIpAddress(HttpServletRequest request) {
@@ -187,7 +200,7 @@ private String getIpAddress(HttpServletRequest request) {
ip = request.getRemoteAddr();
}
// 如果是多级代理,那么取第一个ip为客户端ip
- if (ip != null && ip.indexOf(",") != -1) {
+ if (ip != null && ip.contains(",")) {
ip = ip.substring(0, ip.indexOf(",")).trim();
}
diff --git a/src/main/java/com/company/project/configurer/MybatisConfigurer.java b/src/main/java/com/company/project/configurer/MybatisConfigurer.java
index 0d6487d86..cc31e804e 100644
--- a/src/main/java/com/company/project/configurer/MybatisConfigurer.java
+++ b/src/main/java/com/company/project/configurer/MybatisConfigurer.java
@@ -4,20 +4,16 @@
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
-import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;
-import static com.company.project.core.ProjectConstant.*;
+import static com.company.project.core.ProjectConstants.*;
/**
* Mybatis & Mapper & PageHelper 配置
@@ -31,12 +27,15 @@ public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exc
factory.setDataSource(dataSource);
factory.setTypeAliasesPackage(MODEL_PACKAGE);
- //配置分页插件,详情请查阅官方文档
+ // 配置分页插件,详情请查阅官方文档
PageHelper pageHelper = new PageHelper();
Properties properties = new Properties();
- properties.setProperty("pageSizeZero", "true");//分页尺寸为0时查询所有纪录不再执行分页
- properties.setProperty("reasonable", "true");//页码<=0 查询第一页,页码>=总页数查询最后一页
- properties.setProperty("supportMethodsArguments", "true");//支持通过 Mapper 接口参数来传递分页参数
+ // 分页尺寸为0时查询所有纪录不再执行分页
+ properties.setProperty("pageSizeZero", "true");
+ // 页码<=0 查询第一页,页码>=总页数查询最后一页
+ properties.setProperty("reasonable", "true");
+ // 支持通过 Mapper 接口参数来传递分页参数
+ properties.setProperty("supportMethodsArguments", "true");
pageHelper.setProperties(properties);
//添加插件
@@ -54,10 +53,11 @@ public MapperScannerConfigurer mapperScannerConfigurer() {
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
mapperScannerConfigurer.setBasePackage(MAPPER_PACKAGE);
- //配置通用Mapper,详情请查阅官方文档
+ // 配置通用Mapper,详情请查阅官方文档
Properties properties = new Properties();
properties.setProperty("mappers", MAPPER_INTERFACE_REFERENCE);
- properties.setProperty("notEmpty", "false");//insert、update是否判断字符串类型!='' 即 test="str != null"表达式内是否追加 and str != ''
+ //insert、update是否判断字符串类型!='' 即 test="str != null"表达式内是否追加 and str != ''
+ properties.setProperty("notEmpty", "false");
properties.setProperty("IDENTITY", "MYSQL");
mapperScannerConfigurer.setProperties(properties);
diff --git a/src/main/java/com/company/project/core/AbstractService.java b/src/main/java/com/company/project/core/AbstractService.java
index 35dbf8201..1e8a0ee7e 100644
--- a/src/main/java/com/company/project/core/AbstractService.java
+++ b/src/main/java/com/company/project/core/AbstractService.java
@@ -17,33 +17,42 @@ public abstract class AbstractService implements Service {
@Autowired
protected Mapper mapper;
- private Class modelClass; // 当前泛型真实类型的Class
+ /**
+ * 当前泛型真实类型的Class
+ */
+ private Class modelClass;
public AbstractService() {
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
modelClass = (Class) pt.getActualTypeArguments()[0];
}
+ @Override
public void save(T model) {
mapper.insertSelective(model);
}
+ @Override
public void save(List models) {
mapper.insertList(models);
}
+ @Override
public void deleteById(Integer id) {
mapper.deleteByPrimaryKey(id);
}
+ @Override
public void deleteByIds(String ids) {
mapper.deleteByIds(ids);
}
+ @Override
public void update(T model) {
mapper.updateByPrimaryKeySelective(model);
}
+ @Override
public T findById(Integer id) {
return mapper.selectByPrimaryKey(id);
}
@@ -61,14 +70,17 @@ public T findBy(String fieldName, Object value) throws TooManyResultsException {
}
}
+ @Override
public List findByIds(String ids) {
return mapper.selectByIds(ids);
}
+ @Override
public List findByCondition(Condition condition) {
return mapper.selectByCondition(condition);
}
+ @Override
public List findAll() {
return mapper.selectAll();
}
diff --git a/src/main/java/com/company/project/core/CustomObjectMapper.java b/src/main/java/com/company/project/core/CustomObjectMapper.java
new file mode 100644
index 000000000..3ed0b51c7
--- /dev/null
+++ b/src/main/java/com/company/project/core/CustomObjectMapper.java
@@ -0,0 +1,58 @@
+package com.company.project.core;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+/**
+ * 定制 Jackson 的 ObjectMapper
+ *
+ * @author
+ * @since 1.0.0
+ */
+@Component
+public class CustomObjectMapper extends ObjectMapper {
+
+ private static final long serialVersionUID = 1L;
+
+ public CustomObjectMapper() {
+ super();
+ init();
+ }
+
+ public void init() {
+ // 排除值为空属性,只对POJO起作用,map或者list无效
+// setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+
+ // 是否进行缩进输出
+ configure(SerializationFeature.INDENT_OUTPUT, false);
+
+ // 将驼峰转为下划线
+ // setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
+
+ // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
+ this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ this.setTimeZone(TimeZone.getDefault());
+
+ // 进行日期格式化
+ String dateFormatPattern = "yyyy-MM-dd HH:mm:ss";
+ this.setDateFormat(new SimpleDateFormat(dateFormatPattern));
+ }
+
+
+ public String toJSONString(Object object) {
+ try {
+ return writeValueAsString(object);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/company/project/core/ProjectConstant.java b/src/main/java/com/company/project/core/ProjectConstant.java
deleted file mode 100644
index 76d6abe4c..000000000
--- a/src/main/java/com/company/project/core/ProjectConstant.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.company.project.core;
-
-/**
- * 项目常量
- */
-public final class ProjectConstant {
- public static final String BASE_PACKAGE = "com.company.project";//生成代码所在的基础包名称,可根据自己公司的项目修改(注意:这个配置修改之后需要手工修改src目录项目默认的包路径,使其保持一致,不然会找不到类)
-
- public static final String MODEL_PACKAGE = BASE_PACKAGE + ".model";//生成的Model所在包
- public static final String MAPPER_PACKAGE = BASE_PACKAGE + ".dao";//生成的Mapper所在包
- public static final String SERVICE_PACKAGE = BASE_PACKAGE + ".service";//生成的Service所在包
- public static final String SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";//生成的ServiceImpl所在包
- public static final String CONTROLLER_PACKAGE = BASE_PACKAGE + ".web";//生成的Controller所在包
-
- public static final String MAPPER_INTERFACE_REFERENCE = BASE_PACKAGE + ".core.Mapper";//Mapper插件基础接口的完全限定名
-}
diff --git a/src/main/java/com/company/project/core/ProjectConstants.java b/src/main/java/com/company/project/core/ProjectConstants.java
new file mode 100644
index 000000000..16c613a13
--- /dev/null
+++ b/src/main/java/com/company/project/core/ProjectConstants.java
@@ -0,0 +1,37 @@
+package com.company.project.core;
+
+/**
+ * 项目常量,除BASE_PACKAGE建议修改以外,别的常量均不建议修改
+ * 因为这里修改后,在generator.template里面也需要再次修改引用包的路径
+ */
+public final class ProjectConstants {
+ /**
+ * 生成代码所在的基础包名称,可根据自己公司的项目修改
+ * (注意:这个配置修改之后需要手工修改src目录项目默认的包路径,使其保持一致,不然会找不到类)
+ */
+ public static final String BASE_PACKAGE = "com.company.project";
+ /**
+ * 生成的Model所在包
+ */
+ public static final String MODEL_PACKAGE = BASE_PACKAGE + ".model";
+ /**
+ * 生成的Mapper所在包
+ */
+ public static final String MAPPER_PACKAGE = BASE_PACKAGE + ".dao";
+ /**
+ * 生成的Service所在包
+ */
+ public static final String SERVICE_PACKAGE = BASE_PACKAGE + ".service";
+ /**
+ * 生成的ServiceImpl所在包
+ */
+ public static final String SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";
+ /**
+ * 生成的Controller所在包
+ */
+ public static final String CONTROLLER_PACKAGE = BASE_PACKAGE + ".web";
+ /**
+ * Mapper插件基础接口的完全限定名
+ */
+ public static final String MAPPER_INTERFACE_REFERENCE = BASE_PACKAGE + ".core.Mapper";
+}
diff --git a/src/main/java/com/company/project/core/Result.java b/src/main/java/com/company/project/core/Result.java
index 85ba3a114..a4f53d94c 100644
--- a/src/main/java/com/company/project/core/Result.java
+++ b/src/main/java/com/company/project/core/Result.java
@@ -1,7 +1,5 @@
package com.company.project.core;
-import com.alibaba.fastjson.JSON;
-
/**
* 统一API响应结果封装
*/
@@ -36,9 +34,4 @@ public Result setData(T data) {
this.data = data;
return this;
}
-
- @Override
- public String toString() {
- return JSON.toJSONString(this);
- }
}
diff --git a/src/main/java/com/company/project/core/Service.java b/src/main/java/com/company/project/core/Service.java
index 5fec7ca13..03e8a6a83 100644
--- a/src/main/java/com/company/project/core/Service.java
+++ b/src/main/java/com/company/project/core/Service.java
@@ -9,14 +9,75 @@
* Service 层 基础接口,其他Service 接口 请继承该接口
*/
public interface Service {
- void save(T model);//持久化
- void save(List models);//批量持久化
- void deleteById(Integer id);//通过主鍵刪除
- void deleteByIds(String ids);//批量刪除 eg:ids -> “1,2,3,4”
- void update(T model);//更新
- T findById(Integer id);//通过ID查找
- T findBy(String fieldName, Object value) throws TooManyResultsException; //通过Model中某个成员变量名称(非数据表中column的名称)查找,value需符合unique约束
- List findByIds(String ids);//通过多个ID查找//eg:ids -> “1,2,3,4”
- List findByCondition(Condition condition);//根据条件查找
- List findAll();//获取所有
+ /**
+ * 持久化
+ */
+ void save(T model);
+
+ /**
+ * 批量持久化
+ */
+ void save(List models);
+
+ /**
+ * 通过主鍵刪除
+ *
+ * @param id primary key
+ */
+ void deleteById(Integer id);
+
+ /**
+ * 批量刪除
+ *
+ * @param ids eg:ids -> “1,2,3,4”
+ */
+ void deleteByIds(String ids);
+
+ /**
+ * 更新
+ *
+ * @param model
+ */
+ void update(T model);
+
+ /**
+ * 通过ID查找
+ *
+ * @param id
+ * @return
+ */
+ T findById(Integer id);
+
+ /**
+ * 通过Model中某个成员变量名称(非数据表中column的名称)查找,value需符合unique约束
+ *
+ * @param fieldName fieldName
+ * @param value value
+ * @return
+ * @throws TooManyResultsException
+ */
+ T findBy(String fieldName, Object value) throws TooManyResultsException;
+
+ /**
+ * 通过多个ID查找//eg:ids -> “1,2,3,4”
+ *
+ * @param ids
+ * @return
+ */
+ List findByIds(String ids);
+
+ /**
+ * 根据条件查找
+ *
+ * @param condition condition
+ * @return
+ */
+ List findByCondition(Condition condition);
+
+ /**
+ * 获取所有
+ *
+ * @return
+ */
+ List findAll();
}
diff --git a/src/main/java/com/company/project/dao/UserTesterMapper.java b/src/main/java/com/company/project/dao/UserTesterMapper.java
new file mode 100644
index 000000000..16fb22ef1
--- /dev/null
+++ b/src/main/java/com/company/project/dao/UserTesterMapper.java
@@ -0,0 +1,7 @@
+package com.company.project.dao;
+
+import com.company.project.core.Mapper;
+import com.company.project.model.UserTester;
+
+public interface UserTesterMapper extends Mapper {
+}
\ No newline at end of file
diff --git a/src/main/java/com/company/project/model/UserTester.java b/src/main/java/com/company/project/model/UserTester.java
new file mode 100644
index 000000000..4b04a7b9a
--- /dev/null
+++ b/src/main/java/com/company/project/model/UserTester.java
@@ -0,0 +1,148 @@
+package com.company.project.model;
+
+import java.util.Date;
+import javax.persistence.*;
+
+@Table(name = "t_user_tester")
+public class UserTester {
+
+ /** 多个ID注解可以作为联合主键 */
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Integer id;
+
+ private String name;
+
+ /**
+ * 0-关闭,1-正常
+ */
+ private String state;
+
+ /**
+ * 创建时间
+ */
+ @Column(name = "create_time")
+ private Date createTime;
+
+ @Column(name = "create_by")
+ private String createBy;
+
+ /**
+ * 更新时间
+ */
+ @Column(name = "update_time")
+ private Date updateTime;
+
+ @Column(name = "update_by")
+ private String updateBy;
+
+ /**
+ * @return id
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
+ * @param id
+ */
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ /**
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * 获取0-关闭,1-正常
+ *
+ * @return state - 0-关闭,1-正常
+ */
+ public String getState() {
+ return state;
+ }
+
+ /**
+ * 设置0-关闭,1-正常
+ *
+ * @param state 0-关闭,1-正常
+ */
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ /**
+ * 获取创建时间
+ *
+ * @return create_time - 创建时间
+ */
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ /**
+ * 设置创建时间
+ *
+ * @param createTime 创建时间
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * @return create_by
+ */
+ public String getCreateBy() {
+ return createBy;
+ }
+
+ /**
+ * @param createBy
+ */
+ public void setCreateBy(String createBy) {
+ this.createBy = createBy;
+ }
+
+ /**
+ * 获取更新时间
+ *
+ * @return update_time - 更新时间
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ /**
+ * 设置更新时间
+ *
+ * @param updateTime 更新时间
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ /**
+ * @return update_by
+ */
+ public String getUpdateBy() {
+ return updateBy;
+ }
+
+ /**
+ * @param updateBy
+ */
+ public void setUpdateBy(String updateBy) {
+ this.updateBy = updateBy;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/company/project/service/UserTesterService.java b/src/main/java/com/company/project/service/UserTesterService.java
new file mode 100644
index 000000000..f17ab700b
--- /dev/null
+++ b/src/main/java/com/company/project/service/UserTesterService.java
@@ -0,0 +1,11 @@
+package com.company.project.service;
+import com.company.project.model.UserTester;
+import com.company.project.core.Service;
+
+
+/**
+ * Created by CodeGenerator on 2019-04-09 09:43:40.
+ */
+public interface UserTesterService extends Service {
+
+}
diff --git a/src/main/java/com/company/project/service/impl/UserTesterServiceImpl.java b/src/main/java/com/company/project/service/impl/UserTesterServiceImpl.java
new file mode 100644
index 000000000..4d0ddd384
--- /dev/null
+++ b/src/main/java/com/company/project/service/impl/UserTesterServiceImpl.java
@@ -0,0 +1,22 @@
+package com.company.project.service.impl;
+
+import com.company.project.dao.UserTesterMapper;
+import com.company.project.model.UserTester;
+import com.company.project.service.UserTesterService;
+import com.company.project.core.AbstractService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+
+/**
+ * Created by CodeGenerator on 2019-04-09 09:43:40.
+ */
+@Service
+@Transactional
+public class UserTesterServiceImpl extends AbstractService implements UserTesterService {
+ @Resource
+ private UserTesterMapper tUserTesterMapper;
+
+}
diff --git a/src/main/java/com/company/project/web/UserTesterController.java b/src/main/java/com/company/project/web/UserTesterController.java
new file mode 100644
index 000000000..93b7ab77e
--- /dev/null
+++ b/src/main/java/com/company/project/web/UserTesterController.java
@@ -0,0 +1,63 @@
+package com.company.project.web;
+import com.company.project.core.CustomObjectMapper;
+import com.company.project.core.Result;
+import com.company.project.core.ResultGenerator;
+import com.company.project.model.UserTester;
+import com.company.project.service.UserTesterService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+* Created by CodeGenerator on 2019-04-09 09:43:40.
+*/
+@RestController
+@RequestMapping("/user/tester")
+public class UserTesterController {
+ private static final Logger LOGGER = LoggerFactory.getLogger(UserTesterController.class);
+ @Resource
+ private UserTesterService userTesterService;
+ @Resource
+ private CustomObjectMapper objectMapper;
+
+ @PostMapping("/add")
+ public Result add(UserTester userTester) {
+ userTesterService.save(userTester);
+ return ResultGenerator.genSuccessResult();
+ }
+
+ @PostMapping("/delete")
+ public Result delete(@RequestParam Integer id) {
+ userTesterService.deleteById(id);
+ return ResultGenerator.genSuccessResult();
+ }
+
+ @PostMapping("/update")
+ public Result update(UserTester userTester) {
+ userTesterService.update(userTester);
+ return ResultGenerator.genSuccessResult();
+ }
+
+ @RequestMapping("/detail")
+ public Result detail(@RequestParam Integer id) {
+ UserTester userTester = userTesterService.findById(id);
+ return ResultGenerator.genSuccessResult(userTester);
+ }
+
+ @RequestMapping("/list")
+ public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) {
+ PageHelper.startPage(page, size);
+ List list = userTesterService.findAll();
+ PageInfo pageInfo = new PageInfo(list);
+ LOGGER.info("返回到前端的数据=[{}]", objectMapper.toJSONString(pageInfo));
+ return ResultGenerator.genSuccessResult(pageInfo);
+ }
+}
diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties
index 71aa3d9b0..b1e52e825 100644
--- a/src/main/resources/application-dev.properties
+++ b/src/main/resources/application-dev.properties
@@ -2,5 +2,8 @@
# 数据源配置,请修改为你项目的实际配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
-spring.datasource.password=123456
-spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.password=root
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+# 开发环境和生产环境的部署方式与本机不一样
+logging.config=config/logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties
index 287da7b20..c39c5c4d3 100644
--- a/src/main/resources/application-test.properties
+++ b/src/main/resources/application-test.properties
@@ -1 +1,8 @@
# 测试环境配置
+# 数据源配置,请修改为你项目的实际配置
+spring.datasource.url=jdbc:mysql://localhost:3306/test
+spring.datasource.username=root
+spring.datasource.password=root
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+logging.config=classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index e217b7192..2dff4ca94 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,6 +1,13 @@
-spring.profiles.active=dev
+
# 所有环境通用的配置,放在这里
+server.port=7071
+# 根路径
+server.servlet.context-path=/seed
+# 应用名称
+server.servlet.application-display-name=SEED
+# 激活的配置文件
+spring.profiles.active=test
# 404 交给异常处理器处理
spring.mvc.throw-exception-if-no-handler-found=true
-spring.resources.add-mappings=false
+spring.resources.add-mappings=false
\ No newline at end of file
diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml
new file mode 100644
index 000000000..0e91693d0
--- /dev/null
+++ b/src/main/resources/logback-spring.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} \(L%line\) - %msg%n
+
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} \(L%line\) - %msg%n
+
+ ${LOG_PATH}/${BASE_FILE_NAME}.log
+
+
+ ${LOG_PATH}/history/${BASE_FILE_NAME}.%d{yyyy-MM-dd}.%i.gz
+ ${LOG_FILE_MAX_SIZE}
+ ${LOG_FILE_MAX_HISTORY}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/mapper/UserTesterMapper.xml b/src/main/resources/mapper/UserTesterMapper.xml
new file mode 100644
index 000000000..e65a96e75
--- /dev/null
+++ b/src/main/resources/mapper/UserTesterMapper.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/CodeGenerator.java b/src/test/java/CodeGenerator.java
index 05928e2bf..92127ffc0 100644
--- a/src/test/java/CodeGenerator.java
+++ b/src/test/java/CodeGenerator.java
@@ -11,39 +11,72 @@
import java.text.SimpleDateFormat;
import java.util.*;
-import static com.company.project.core.ProjectConstant.*;
+import static com.company.project.core.ProjectConstants.*;
/**
* 代码生成器,根据数据表名称生成对应的Model、Mapper、Service、Controller简化开发。
+ *
+ * @author administrator
+ * @date 2019-04-09
*/
public class CodeGenerator {
- //JDBC配置,请修改为你项目的实际配置
+ /**
+ * JDBC配置,请修改为你项目的实际配置
+ */
private static final String JDBC_URL = "jdbc:mysql://localhost:3306/test";
private static final String JDBC_USERNAME = "root";
- private static final String JDBC_PASSWORD = "123456";
+ private static final String JDBC_PASSWORD = "root";
private static final String JDBC_DIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
- private static final String PROJECT_PATH = System.getProperty("user.dir");//项目在硬盘上的基础路径
- private static final String TEMPLATE_FILE_PATH = PROJECT_PATH + "/src/test/resources/generator/template";//模板位置
+ /**
+ * 项目在硬盘上的基础路径
+ */
+ private static final String PROJECT_PATH = System.getProperty("user.dir");
+ /**
+ * 模板位置
+ */
+ private static final String TEMPLATE_FILE_PATH = PROJECT_PATH + "/src/test/resources/generator/template";
- private static final String JAVA_PATH = "/src/main/java"; //java文件路径
- private static final String RESOURCES_PATH = "/src/main/resources";//资源文件路径
+ /**
+ * java文件路径
+ */
+ 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);//生成的Service存放路径
- private static final String PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(SERVICE_IMPL_PACKAGE);//生成的Service实现存放路径
- private static final String PACKAGE_PATH_CONTROLLER = packageConvertPath(CONTROLLER_PACKAGE);//生成的Controller存放路径
+ /**
+ * 生成的Service存放路径
+ */
+ private static final String PACKAGE_PATH_SERVICE = packageConvertPath(SERVICE_PACKAGE);
+ /**
+ * 生成的Service实现存放路径
+ */
+ private static final String PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(SERVICE_IMPL_PACKAGE);
+ /**
+ * 生成的Controller存放路径
+ */
+ private static final String PACKAGE_PATH_CONTROLLER = packageConvertPath(CONTROLLER_PACKAGE);
- private static final String AUTHOR = "CodeGenerator";//@author
- private static final String DATE = new SimpleDateFormat("yyyy/MM/dd").format(new Date());//@date
+ /**
+ * 作者信息
+ */
+ private static final String AUTHOR = "CodeGenerator";
+ /**
+ * 时间
+ */
+ private static final String DATE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
public static void main(String[] args) {
- genCode("输入表名");
- //genCodeByCustomModelName("输入表名","输入自定义Model名称");
+// genCode("输入表名");
+ genCodeByCustomModelName("t_user_tester","UserTester");
}
/**
* 通过数据表名称生成代码,Model 名称通过解析数据表名称获得,下划线转大驼峰的形式。
* 如输入表名称 "t_user_detail" 将生成 TUserDetail、TUserDetailMapper、TUserDetailService ...
+ *
* @param tableNames 数据表名称...
*/
public static void genCode(String... tableNames) {
@@ -55,6 +88,7 @@ public static void genCode(String... tableNames) {
/**
* 通过数据表名称,和自定义的 Model 名称生成代码
* 如输入表名称 "t_user_detail" 和自定义的 Model 名称 "User" 将生成 User、UserMapper、UserService ...
+ *
* @param tableName 数据表名称
* @param modelName 自定义的 Model 名称
*/
@@ -102,7 +136,7 @@ public static void genModelAndMapper(String tableName, String modelName) {
TableConfiguration tableConfiguration = new TableConfiguration(context);
tableConfiguration.setTableName(tableName);
- if (StringUtils.isNotEmpty(modelName))tableConfiguration.setDomainObjectName(modelName);
+ if (StringUtils.isNotEmpty(modelName)) tableConfiguration.setDomainObjectName(modelName);
tableConfiguration.setGeneratedKey(new GeneratedKey("id", "Mysql", true, null));
context.addTableConfiguration(tableConfiguration);
diff --git a/src/test/java/com/conpany/project/Tester.java b/src/test/java/com/conpany/project/Tester.java
index ca247abae..9630090ba 100644
--- a/src/test/java/com/conpany/project/Tester.java
+++ b/src/test/java/com/conpany/project/Tester.java
@@ -1,7 +1,7 @@
package com.conpany.project;
-import com.company.project.Application;
+import com.company.project.AppStarter;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
@@ -12,7 +12,7 @@
* 单元测试继承该类即可
*/
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = Application.class)
+@SpringBootTest(classes = AppStarter.class)
@Transactional
@Rollback
public abstract class Tester {}
diff --git a/src/test/resources/demo-user.sql b/src/test/resources/demo-user.sql
index 6c16772ff..76d35e3f1 100644
--- a/src/test/resources/demo-user.sql
+++ b/src/test/resources/demo-user.sql
@@ -2,44 +2,37 @@
Navicat MySQL Data Transfer
Source Server : Localhost
-Source Server Version : 50713
+Source Server Version : 50721
Source Host : localhost:3306
Source Database : test
Target Server Type : MYSQL
-Target Server Version : 50713
+Target Server Version : 50721
File Encoding : 65001
-Date: 2017-06-23 14:25:27
+Date: 2019-04-10 15:53:02
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
--- Table structure for user
+-- Table structure for t_user_tester
-- ----------------------------
-DROP TABLE IF EXISTS `user`;
-CREATE TABLE `user` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `username` varchar(255) NOT NULL,
- `password` varchar(255) NOT NULL,
- `nick_name` varchar(255) DEFAULT NULL,
- `sex` int(1) DEFAULT NULL,
- `register_date` datetime NOT NULL,
+DROP TABLE IF EXISTS `t_user_tester`;
+CREATE TABLE `t_user_tester` (
+ `id` int(10) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) DEFAULT NULL,
+ `state` char(1) DEFAULT '1' COMMENT '0-关闭,1-正常',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `create_by` varchar(64) DEFAULT NULL,
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `update_by` varchar(64) DEFAULT NULL,
PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
--- Records of user
+-- Records of t_user_tester
-- ----------------------------
-INSERT INTO `user` VALUES ('1', '89921218@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('2', '2@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-2', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('3', '3@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-3', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('4', '4@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-4', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('5', '5@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-5', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('6', '6@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-6', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('7', '7@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-7', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('8', '8@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-8', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('9', '9@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-9', '1', '2017-06-23 14:24:23');
-INSERT INTO `user` VALUES ('10', '10@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-10', '1', '2017-06-23 14:24:23');
-SET FOREIGN_KEY_CHECKS=1;
+INSERT INTO `t_user_tester` VALUES ('1', 'jcouyang', '1', '2019-04-09 09:53:21', 'admin', null, null);
+INSERT INTO `t_user_tester` VALUES ('2', '123243', '1', '2019-04-09 09:56:15', 'jcouyang', null, null);
+INSERT INTO `t_user_tester` VALUES ('3', '123', '1', '2019-04-10 15:20:30', '中文测试', null, null);