昨天搭建ssm框架时突然想到可以搭建springboot来完美解决配置复杂的问题,今天学习了一下springboot的搭建,在此记录一下搭建的过程和踩过的坑
这里给自己定一个该框架搭建完成的目标,如下
框架要求功能:
- 处理http/json 请求
- 日志记录
- 持久化
- 数据源,事务控制
- 定时任务
- 视图模版
搭建环境:
- 编译器:idea 2016.2.4
- Maven : maven3.0
- JDK: java7
- 系统: mac OS 10.10.4
- 数据库: mysql5.6
2017-03-29
搭建记录
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>1.4.0.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
@Controller
@EnableAutoConfiguration
public class TestBootController {
@RequestMapping("/")
@ResponseBody
String home() {
return "hello world";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(TestBootController.class, args);
}
}
此时的项目目录结构是这样的
//业务层接口
public interface TestInterFace {
public int testInterFace();
public User testUser();
}
//业务层接口实现
@Service
public class TestInterFaceImpl implements TestInterFace {
@Override public int testInterFace() {
return 0;
}
@Override public User testUser() {
return new User();
}
}
修改controller层代码
@Controller
@EnableAutoConfiguration
public class TestBootController {
@Autowired
private TestInterFace testInterFace;
@RequestMapping("/num")
@ResponseBody
int home() {
int i = testInterFace.testInterFace();
return i;
}
@RequestMapping("/get")
@ResponseBody User getUser() {
return testInterFace.testUser();
}
public static void main(String[] args) throws Exception {
SpringApplication.run(TestBootController.class, args);
}
}
启动后抛异常
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘testBootController’: Unsatisfied dependency expressed through field ‘testInterFace’: No qualifying bean of type [com.kx.springboot.service.TestInterFace] found for dependency [com.kx.springboot.service.TestInterFace]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.kx.springboot.service.TestInterFace] found for dependency [com.kx.springboot.service.TestInterFace]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
相信大家对这种异常非常常见,注入失败,这时候问题来了,按照传统的方式,对注入进行检查。service层已经加了@service的注解,怎么还是注入失败了呢,想查看配置文件,发现springboot没有配置文件,那么他是怎么扫描注解的呢?
百度了一下才知道,springboot默认按照包顺序注入,所以在创建controller时service还没有注入,springboot不需要传统的xml配置扫描包,只需要添加注解@ComponentScan(basePackages={“com.kx.springboot.service”}),代码如下
@Controller
@EnableAutoConfiguration
@ComponentScan(basePackages={"com.kx.springboot.service"})//添加的注解
public class TestBootController {
@Autowired
private TestInterFace testInterFace;
@RequestMapping("/num")
@ResponseBody
int home() {
int i = testInterFace.testInterFace();
return i;
}
@RequestMapping("/get")
@ResponseBody User getUser() {
return testInterFace.testUser();
}
public static void main(String[] args) throws Exception {
SpringApplication.run(TestBootController.class, args);
}
}
再次启动,成功,访问http://localhost:8088/get
{“username”:”username寇鑫123”,”password”:”password寇鑫123”}
增加 UserController
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private TestInterFace testInterFace;
@RequestMapping("/get")
@ResponseBody User getUser() {
return testInterFace.testUser();
}
}
修改原来 TestBootController
@Controller
@RequestMapping("test")
public class TestBootController {
@Autowired
private TestInterFace testInterFace;
@RequestMapping("/num")
@ResponseBody
int home() {
int i = testInterFace.testInterFace();
return i;
}
@RequestMapping("/get")
@ResponseBody User getUser() {
return testInterFace.testUser();
}
}
在包的最外层增加新的应用启动入口 —> Application
@EnableAutoConfiguration
@ComponentScan(basePackages={"com.kx.springboot"})
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
可以看到,应用启动入口配置了扫描所有包。此时整个项目的结构如图所示
http://localhost:8080/test/get
{“username”:”username寇鑫123”,”password”:”password寇鑫123”}
http://localhost:8080/user/get
{“username”:”username寇鑫123”,”password”:”password寇鑫123”}
到此,符合处理http/json 的web框架已经搭建ok了
============2017-3-30 =============
第一步处理http/json已经完成了,现在给我们的框架里加上日志记录的功能
要求:
- 日志按天记录,自动生成当天的记录文件
- 日志分级存储(info,error)
Springboot自带日志,所以我们现在直接在SpringBoot中添加日志
修改 TestController
@Controller
@RequestMapping("test")
public class TestBootController {
//增加日志
private final Logger log = LoggerFactory.getLogger(TestBootController.class);
@Autowired
private TestInterFace testInterFace;
@RequestMapping("/num")
@ResponseBody
int home() {
int i = testInterFace.testInterFace();
return i;
}
@RequestMapping("/get")
@ResponseBody User getUser() {
//打印日志
log.info("TestBootController getUser info");
return testInterFace.testUser();
}
}
只增加了两行代码,现在启动尝试打印日志
访问 http://localhost:8080/test/get
可以看到我们的日志已经打出来了,那么现在又有疑问了,这个日志只是打在控制台了,并没有生成文件,查询后发现默认日志如果要打印生成文件需要添加application.properties,而添加这个只可以打固定名称格式的日志,并不能灵活的配置,所以添加Springboot默认支持的logback作为标准日志输出
添加新的pom依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
dependency>
在resource下添加logback配置文件logback.xml
首先配置按天生成日志,尝试日志文件打印输出
<configuration debug="false">
<property name="LOG_HOME" value="/Users/kx/Desktop" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
encoder>
appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/TestSpringBoot.log.%d{yyyy-MM-dd}.logFileNamePattern>
<MaxHistory>30MaxHistory>
rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
encoder>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MBMaxFileSize>
triggeringPolicy>
appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
root>
configuration>
启动应用,尝试输出日志
访问 http://localhost:8080/test/get
好吧,首先发现我们的日志不是彩色的了,哭~,不过还好日志打出来了,那么看看我们的文件有没有生成
//生成文件
-rw-r--r-- 1 kx staff 5117 3 30 22:19 TestSpringBoot.log.2017-03-30.log
//info 日志打印效果
2017-03-30 22:21:03.341 [http-nio-8080-exec-3] INFO com.kx.springboot.controller.TestBootController - TestBootController getUser info
OK,文件也完美的按照我们指定的路径生成了,并且文件命名方式按照配置的日期命名,日志打印的内容也按照配置的内容正确的打印了,现在配置info日志和error日志,区分info和error打出来的日志文件
修改 logback.log 增加新的error appender 修改原来的appender 为 info
<configuration debug="false">
<property name="LOG_HOME" value="/Users/kx/Desktop" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
encoder>
appender>
<appender name="DAYINFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/TestSpringBoot_info.log.%d{yyyy-MM-dd}.logFileNamePattern>
<MaxHistory>30MaxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>errorlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
encoder>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MBMaxFileSize>
triggeringPolicy>
appender>
<appender name="DAYERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/TestSpringBoot_error.log.%d{yyyy-MM-dd}.logFileNamePattern>
<MaxHistory>30MaxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>errorlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
encoder>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MBMaxFileSize>
triggeringPolicy>
appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="DAYINFO" />
<appender-ref ref="DAYERROR" />
root>
configuration>
启动应用后发现已经新增了两个日志文件,命名完全按照配置
-rw-r--r-- 1 kx staff 0 3 30 22:19 TestSpringBoot_error.log.2017-03-30.log
-rw-r--r-- 1 kx staff 5117 3 30 22:19 TestSpringBoot_info.log.2017-03-30.log
访问 http://localhost:8080/test/get
//info 日志打印效果
2017-03-30 22:21:03.341 [http-nio-8080-exec-3] INFO com.kx.springboot.controller.TestBootController - TestBootController getUser info
//error 日志打印效果
2017-03-30 22:21:03.342 [http-nio-8080-exec-3] ERROR com.kx.springboot.controller.TestBootController - TestBootController getUser error
我们发现error日志和info日志已经按照我们的要求已经打印到对应的文件中了,那么现在我们想解决一下控制台彩色输出的模块,刚好百度到了这里的代码(珍藏)
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}pattern>
<charset>utf8charset>
encoder>
appender>
看一下我们现在的logback日志总文件
<configuration>
<property name="LOG_HOME" value="/Users/kx/Desktop" />
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}pattern>
<charset>utf8charset>
encoder>
appender>
<appender name="DAYINFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/TestSpringBoot_info.log.%d{yyyy-MM-dd}.logFileNamePattern>
<MaxHistory>30MaxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>infolevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
encoder>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MBMaxFileSize>
triggeringPolicy>
appender>
<appender name="DAYERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/TestSpringBoot_error.log.%d{yyyy-MM-dd}.logFileNamePattern>
<MaxHistory>30MaxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>errorlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
encoder>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MBMaxFileSize>
triggeringPolicy>
appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="DAYERROR" />
<appender-ref ref="DAYINFO" />
root>
configuration>
再次运行项目,访问 http://localhost:8080/test/get
哈哈哈,我们的彩色日志又回来了,而且结构清晰,调试代码的时候简直神器啊
2017-04-01
============整合Mybatis============
在众多orm框架中,我对mybatis最熟悉,所以我采用mybatis进行整合,对我们的orm框架,这里我们也提出几点要求
在查阅了一些资料后,找到目前为止最简单的一种整合mybatis方式,这里贴出原始博客地址
http://blog.didispace.com/springbootmybatis/
参照大神的整合,我们的整合异常的顺利,贴出我们增加的代码
在pom中添加以下依赖
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>1.1.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.21version>
dependency>
在application.properties 中增加以下配置
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
表结构
Create Table: CREATE TABLE `userinfo` (
`id` int(20) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
编写dao层代码,新建UserDao 接口
@Mapper
public interface UserDao {
@Select("SELECT * FROM USERINFO WHERE username = #{username}")
UserInfo findByName(@Param("username") String username);
@Insert("INSERT INTO USERINFO(username, password) VALUES(#{username}, #{password})")
int insert(@Param("username") String name, @Param("password") String password);
}
在业务层增加对dao层接口的引用,修改TestInterFace,TestInterFaceImpl
public interface TestInterFace {
public int testInterFace();
public UserInfo testUser();
public int insertUser(String username,String password);//新增的接口
}
@Service
public class TestInterFaceImpl implements TestInterFace {
//引入dao层接口
@Autowired UserDao userDao;
@Override public int testInterFace() {
return 0;
}
@Override public UserInfo testUser() {
return new UserInfo();
}
//新增的接口实现
@Override public int insertUser(String username,String password) {
return userDao.insert(username,password);
}
}
接下来修改我们的controller,提供对外的接口,修改UserController
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private TestInterFace testInterFace;
@RequestMapping("/get")
@ResponseBody UserInfo getUser() {
return testInterFace.testUser();
}
//增加新的对外访问接口
@RequestMapping("/add")
@ResponseBody String add() {
testInterFace.insertUser("username123寇鑫","password123寇鑫");
return "插入成功";
}
}
来测试一下我们的新接口,访问 http://localhost:8080/user/add
看到浏览器已经正常返回了,接下来去数据库看看数据有没有实际插入
+----+-------------------+-------------------+
| id | username | password |
+----+-------------------+-------------------+
| 1 | username123寇鑫 | password123寇鑫 |
+----+-------------------+-------------------+
可以看到,在我们的表中,已经插入了一条数据,并且中文显示正常。但现在每次新加一个接口,都要对应的写一条sql,这样很麻烦,而且不利于开发,业务方不能专注于业务的开发,所以我们要抽象出来通用的curd接口,并且支付分页。
2017-04-04
mybatis有很多成熟的分页插件以及通用接口插件,这里我们也采用目前较为成熟的方案,不必重复造轮子。
添加pom
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>4.2.1version>
dependency>
<dependency>
<groupId>tk.mybatisgroupId>
<artifactId>mapperartifactId>
<version>3.3.9version>
dependency>
因为springboot 不需要设置xml,所以这里都采用注解和代码的形式注入插件
新建配置类
package com.kx.springboot.dao.mybatis;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.util.Properties;
/**
* Created by kx on 17/4/2.
*/
public class MyBatisConfig {
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean() {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
// bean.setDataSource(dataSource());
bean.setTypeAliasesPackage("com.kx.springboot.bean");
//分页插件设置
PageHelper pageHelper = new PageHelper();
Properties properties = new Properties();
properties.setProperty("reasonable", "true");
properties.setProperty("supportMethodsArguments", "true");
properties.setProperty("returnPageInfo", "check");
properties.setProperty("params", "count=countSql");
pageHelper.setProperties(properties);
//添加分页插件
bean.setPlugins(new Interceptor[]{pageHelper});
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
//基于注解扫描Mapper,不需配置xml路径
//bean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
return bean.getObject();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
新建配置扫描类
package com.kx.springboot.dao.mybatis;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
import java.util.Properties;
/**
* Created by kx on 17/4/2.
*/
@Configuration
//必须在MyBatisConfig注册后再加载MapperScannerConfigurer,否则会报错
@AutoConfigureAfter(MyBatisConfig.class)
public class MyBatisMapperScannerConfig {
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage("com.kx.springboot.dao.mybatis");
//初始化扫描器的相关配置,这里我们要创建一个Mapper的父类
Properties properties = new Properties();
properties.setProperty("mappers", "com.kx.springboot.dao.baseDao.MyMapper");
properties.setProperty("notEmpty", "false");
properties.setProperty("IDENTITY", "MYSQL");
mapperScannerConfigurer.setProperties(properties);
return mapperScannerConfigurer;
}
}
新建对外暴露接口
package com.kx.springboot.dao.baseDao;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
/**
* Created by kx on 17/4/2.
*/
public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
//TODO
//FIXME 特别注意,该接口不能被扫描到,否则会出错
}
现在,修改我们的dao层实现类,继承我们的通用接口
@Mapper
public interface UserDao extends MyMapper<UserInfo> {
}
在业务层中增加想要调用的方法
public interface TestInterFace {
public int testInterFace();
public UserInfo testUser();
public int insertUser(UserInfo userInfo);
//新增加的方法
List selectALL();
}
@Service
public class TestInterFaceImpl implements TestInterFace {
@Autowired UserDao userDao;
@Override public int testInterFace() {
return 0;
}
@Override public UserInfo testUser() {
return new UserInfo();
}
@Override public int insertUser(UserInfo userInfo) {
return userDao.insert(userInfo);
}
//新增加的实现
@Override
public List selectALL(){
return userDao.selectAll();
}
}
看到我们在调用userDao时已经有了通用的单表查询方法。将新接口暴露给http,修改controller
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private TestInterFace testInterFace;
@RequestMapping("/get")
@ResponseBody UserInfo getUser() {
return testInterFace.testUser();
}
@RequestMapping("/add")
@ResponseBody String add() {
UserInfo user = new UserInfo();
user.setUsername("username123寇鑫");
user.setPassword("password123寇鑫");
testInterFace.insertUser(user);
return "插入成功";
}
//新增的接口方法
@RequestMapping("/getall")
@ResponseBody List getall() {
return testInterFace.selectALL();
}
}
访问http://localhost:8080/user/getall
程序抛出异常
### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'ssmtest.user_info' doesn't exist
### The error may exist in com/kx/springboot/dao/UserDao.java (best guess)
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT username,password FROM user_info
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'ssmtest.user_info' doesn't exist
; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'ssmtest.user_info' doesn't exist] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'ssmtest.user_info' doesn't exist
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
从异常可以看出来,我们的表和我们查询数据库的字段没有映射起来,查询资料后发现原因是通用插件的问题,默认的字段中有下划线,我们需要手动指定映射
修改userinfo类
package com.kx.springboot.bean;
import javax.persistence.Column;
import javax.persistence.Table;
/**
* Created by kx on 17/3/29.
*/
//增加注解声明表名
@Table(name = "userinfo")
public class UserInfo {
//增加注解声明字段名
@Column(name = "username")
private String username = "username寇鑫123";
@Column(name = "password")
private String password = "password寇鑫123";
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override public String toString() {
return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}';
}
}
再次启动访问 http://loclhost:8080/user/getall
[
{
"username":"user123寇鑫",
"password":"password123寇鑫"
},
{
"username":"username123寇鑫",
"password":"password123寇鑫"
}
]
得到如下结果,到此已经成功整合了通用mapper插件,现在加入定时任务测试
springboot 定时任务的启动和配置要简单很多,只需要增加一个注解即可
修改Application.java 启动类
@EnableAutoConfiguration
@ComponentScan(basePackages={"com.kx.springboot"})
@EnableScheduling//增加支持定时任务的注解
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
新建定时任务类
@Component
public class SchedulingTest {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Scheduled(cron = "0/5 * * * * ?") // 每5秒执行一次
public void scheduler() {
logger.info(">>>>>>>>>>>>> scheduled test... ");
}
}
启动测试
2017-04-05 00:19:00.002 INFO 6512 --- [pool-1-thread-1] c.kx.springboot.schedul.SchedulingTest : >>>>>>>>>>>>> scheduled test...
2017-04-05 00:19:05.000 INFO 6512 --- [pool-1-thread-1] c.kx.springboot.schedul.SchedulingTest : >>>>>>>>>>>>> scheduled test...
2017-04-05 00:19:10.000 INFO 6512 --- [pool-1-thread-1] c.kx.springboot.schedul.SchedulingTest : >>>>>>>>>>>>> scheduled test...
2017-04-05 00:19:15.000 INFO 6512 --- [pool-1-thread-1] c.kx.springboot.schedul.SchedulingTest : >>>>>>>>>>>>> scheduled test...
2017-04-05 00:19:20.001 INFO 6512 --- [pool-1-thread-1] c.kx.springboot.schedul.SchedulingTest : >>>>>>>>>>>>> scheduled test...
2017-04-05 00:19:25.002 INFO 6512 --- [pool-1-thread-1] c.kx.springboot.schedul.SchedulingTest : >>>>>>>>>>>>> scheduled test...
2017-04-05 00:19:30.003 INFO 6512 --- [pool-1-thread-1] c.kx.springboot.schedul.SchedulingTest : >>>>>>>>>>>>> scheduled test...
2017-04-05 00:19:35.003 INFO 6512 --- [pool-1-thread-1] c.kx.springboot.schedul.SchedulingTest : >>>>>>>>>>>>> scheduled test...
可以看到我们的定时任务执行结果没有问题,接下来要在框架中增加多数据源以及事务控制。