本例爲Spring Boot 簡單應用的基礎教程,IDE爲Eclipse,參考官方reference guide文檔。javascript
英文文檔地址:https://docs.spring.io/spring-boot/docs/current/reference/pdf/html
github上他人翻譯的中文文檔地址:https://github.com/qibaoguang/Spring-Boot-Reference-Guide前端
建議:預先在Eclipse Marketplace中安裝好Spring Tools,以便獲取提示等。java
填寫項目所需的必要信息。mysql
無需在新建項目時經過選項直接添加依賴,因此直接finish便可。jquery
Spring Boot 以 main函數啓動項目,在新建好項目後,會自動生成啓動類。git
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); } }
此時能夠選擇以下兩個任意選項啓動項目。github
一、配置Log4j2爲項目日誌系統,Spring Boot默認依賴的爲Logback,因此須要先去除spring-boot-starter中的Logback依賴。web
二、本例應用hibernate框架,因此配置了spring-boot-starter-data-jpa依賴,Spring Boot默認使用Hibernate 5.0.x,若是使用mybatis框架請另行查詢配置方法。ajax
三、本例使用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放置在src/main/resource路徑下,經過其配置項目。
一、配置項目啓動端口與項目contextPath經過server.x配置。
二、配置數據庫鏈接經過spring.datasource.x配置。
三、配置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
一、SpringBoot默認應用Logback日誌系統。能夠在application.properties中配置logging.x設置日誌配置。
二、本項目應用Log4j2做爲日誌系統。在pom.xml中的spring-boot-starter中去除Logback的依賴。
加入spring-boot-starter-log4j2依賴,將Log4j2配置文件命名爲log4j2.xml或log4j2-spring.xml放置在 src/main/resources下便可。
三、官方推薦命名爲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/**
包目錄結構請查閱最開始的包目錄結構預覽。
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; } }
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> { }
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 { }
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(); } }
package com.example.service; /** * @description 業務邏輯層示例接口 * @author yuanzi * @time 2017年12月21日 下午2:54:19 */ public interface ExampleService { /** * 存儲示例信息 * * @param name */ void save(String name); }
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); } }
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(); } }
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層進行簡單測試。
待完善。