本例为Spring Boot 简单应用的基础教程,IDE为Eclipse,参考官方reference guide文档。
英文文档地址:https://docs.spring.io/spring-boot/docs/current/reference/pdf/
github上他人翻译的中文文档地址:https://github.com/qibaoguang/Spring-Boot-Reference-Guide
建议:预先在Eclipse Marketplace中安装好Spring Tools,以便获取提示等。
项目包目录结构预览:
第一步:新建Spring Boot项目。
填写项目所需的必要信息。
无需在新建项目时通过选项直接添加依赖,所以直接finish即可。
第二步:启动程序
Spring Boot 以 main函数启动项目,在新建好项目后,会自动生成启动类。
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 此处将包含main函数的类放置于顶层 的com.example包中,{@code @SpringBootApplication}可以定义隐式的包搜索路径。
* {@code @Configuration},{@code @EnableAutoConfiguration}{@code @ComponentScan}
* 此处同时使用以上三个注解等同于{@code @SpringBootApplication}
* 将包含main函数的类放在顶层包中,{@code @EnableAutoConfiguration}可以隐式的定义基础的包搜索路径,以搜索注解实
* 体,则使用@{@code ComponentScan}就不需要指定basePackage属性了。
*
* @description SpringBoot启动类
* @author xinyuan.wei
* @time 2017年12月20日 下午3:59:19
*/
@SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
此时可以选择如下两个任意选项启动项目。
第三步:pom.xml配置
1、配置Log4j2为项目日志系统,Spring Boot默认依赖的为Logback,所以需要先去除spring-boot-starter中的Logback依赖。
2、本例应用hibernate框架,所以配置了spring-boot-starter-data-jpa依赖,Spring Boot默认使用Hibernate 5.0.x,如果使用mybatis框架请另行查询配置方法。
3、本例使用mysql数据库。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>SpringBootDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringBootDemo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<json-lib.version>2.4</json-lib.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<!-- 去除logback依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- spring mvc 配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jpa 配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 应用log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- json-lib -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>${json-lib.version}</version>
<classifier>jdk15</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
第三步:application.properties配置
application.properties放置在src/main/resource路径下,通过其配置项目。
1、配置项目启动端口与项目contextPath通过server.x配置。
2、配置数据库连接通过spring.datasource.x配置。
3、配置jpa通过spring.jpa.x配置。本例中应用hibernate4,配置hibernate的一些属性则使用spring.jpa.properties.x,在properties后面写上相关属性名即可。
#Server config
server.port=8081
server.context-path=/SpringBootDemo
#Datasource config
spring.datasource.url=jdbc:mysql://localhost/springboottest
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#JPA config
spring.jpa.database=MYSQL
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
第四步:log4j2.xml配置
1、SpringBoot默认应用Logback日志系统。可以在application.properties中配置logging.x设置日志配置。
2、本项目应用Log4j2作为日志系统。在pom.xml中的spring-boot-starter中去除Logback的依赖。
加入spring-boot-starter-log4j2依赖,将Log4j2配置文件命名为log4j2.xml或log4j2-spring.xml放置在 src/main/resources下即可。
3、官方推荐命名为log4j2-spring.xml,以便Spring可以完全控制日志初始化。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<!-- status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出 monitorInterval
: Log4j能够自动检测修改配置文件和重新配置本身, 设置间隔秒数。如:monitorInterval="600" -->
<Configuration status="WARN">
<Properties>
<!-- 日志路径 web.xml中需指定servlet3.0 ${web:rootDir}才可以获取到当前web项目的路径-->
<Property name="LOG_HOME">/home/logs</Property>
<!-- 日志名字 -->
<Property name="LOG_NAME">SpringBootDemo</Property>
</Properties>
<Appenders>
<!-- 将日志信息从控制台输出 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 控制台只输出level及以上级别的信息(onMatch-匹配ACCEPT接受),其他的直接拒绝(onMismatch-不匹配DENY拒绝) -->
<!-- <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/> -->
<!-- 输出日志的格式 -->
<PatternLayout
pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%logger{36}.%M,%L] - %msg%n" />
</Console>
<!-- 将日志信息写入日志文件 配置了RollingRandomAccessFile就不用配置此处了-待测试 -->
<!-- <File name="File" filename="${LOG_HOME}/${LOG_NAME}.log" append="true">
<PatternLayout pattern="%d %p %C{1.} [%t] %m%n" /> </File> -->
<!-- 分割日志 -->
<RollingRandomAccessFile name="RollingFile"
fileName="${LOG_HOME}/${LOG_NAME}" filePattern="${LOG_HOME}/${LOG_NAME}.%d{yyyy-MM-dd}.log">
<PatternLayout
pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%logger{36}.%M,%L] - %msg%n" />
<Policies>
<!-- 按天分割日志,interval以小时设置, modulate=true,则封存时间将以0点为边界进行偏移计算 -->
<TimeBasedTriggeringPolicy modulate="true"
interval="24" />
<!-- 按日志大小分割日志,可以与按时间分割共用,满足其中一个条件即分割 -->
<!-- <SizeBasedTriggeringPolicy size="200 MB" /> -->
</Policies>
<DefaultRolloverStrategy />
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<!-- 避免日志重复写入,将框架相关的包单独设置 additivity="false" 不设置会重复打印日志 -->
<logger name="org.springframework.core" level="info"
additivity="false"></logger>
<logger name="org.springframework.beans" level="info"
additivity="false"></logger>
<logger name="org.springframework.context" level="info"
additivity="false"></logger>
<logger name="org.springframework.web" level="info" additivity="false"></logger>
<logger name="org.springframework.webmvc" level="info" additivity="false"></logger>
<logger name="org.springframework.test" level="info" additivity="false"></logger>
<logger name="org.springframework.amqp" level="info" additivity="false"></logger>
<!-- Root level 是设置全局的信息显示级别,这里设置为error表示:error及以上的信息将被输出 信息的级别大小为: debug
< info < warn < error < fatal -->
<Root level="info">
<!-- 仅有上述的Appenders配置还不够,这里还不能少,少了就不会在控制台输出 -->
<AppenderRef ref="Console" />
<!-- 仅有上述的Appenders配置还不够,这里还不能少,少了就不会写入文件,但会创建文件 -->
<!-- <AppenderRef ref="File" /> -->
<AppenderRef ref="RollingFile" />
</Root>
<!-- 可以专门为某个类指定信息级别,例如为main包下的Main类指定信息级别为trace -->
<!-- <Logger name="main.Main" level="trace" /> -->
</Loggers>
</Configuration>
第五步:静态资源与视图的配置
SpringBoot默认了静态资源存放位置,定义了存放在下列目录下的资源可以触发实时加载:
/META-INF/maven
/META-INF/resources
/resources
/static
/public
/templates
可以通过 spring.resources.staticLocations 属性自定义静态资源存放的位置。
SpringBoot可以静态资源路径下的index.html作为应用主页。
本例应用了默认的路径配置,将index.html页面放在了/static目录下,系统可以自动识别其为应用主页,因此未对视图做相应配置。
对视图的自定义配置可以参考如下:
spring.mvc.view.prefix=classpath:/templates/
spring.mvc.view.suffix=.html
spring.mvc.static-path-pattern=/static/**
第六步:代码示例
包目录结构请查阅最开始的包目录结构预览。
Hibernate的SessionFactory配置
package com.example.config;
import org.hibernate.SessionFactory;
import org.hibernate.jpa.HibernateEntityManagerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* SpringBoot应该是不会自动配置Hibernate的SessionFactory的,它会自动创建一个JPA的{@code EntityManagerFactory}。
* 使用Hibernate的SessionFactory首先需在application.properties中配置好current_session_context_class
*
* @description Hibernate SessionFactory配置类
* @author yuanzi
* @time 2017年12月21日 上午11:14:08
*/
@Configuration
public class SessionFactoryConfig {
@Bean
public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf){
return hemf.getSessionFactory();
}
}
实体类
在数据库中建立一个example表,表中只有主键id字段和name字段。
然后建立对应实体类。
package com.example.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @description 测试实体类
* @author yuanzi
* @time 2017年12月21日 上午10:25:36
*/
@Entity
@Table(name = "example")
public class ExampleEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name", nullable = false)
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Dao层
Dao层接口
package com.example.dao;
import java.util.Collection;
import java.util.List;
/**
* 接口方法默认public修饰,其属性默认为static final修饰,保持代码简洁,接口方法不再显式声明public。
*
* @description 数据层基础接口
* @author yuanzi
* @time 2017年12月21日 上午10:31:27
*/
public interface BaseDao<T> {
/**
* 通用存储方法
*
* @param object
*/
void save(T object);
/**
* 通用批量存储方法
*
* @param object
*/
void batchSave(Collection<T> object);
/**
* 通用更新方法
*
* @param object
*/
void update(T object);
/**
* 通用删除方法
*
* @param object
*/
void delete(T object);
/**
* 通用查询所有数据方法
*
* @return List<T>
*/
List<T> getAll();
}
package com.example.dao;
import com.example.entity.ExampleEntity;
/**
* @description 数据层示例接口
* @author yuanzi
* @time 2017年12月21日 下午3:05:37
*/
public interface ExampleDao extends BaseDao<ExampleEntity> {
}
Dao层实现
package com.example.dao.impl;
import java.util.Collection;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.example.dao.BaseDao;
/**
* 设置 rollbackFor = Exception.class,对抛出异常的事务进行回滚。
*
* @description 数据层基础实现
* @author xinyuan.wei
* @time 2017年12月21日 下午2:43:29
*/
@Transactional(rollbackFor = Exception.class)
public class BaseDaoImpl<T> implements BaseDao<T> {
@Autowired
public SessionFactory sessionFactory;
@Override
public void save(T object) {
Session session = sessionFactory.getCurrentSession();
session.save(object);
}
@Override
public void batchSave(Collection<T> object) {
// TODO Auto-generated method stub
}
@Override
public void update(T object) {
// TODO Auto-generated method stub
}
@Override
public void delete(T object) {
// TODO Auto-generated method stub
}
@Override
public List<T> getAll() {
// TODO Auto-generated method stub
return null;
}
}
package com.example.dao.impl;
import com.example.dao.ExampleDao;
import com.example.entity.ExampleEntity;
/**
* @description 数据层示例实现类
* @author xinyuan.wei
* @time 2017年12月21日 下午3:08:14
*/
public class ExampleDaoImpl extends BaseDaoImpl<ExampleEntity> implements ExampleDao {
}
Dao层配置类(可在实现类上直接使用@Repository注解替代)
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.dao.ExampleDao;
import com.example.dao.impl.ExampleDaoImpl;
/**
* @description 数据层配置类
* @author yuanzi
* @time 2017年12月21日 下午3:00:12
*/
@Configuration
public class DaoConfig {
@Bean
public ExampleDao getExampleDao() {
return new ExampleDaoImpl();
}
}
service层
service接口类
package com.example.service;
/**
* @description 业务逻辑层示例接口
* @author yuanzi
* @time 2017年12月21日 下午2:54:19
*/
public interface ExampleService {
/**
* 存储示例信息
*
* @param name
*/
void save(String name);
}
service实现类
package com.example.service.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.example.dao.ExampleDao;
import com.example.entity.ExampleEntity;
import com.example.service.ExampleService;
/**
* @description 业务逻辑层示例实现类
* @author xinyuan.wei
* @time 2017年12月21日 下午3:10:13
*/
public class ExampleServiceImpl implements ExampleService {
private static final Logger LOG = LoggerFactory.getLogger(ExampleServiceImpl.class);
@Autowired
public ExampleDao exampleDao;
@Override
public void save(String name) {
ExampleEntity exampleEntity = new ExampleEntity();
exampleEntity.setName(name);
exampleDao.save(exampleEntity);
LOG.info("存储{}成功", name);
}
}
service配置类(可在实现类上直接使用@Service注解替代)
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.service.ExampleService;
import com.example.service.impl.ExampleServiceImpl;
/**
* @description 业务层配置类
* @author yuanzi
* @time 2017年12月21日 下午3:00:41
*/
@Configuration
public class ServiceConfig {
@Bean
public ExampleService getExmapleService() {
return new ExampleServiceImpl();
}
}
controller层
package com.example.web.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.service.ExampleService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
* @description 示例controller
* @author yuanzi
* @time 2017年12月20日 下午4:06:19
*/
@RestController
@RequestMapping(value = "/example")
public class ExampleController {
private static final Logger LOG = LoggerFactory.getLogger(ExampleController.class);
@Autowired
private ExampleService exampleService;
@RequestMapping(value = "/example", method = RequestMethod.POST)
public JSONObject example(@RequestParam(name = "name") String name) {
JSONObject data = new JSONObject();
JSONObject result = new JSONObject();
JSONObject object = new JSONObject();
JSONArray array = new JSONArray();
try {
exampleService.save(name);
result.put("code", 0);
result.put("info", "");
result.put("developInfo", "");
LOG.error("提交{}成功", name);
} catch (Exception e) {
result.put("code", 1);
result.put("info", "提交失败");
result.put("developInfo", e.fillInStackTrace().toString());
LOG.error("提交失败:", e.fillInStackTrace());
}
data.put("result", result);
data.put("object", object);
data.put("array", array);
return data;
}
}
建立完controller后,此时可以通过postman测试工具进行测试或者使用Mock对接口(controller层)进行单元测试。
第七步:前端示例
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1" />
<meta http-equiv="X-UA-Compatible" content="IE=9" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>主页示例</title>
</head>
<body>
<div>
<input placeholder="名称" id="name" name="name" type="text" value="">
<input type="button" id="btn" name="btn" value="提交" onclick="exampleFun();">
</div>
</body>
<!-- jQuery -->
<script src="javascript/dependence/jquery.min.js"></script>
<script src="javascript/index_example.js"></script>
</html>
index_example.js
/**
* JavaScript示例
*/
function exampleFun() {
var name = $("#name").val();
$.ajax({
url : "example/example",
data : {
name : name
},
type : "POST",
dataType : "json",
success : function(data) {
if (data.result.code == 0) {
alert("存储成功!");
} else {
alert('存储失败!');
}
},
error : function(data) {
alert('系统错误(INDEXSYS001),请联系系统管理员');
}
});
}
建立完前端页面,此时也可以对controller层进行简单测试。
第八步:单元测试
待完善。