首先感谢csdn大大的文章,blog.csdn.net/jrainbow/article/details/51980036,本文是在该博客基础下扩展。
1、Maven构建Spring Boot
1.1创建Maven 工程
使用spring-boot-starter-parent来构建Spring Boot项目是一个很好的方法,但很多项目本身就是依赖其它的父模块的,再或者spring-boot-starter-parent默认提供的那么多配置和功能我们用不到。引入spring-boot-starter-parent依赖及web依赖,编辑
pom.xml
4.0.0
com.ljy
springboot
0.0.1-SNAPSHOT
springboot
jar
org.springframework.boot
spring-boot-starter-parent
1.2.3.RELEASE
org.springframework.boot
spring-boot-starter-web
1.2 启动入口
update project后,建立如下结构,并创建启动文件 Application.java
Application.java
package com.ljy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
入口类Application带main方法,我们直接运行main方法就能启动Spring Boot项目了,这样极大程序地方便了我们调试程序和项目。
Application类说明自己是Spring Boot的入口类,那么需要加入@Configuration注解。
@EnableAutoConfiguration习惯放在主方法类Application上,当项目运行时,Spring容器去自动查找带特定注解的类,如:带@Entity、@Service等类。
@ComponentScan如果不带basePackage 属性的话,它会自动扫描以入口类所在的包为父节点下所有子包下的类。这也是Spring Boot会提议我们把Application类放于根包路径下。
如果我们的项目和Spring Boot建议的代码结构一样,Application类放在根包路径下。那么我们可以使用@SpringBootApplication来代替上。这里我们就用@SpringBootApplication。
最基础的springboot已经配置完毕。
1.3新建首页html
index.html
MyHtml.html
This is my HTML page2.
试下是不是配置成功了。运行启动文件Application.java,访问http://localhost:8080/,默认端口8080,首页默认index.jsp、index.html。结果成功访问首页
如果启动失败报错
java.lang.UnsupportedClassVersionError: javax/annotation/ManagedBean : Unsupported major.minor version 51.0
则需要指定jdk版本。
注意:默认配置的/**映射到/static(或/public ,/resources,/META-INF/resources)
当请求/index.html的时候,Spring MVC 会在/static/目录下面找到。
所以如果访问http://localhost:8080/static/index.html,那么上面配置的几个目录下面都没有/static目录,因此会找不到资源文件!
所以写静态资源位置的时候,不要带上映射的目录名(如/static/,/public/ ,/resources/,/META-INF/resources/)!
如果我按如下结构存放相同名称的图片,那么Spring Boot 读取图片的优先级是怎样的呢? 如下图:
当我们访问地址 http://localhost:8080/fengjing.jpg 的时候,显示哪张图片?这里博主可以直接告诉大家,优先级顺序为:META/resources > resources > static > public 如果我们想访问pic2.jpg,请求地址 http://localhost:8080/img/pic2.jpg
2.Spring Boot的Web项目实现
2.1 Application类支持Web应用
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
入口类Application继承SpringBootServletInitializer并重写configure方法。运行主方法后,会将我们的web项目打包成war,并默认启动tomcat容器来运行我们的Web项目。
2.2服务器端口更改
spring会从classpath下的/config目录或者classpath的根目录查找application.properties或application.yml。两种配置特点自行查询。这里选择yml。
application.yml
# Server settings
server:
port: 80
address: 127.0.0.1
# SPRING PROFILES
spring:
# HTTP ENCODING
http:
encoding.charset: UTF-8
encoding.enable: true
encoding.force: true
这里需要注意,yml配置文件是的值属性前面必须有一个空格,如果没有空格,Spring的解析器会忽略此配置项。
2.3Controller
Spring Boot应用中@RestController的Controller带有默认基于Jackson2的对象转JSON功能。如:
@RestController
public class MyController {
@RequestMapping("/thing")
public MyThing thing() {
return new MyThing();
}
}
如需跳转,
可以在application.yml设置前缀后缀
spring:
mvc:
view.prefix: /WEB-INF/jsp/
view.suffix: .jsp
跳转类如下:
@Controller
public class MyController {
@RequestMapping("/thing")
public String thing() {
return “test”;
}
}
2.4Spring Boot应用实现热部署
org.springframework
springloaded
当系统通过 mvn spring-boot:run启动或者 右键application debug 启动java文件时,系统会监视classes文件,当有classes文件被改动时,系统会重新加载类文件,不用重启启动服务。
注:使用application run(非debug模式下),热部署功能会失效。
2.5打包成jar/war插件
放在project子节点
org.springframework.boot
spring-boot-maven-plugin
这时已经可以打成独立的jar包运行。
3.Spring Boot集成MyBatis
3.1加入基础依赖
mybatis:
org.mybatis
mybatis
3.4.0
mybatis-spring-boot-starter:
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.1.1
mysql:
mysql
mysql-connector-java
3.2数据库配置
# SPRING PROFILES
spring:
# DATASOURCE
datasource:
driverClass: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springboot?useUnicode=true&characterEncoding=utf-8
username: root
password: test
3.3引入通用Mapper
引入依赖
tk.mybatis
mapper
3.3.7
配置通用Mapper
MyBatisMapperScannerConfig.java
package com.ljy.common.configure;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
@Configuration
public class MyBatisMapperScannerConfig {
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage("com.ljy.dao");//扫描该路径下的dao
Properties properties = new Properties();
properties.setProperty("mappers", "com.ljy.common.BaseDao");//通用dao
properties.setProperty("notEmpty", "false");
properties.setProperty("IDENTITY", "MYSQL");
mapperScannerConfigurer.setProperties(properties);
return mapperScannerConfigurer;
}
}
其实MyBatisMapperScannerConfig 是一个MyBatis扫描Mapper接口扫描。
MapperScannerConfigurer根据指定的创建接口或注解创建映射器。我们这里映射了com.ljy.dao包下的接口。
使用MapperScannerConfigurer,没有必要去指定SqlSessionFactory或SqlSessionTemplate,因为MapperScannerConfigurer将会创建MapperFactoryBean,之后自动装配。但是,如果你使用了一个以上的DataSource(因此,也是多个的SqlSessionFactory),那么自动装配可能会失效。这种情况下,你可以使用sqlSessionFactory或sqlSessionTemplate属性来设置正确的工厂/模板。
注意的是网络上有些文章中在MapperScannerConfigurer之前还配置了 MyBatisConfig,因为MapperScannerConfigurer会创建MapperFactoryBean,所以我的项目中没有再配置MyBatisConfig。经使用没有出现任何问题。
3.4通用Mapper的使用(Dao层)
BaseDao.java
package com.ljy.common;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
public interface BaseDao extends Mapper,MySqlMapper{
}
附上测试表sql
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`username` varchar(255) DEFAULT NULL,
`state` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'test', '1');
INSERT INTO `user` VALUES ('2', 'user', '2');
表实体类:
User.java
package com.ljy.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class User implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String username;
private Integer state;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
}
*Dao:
package com.ljy.dao;
import com.ljy.common.BaseDao;
import com.ljy.entity.User;
public interface UserDao extends BaseDao{
}
MyBatis的Dao与其它的ORM框架不一样的是,MyBatis的Dao其实就是Mapper,是一个接口,是通过MapperScannerConfigurer扫描后生成实现的,我们不需要再写Dao接口的实现。
3.5业务处理及事务(Service层)
*Service
package com.ljy.service;
public interface UserService {
}
*ServiceImpl
package com.ljy.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ljy.dao.UserDao;
import com.ljy.entity.User;
import com.ljy.service.UserService;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
public User getUser(int id) {
return userDao.selectByPrimaryKey(id);
}
}
Spring Boot集成MyBatis后,实现事物管理的方法很简单,只需要在业务方法前面加上@Transactional注解就可以了。
写个类看下成功没
Test.java
package com.ljy.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ljy.entity.User;
import com.ljy.service.UserService;
@RestController
public class Test {
@Autowired
private UserService userService;
@RequestMapping("/test")
public User test() {
return userService.getUser(1);
}
}
运行springboot后访问http://localhost/test,成功
4.集成PageHelper
4.1依赖包
com.github.pagehelper
pagehelper
4.1.0
4.2配置类
MybatisConf.java
package com.ljy.common.configure;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.github.pagehelper.PageHelper;
/*
* 注册MyBatis分页插件PageHelper
*/
@Configuration
public class MybatisConf {
@Bean
public PageHelper pageHelper() {
System.out.println("MyBatisConfiguration.pageHelper()");
PageHelper pageHelper = new PageHelper();
Properties p = new Properties();
p.setProperty("offsetAsPageNum", "true");
p.setProperty("rowBoundsWithCount", "true");
p.setProperty("reasonable", "true");
pageHelper.setProperties(p);
return pageHelper;
}
}
这时就可以使用PageHelp插件了,在controller中直接使用。
Test.java
package com.ljy.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ljy.dao.UserDao;
import com.ljy.entity.User;
import com.ljy.service.UserService;
@RestController
public class Test {
@Autowired
private UserService userService;
@RequestMapping("/test")
public PageInfo test() {
/*
* 第一个参数是第几页;第二个参数是每页显示条数。
*/
PageHelper.startPage(1,1);
List list=userService.getUsers();
PageInfo pageInfo=new PageInfo(list);
return pageInfo;
}
}
UserService .java
package com.ljy.service;
import java.util.List;
import com.ljy.entity.User;
public interface UserService {
public User getUser(int id);
public List getUsers();
}
UserServiceImpl.java
package com.ljy.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ljy.dao.UserDao;
import com.ljy.entity.User;
import com.ljy.service.UserService;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
public User getUser(int id) {
return userDao.selectByPrimaryKey(id);
}
@Override
public List getUsers() {
// TODO Auto-generated method stub
return userDao.selectAll();
}
}
4.3PageHelper实现原理
参考这篇文章http://blog.csdn.net/jaryle/article/details/52315565
原理:
pageHelper会使用ThreadLocal获取到同一线程中的变量信息,各个线程之间的Threadlocal不会相互干扰,也就是Thread1中的ThreadLocal1之后获取到Tread1中的变量的信息,不会获取到Thread2中的信息
所以在多线程环境下,各个Threadlocal之间相互隔离,可以实现,不同thread使用不同的数据源或不同的Thread中执行不同的SQL语句
所以,PageHelper利用这一点通过拦截器获取到同一线程中的预编译好的SQL语句之后将SQL语句包装成具有分页功能的SQL语句,并将其再次赋值给下一步操作,所以实际执行的SQL语句就是有了分页功能的SQL语句
5集成quartz
完全借鉴了文章http://www.jianshu.com/p/2f45eadca7f9,感谢作者。
5.1.依赖包引入
org.springframework
spring-context-support
org.springframework
spring-tx
org.quartz-scheduler
quartz
2.2.1
5.2.注册[pring-boot启动完成事件监听,用于启动job任务
SchedulerListener.java
package com.ljy.common.shcedule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Configuration
public class SchedulerListener implements ApplicationListener {
@Autowired
public MyScheduler myScheduler;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
myScheduler.scheduleJobs();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
return schedulerFactoryBean;
}
}
5.3、job参数设置
MyScheduler.java
package com.ljy.common.shcedule;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
@Component
public class MyScheduler {
@Autowired
SchedulerFactoryBean schedulerFactoryBean;
public void scheduleJobs() throws SchedulerException {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
startJob1(scheduler);
startJob2(scheduler);
}
private void startJob1(Scheduler scheduler) throws SchedulerException{
JobDetail jobDetail = JobBuilder.newJob(ScheduledJob.class) .withIdentity("job1", "group1").build();
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") .withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail,cronTrigger);
}
private void startJob2(Scheduler scheduler) throws SchedulerException{
JobDetail jobDetail = JobBuilder.newJob(ScheduledJob2.class) .withIdentity("job2", "group1").build();
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group1") .withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail,cronTrigger);
}
}
5.4.实现各个任务job
package com.ljy.common.shcedule;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class ScheduledJob implements Job{
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
// TODO Auto-generated method stub
System.out.println("1任务运行----------------------");
}
}
接下来就是见证奇迹的时刻
附上源码地址https://github.com/tianya1451/springboot