前言:學習SpringBoot不應該直接就是開始使用SpringBoot,如果直接拿來用肯定會有很多人不是很明白特别剛開始入門的,當然官網上也有快速上手的教程但是官網上跨度有點大,在這片文章中為主要是從以前沒使用SpringBoot之前我們怎麼做的以及慢慢的引入SpringBoot,我希望通過自己的體會和認識來幫助更多朋友來學習SpringBoot
目錄結構
- SpringJavaConfig
- @Configuration和基礎的@Bean
- @ComponentScan和測試
- @Bean标簽屬性詳解
- @Import标簽
- XML和Annotation的混用
- 其他常用标簽(@PropertySource和@PropertySources,@Profile和@ActiveProfile)
- 第一個HelloWorld
- Springboot簡介
- Springboot基本使用
- 應用建構
- SpringApplication
- 參數配置
- 日志
- 預設日志
- 外部日志架構LogBack
- Springboot開發WEB應用
- 靜态資源
- Freemarker內建
- 錯誤處理
- mybatis內建
- 事務處理
- 檔案上傳
首先了解 Spring Java Config(Spring的java配置)
(在這裡我們先以最原始的方式來建立項目和測試)
建立一個Maven項目添加依賴和加入配置檔案
application.xml
SomeBean.java
public class SomeBean {}
application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="someBean" class="com.jd.javaconfig.SomeBean"></bean>
</beans>
這個是基于XML配置的方式
MyTest.java
public class MyTest {
@Test
public void test1(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("application.xml");
SomeBean sb = ctx.getBean(SomeBean.class);
System.out.println(sb);
}
上面是我們最簡單的一個Spring Demo
下面通過标簽來配置Spring
OtherBean.java
public class OtherBean {}
下面我們寫了一個方法傳回一個SomeBean的對象我們要告訴Spring這個方法是Spring幫我們管理的bean通過@Bean标簽
AppConfig .java
// 作為Spring的主配置檔案
//@Configuration标簽表示這個類可被Spring識别的配置對象的類,隻有有這個标記的标簽的類才能使用@Bean标簽作用于對應的方法上面
@Configuration
public class AppConfig {
//@Bean标簽表示讓Spring幫我們管理bean
@Bean
public SomeBean someBean(){
return new SomeBean();
}
@Bean
public OtherBean otherBean(){
return new OtherBean();
}
}
不像上一個demo,這個是基于AnnotationConfigApplicationContext來配置的
MyTest.java
@Test
public void test() {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
SomeBean sb = ctx.getBean(SomeBean.class);
OtherBean ob = ctx.getBean(OtherBean.class);
System.out.println(sb);
System.out.println(ob);
}
到這裡我們就已經學完了兩個重要的标簽 @Configuration和@Bean,
@Configuration标簽表示這個類可被Spring識别的配置對象的類,隻有有這個标記的标簽的類才能使用
@Bean标簽作用于對應的方法上面
@Bean(destroyMethod = "destory", initMethod = "init")也可以通過這樣的寫法來配置bean的初始化方法和銷毀方法
@Component标簽
@Component
public class SomeBean {}
@Component
public class OtherBean {}
//@Configuration标簽表示這個類可被Spring識别的配置對象的類,這有有這個标記的标簽的類才能使用@Bean标簽作用于對應的方法上面
// @ComponentScan:開啟元件自動掃描;預設情況下,它會掃描目前類所在的包及其子包中的所有标簽對象加載到Spring容器
@Configuration
@ComponentScan(basePackages="com.jd.scan")
public class AppConfig {}
public class MyTest {
@Test
public void test() {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
SomeBean sb = ctx.getBean(SomeBean.class);
OtherBean ob = ctx.getBean(OtherBean.class);
System.out.println(sb);
System.out.println(ob);
}
}
@ComponentScan:開啟元件自動掃描;預設情況下,它會掃描目前類所在的包及其子包中的所有标簽對象加載到Spring容器
對象的關系引用
在someBean裡依賴一個otherBean
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class MyTest {
@Autowired
@Qualifier("somebean")
private SomeBean somebean;
//@Autowired
//@Qualifier("somebean2")
//private SomeBean somebean2;
@Test
public void test() {
System.out.println(somebean.getOtherBean());
//System.out.println(somebean2.getOtherBean());
}
}
@Configuration
public class AppConfig {
//第一種方式(對象的注入)
@Bean(destroyMethod = "destory", initMethod = "init")
public SomeBean somebean(OtherBean otherbean) {
SomeBean sBean = new SomeBean();
sBean.setOtherBean(otherbean);
return sBean;
}
//第二種方式
// @Bean
// public SomeBean somebean2() {
// SomeBean sBean = new SomeBean();
// sBean.setOtherBean(otherbean());
// return sBean;
// }
@Bean
public OtherBean otherbean() {
return new OtherBean();
}
}
使用try來關閉容器
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=AppConfig.class)
public class MyTest2 {
@Test
public void test() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class)) {
SomeBean sb = context.getBean(SomeBean.class, "somebean");
System.out.println(sb);
}
}
}
@import标簽
public class MyDataSource {}
public class MyRedisTemplate {}
@Configuration
public class ConfigRedis {
@Bean
public MyRedisTemplate myRedisTemplate(){
return new MyRedisTemplate();
}
}
@Configuration
public class ConfigDataSource {
@Bean
public MyDataSource myDatasource(){
return new MyDataSource();
}
}
AppConfig這個類因為打上@Configuration标簽是以是主配置檔案,他需要連接配接着兩個類ConfigDataSource.class,ConfigRedis.class 隻需要使用@Import 标簽就可以表示導入類
@Configuration
@Import({ConfigDataSource.class,ConfigRedis.class})
public class AppConfig {
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class MyTest {
@Autowired
private MyDataSource datasource;
@Autowired
private MyRedisTemplate redisTemplate;
@Test
public void test(){
System.out.println(datasource);
System.out.println(redisTemplate);
}
}
@importresource标簽 在javaconfig中混用xml
OtherBean.java
public class OtherBean {}
application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="otherbean" class="com.jd.importresource.OtherBean" />
</beans>
SomeBean.java
@Setter@Getter
public class SomeBean {
private OtherBean otherBean;
public void init() {
System.out.println("===init====");
}
public void destory() {
System.out.println("====destory=====");
}
}
AppConfig.java
@Configuration
// @importresource标簽來在javaconfig中混用xml config
@ImportResource("classpath:com/jd/importresource/application.xml")
public class AppConfig {
@Bean(destroyMethod = "destory", initMethod = "init")
public SomeBean somebean(OtherBean otherbean) {
SomeBean sBean = new SomeBean();
sBean.setOtherBean(otherbean);
return sBean;
}
}
MyTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class MyTest {
@Autowired
private SomeBean somebean;
@Test
public void test() {
System.out.println(somebean.getOtherBean());
}
}
@ImportResource(" classpath:com/jd/importresource/application.xml ") 通過使用@ImportResource标簽來導入資源
引入外部的.properties資源檔案(2種方式)
db.properties
db.username=username
db.password=password
db.url=url
db.driverClass=driverClass
MyDatasource .java
@Setter@Getter@ToString@AllArgsConstructor
public class MyDatasource {
private String username;
private String password;
private String url;
private String driverClass;
}
第一種方式
AppConfig .java
@Configuration
// @PropertySource代表引入外部的.properties資源檔案
//@PropertySources嵌套@PropertySource引入多個外部資源檔案
@PropertySource("classpath:com/jd/properties/db.properties")
public class AppConfig {
@Value("${db.username}")
private String username;
@Value("${db.password}")
private String password;
@Value("${db.url}")
private String url;
@Value("${db.driverClass}")
private String driverClass;
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer (){
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public MyDatasource datasource(){
return new MyDatasource(username, password, url, driverClass);
}
}
MyTest .java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class MyTest {
@Autowired
private MyDatasource datasource;
@Test
public void test() {
System.out.println(datasource);
}
}
第二種方式
@Configuration
// @PropertySource代表引入外部的.properties資源檔案
//@PropertySources嵌套@PropertySource引入多個外部資源檔案
@PropertySource("classpath:com/jd/properties/db.properties")
public class AppConfig {
//Environment代表spring的環境,在環境裡面隻有兩種東西: 1,讀入的外部資源檔案(properties); 2,profile
@Autowired
private Environment env;
@Bean
public MyDatasource datasource() {
return new MyDatasource(env.getProperty("db.username"), env.getProperty("db.password"),
env.getProperty("db.url"), env.getProperty("db.driverClass"));
}
}
profile
db-dev.properties
db-profile.properties
db.username=username
db.password=password
db.url=url
db.driverClass=driverClass
MyDatasource.java
@Setter@Getter@ToString@AllArgsConstructor
public class MyDatasource {
private String username;
private String password;
private String url;
private String driverClass;
}
//生産環境的配置對象
@Configuration
@Profile("pro")
@PropertySource("classpath:com/jd/profile/db-pro.properties")
public class ConfigPro {
@Value("${db.username}")
private String username;
@Value("${db.password}")
private String password;
@Value("${db.url}")
private String url;
@Value("${db.driverClass}")
private String driverClass;
@Bean
public MyDatasource datasource() {
return new MyDatasource(username, password, url, driverClass);
}
}
//針對開發環境的配置
@Configuration
@Profile("dev")
@PropertySource("classpath:com/jd/profile/db-dev.properties")
public class ConfigDev {
@Value("${db.username}")
private String username;
@Value("${db.password}")
private String password;
@Value("${db.url}")
private String url;
@Value("${db.driverClass}")
private String driverClass;
@Bean
public MyDatasource datasource() {
return new MyDatasource(username, password, url, driverClass);
}
}
AppConfig .java
@Configuration
@Import({ ConfigDev.class, ConfigPro.class })
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
MyTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
@ActiveProfiles("dev")
public class MyTest {
@Autowired
private MyDatasource datasource;
@Test
public void test() {
System.out.println(datasource);
}
}
到這裡我們把需要回顧和拓展的知識都有一定加深下面我們開始正式學習SpringBoot
SpringBoot的HelloWorld
先示範在位址欄通路loclhost:8080/hello傳回字元串hello world
1.在pom.xml檔案中加入依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2.建立一個Controller:
HelloSpringBoot.java
@SpringBootApplication
@Controller
public class HelloSpringBoot {
@RequestMapping("hello")
@ResponseBody
public String hello() {
return "hello world";
}
public static void main(String[] args) {
SpringApplication.run(HelloSpringBoot.class, args);
}
}
Snip20170910_30.png
3.運作 main方法
. ____ _ __ _ _
/\ / ' __ _ () __ __ _ \ \ \
( ( )__ | '_ | '| | ' / ` | \ \ \
\/ )| |)| | | | | || (| | ) ) ) )
' |____| .|| ||| |_, | / / / /
=========||==============|/=////
:: Spring Boot :: (v1.5.6.RELEASE)
分析:
1,繼承spring-boot-starter-parent,引入基本的依賴管理配置;
2,引入spring-boot-starter-web,自動引入了springweb相關的包;
3,@SpringBootApplication:這個注解告訴springboot自動的去完成相關配置,包括基礎類的加載,bean的掃描等等,這個後面詳細介紹;簡單了解為這個标簽為我們的應用配置完成了很多基本功能;
4,SpringApplication.run:這個是springboot為我們提供的最大的差別,在于springboot不再是一個web應用,需要我們自己去打包,部署,啟動tomcat,springboot預設把tomcat打包到應用中,我們可以以正常的運作jar的方式來運作springboot應用;
應用獨立運作:
1,pom檔案中添加:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2,使用package指令打包,在指令行中使用java -jar xx.jar運作;注意,一定要引入spring-boot-maven-plugin之後運作package打包才能正常運作;
3,直接使用maven插件:spring-boot:run運作;
Springboot的優缺點
1. 建立獨立的Spring應用程式
2. 嵌入的Tomcat,無需部署WAR檔案
3. 簡化Maven配置
4. 自動配置Spring
5. 提供生産就緒型功能,如日志,健康檢查和外部配置
6. XML沒有要求配置
7. 非常容易和第三方架構內建起來;
缺點:
1,版本更新較快,可能出現較大變化;
2,因為約定大于配置,是以經常會出現一些很難解決的問題;
1,Springboot應用的基本結構:通過start.spring.io(網址)建立一個springboot應用:
2,spring-boot-starter-parent簡介:
1,包含了常用版本屬性;
要修改java編譯版本,可以修改: <properties> <java.version>1.7</java.version> </properties>
2,包含了常用的dependenceManagement;
3,Springboot非常優秀的地方在于提供了非常多以spring-boot-starter-開頭的開箱即用的工具包,常見工具包有以下一些:
spring-boot-starter:核心的工具包,提供了自動配置的支援,日志和YAML配置支援;
spring-boot-starter-activemq:針對快速內建ActiveMQ的工具包;
spring-boot-starter-aop:提供了快速內建SpringAOP和AspectJ的工具包;
spring-boot-starter-data-redis:提供了快速內建Redis和Jedis的工具包;
spring-boot-starter-freemarker:提供了快速內建Freemarker的工具包;
spring-boot-starter-mail:提供了快速內建郵件發送的工具包;
spring-boot-starter-test:提供了對Springboot應用的測試工具包;
spring-boot-starter-web:提供了對web開發的工具包,包括基于SpringMVC的RESTful應用開發,内置的tomcat伺服器等;
spring-boot-starter-actuator:提供了對生産環境中應用監控的工具包;
spring-boot-starter-logging:提供了對日志的工具包,預設使用Logback;
3,Springboot應用的熱部署:
除了使用JRebel來實作熱部署,還可以使用Springboot提供的spring-boot-devtools包來完成Springboot應用熱部署;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
1)原理:
SpringBoot重新開機是reload重新開機,通過監控classpath的變化,如果classpath中的檔案發生變化,即觸發重新開機。springboot通過兩個classpath來完成reload,一個basic classloader中加載不變的類,一個restart classloader中加載classpath中的類,重新開機的時候,restart classloader中的類丢棄并重新加載;
2)排除資源:
spring.devtools.restart.exclude=static/,templates/*
spring.devtools.restart.additional-exclude=public/** (處理預設配置排除之外的)
spring.devtools.restart.enabled=false (禁用自動重新開機)
@SpringBootApplication簡介:
@SpringBootApplication由三個主要的标簽構成:@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan
1)@SpringBootConfiguration:本質就是一個@Configuration,代表這是spring容器的主配置類;
2)@EnableAutoConfiguration:開啟自動配置,Springboot使用這個标簽自動的把内置的符合條件的@Configuration類加載進入應用;
可以檢視spring-boot-autoconfigure包中的META-INF/spring.factories檔案中的配置項(原理,由@EnableAutoConfiguration标簽引入的AutoConfigurationImportSelector類中,使用Spring的SpringFactoriesLoader類實作加載)
3)@ComponentScan:自動掃描;
SpringApplication簡介:
1,SpringApplication類提供了一個标準化的應用執行流程,并在這個執行流程中為我們提供了一些應用擴充點;但大部分情況下,我們隻需要使用它就可以了;
2,SpringBoot提供了一些擴充點,比如修改Banner:
1)建立一個banner.txt
2)設定banner,在配置檔案中使用spring.main.banner-mode=off
3,可以通過建立對象的方式來運作SpringApplication
2)通過builder完成:
4,參數的處理:在應用啟動過程中,可以通過啟動參數給應用傳遞一些額外的參數來控制應用的運作;
1,在main方法中可以直接使用傳入的參數;
2,可以任何類中直接通過@Autowired注入一個ApplicationArguments對象;
Springboot中的日志
為什麼要用日志?
1.比起System.out.println,日志架構可以把日志的輸出和代碼分離;
2.日志架構可以友善的定義日志的輸出環境,控制台,檔案,資料庫;
3.日志架構可以友善的定義日志的輸出格式和輸出級别;
Springboot的預設日志使用:
1.Springboot預設已經開啟日志;預設的日志格式為:時間 日志級别 PID 線程名稱 日志類 日志說明
2.Springboot的日志差別系統日志和應用日志;
3.Springboot推薦使用Logback作為日志架構(common-logging,java-logging,log4j,logback,slf4j)
Logback使用方法(推薦使用logback自己的配置檔案)
1.springboot預設支援logback.xml或者logback-spring.xml,推薦使用logback-spring.xml,springboot會增加額外功能;
2.可以通過logging.config=classpath:mylogback.xml指定自己的logback配置檔案(不推薦);
3.一個典型的logback配置檔案:
Logback使用介紹:
1,<configuration>:Logback配置根元素
屬性包括:
1,scan: 當此屬性設定為true時,配置檔案如果發生改變,将會被重新加載,預設值為true。
2,scanPeriod: 設定監測配置檔案是否有修改的時間間隔,如果沒有給出時間機關,預設機關是毫秒。當scan為true時,此屬性生效。預設的時間間隔為1分鐘。
3,debug: 當此屬性設定為true時,将列印出logback内部日志資訊,實時檢視logback運作狀态。預設值為false。
子元素:
<contextName>:上下文名字;
<property>:定義屬性,可以使用${}在配置檔案中使用;
2,<appender>:在logback中是用于具體記錄日志的元件,可以用來配置日志記錄方式,日志記錄格式等;
name:appender的名字,用于下面在配置日志的時候指定;
class:使用到的appender類;
常見的appender:
1,ch.qos.logback.core.ConsoleAppender:輸出到控制台;
2,ch.qos.logback.core.FileAppender:輸出到檔案;
3,ch.qos.logback.core.rolling.RollingFileAppender:輸出到檔案,可以配置滾動政策,當日志達到某個條件之後分檔案記錄;
4,還有其他的appender,比如寫到資料庫等;
<appender>元素的基本格式:
<appender name="" class="">
<encoder>
<pattern>...</pattern>
</encoder>
<otherconfig></otherconfig>
</appender>
<encoder>元素用來規定日志的輸出格式,所有表達式都以%開始表示接下來是一個特殊辨別符
常見辨別符:
1,%logger{n}:輸出Logger對象類名,n代表長度;
2,%class{n}:輸出所在類名,
3,d{pattern}或者date{pattern}:輸出日志日期,格式同java;
4,L/line:日志所在行号;
5,m/msg:日志内容;
6,method:所在方法名稱;
7,p/level:日志級别;
8,thread:所線上程名稱;
常見的appender使用:
1)ConsoleAppender輸出到控制台,子元素:
<encoder>:日志格式化
<target>:System.out(預設)或者System.err
圖檔.png
2)FileAppender輸出到檔案,子元素:
file:被寫入的檔案名,可以是相對目錄,也可以是絕對目錄,如果上級目錄不存在會自動建立,沒有預設值。
append:檔案結尾,如果是 false,清空現存檔案,預設是true。
encoder:對日志進行格式化
3)RollingFileAppender輸出到檔案,可以設定檔案滾動(分割)條件,子元素:
append:如果是 true,日志被追加到檔案結尾,如果是 false,清空現存檔案,預設是true。
rollingPolicy:滾動政策,涉及檔案移動和重命名。
常用滾動政策:
ch.qos.logback.core.rolling.TimeBasedRollingPolicy:按照時間控制來控制記錄檔案;
fileNamePattern:檔案名稱格式,以%d{pattern};
maxHistory:
可選節點,控制保留的歸檔檔案的最大數量,超出數量就删除舊檔案。(以檔案最小時間為準)
SizeAndTimeBasedRollingPolicy:按照時間和大小控制記錄檔案;
fileNamePattern:檔案名稱格式,可以使用%i來控制索引編号;
maxFileSize:這是活動檔案的大小,預設值是10MB
下面我們來通過一個小Demo來說明
application.properties
db.username=username
db.password=password
db.url=url
springboot.randomlong=${random.long[1,100]}
MyDatasource.java
@Setter@Getter
public class MyDatasource {
private String username;
private String password;
private String url;
}
HelloController.java
@Controller
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@Autowired
private MyDatasource datasource;
@RequestMapping("hello")
@ResponseBody
public String hello() {
//error<warn<info<debug<trace
logger.info("轉出成功");
if (logger.isDebugEnabled()) {
logger.debug("準備轉出10000");
}
if (logger.isTraceEnabled()) {
logger.trace("連接配接資料庫");
logger.trace("查詢賬戶餘額為12000");
}
if (logger.isDebugEnabled()) {
logger.debug("檢查轉出賬戶...");
logger.debug("轉出檢查成功");
logger.debug("執行轉出10000");
logger.debug("轉出成功");
}
logger.info("轉入成功");
System.out.println(datasource);
return "hello world";
}
}
App.java
@SpringBootApplication
public class App {
@Bean
@ConfigurationProperties(prefix = "db")
public MyDatasource datasource() {
return new MyDatasource();
}
public static void main(String[] args) {
new SpringApplicationBuilder(App.class).bannerMode(Mode.OFF).build().run(args);
}
}
logback日志的xml配置檔案
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
<target>System.out</target>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
<file>springbootdemo.log</file>
<append>true</append>
</appender>
<appender name="ROLLFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>springboot.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<appender name="SIZEROLLFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>springboot.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
<appender-ref ref="SIZEROLLFILE" />
</root>
</configuration>
Springboot的WEB開發
Springmvc和freemarker的內建
添加依賴
引入spring-boot-starter-freemarker;
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>freemarker</display-name>
<!-- SpringMVC前端控制器 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-web.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- 編碼過濾器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.do</welcome-file>
</welcome-file-list>
</web-app>
application.xml
<!--開啟注解掃描 -->
<context:component-scan base-package="com.xmg" />
application-web.xml
<import resource="classpath:application.xml" />
<!-- 支援springmvc的注解驅動 -->
<mvc:annotation-driven />
<!-- 配置一個freemarker的配置對象 -->
<bean
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<!-- 配置freemarker的檔案編碼 -->
<property name="defaultEncoding" value="UTF-8" />
<!-- 配置freemarker尋找模闆的路徑 -->
<property name="templateLoaderPath" value="/WEB-INF/views/" />
</bean>
<!-- 配置一個針對于freemarker的viewresovler -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<!-- 配置邏輯視圖自動添加的字尾名 -->
<property name="suffix" value=".ftl" />
<!-- 配置視圖的輸出HTML的contentType -->
<property name="contentType" value="text/html;charset=UTF-8" />
</bean>
FreemarkerController.java
@Controller
public class FreemarkerController {
@RequestMapping("hello")
public String hello(Model model){
model.addAttribute("msg","hello 我是 freemarker");
return "hello";
}
}
Springboot和freemarker的內建
<properties>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
建立模闆
Snip20170910_27.png
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>${msg}</h1>
</body>
</html>
FreemarkerController.java
@Controller
public class FreemarkerController {
@RequestMapping("hello")
public String hello(Model model){
model.addAttribute("msg","hello 我是 freemarker");
return "hello";
}
}
App.java
//運作main
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
通路網頁
Springboot對freemarker的配置:
1,spring.freemarker.enabled=true:是否開啟freemarker支援;
2,spring.freemarker.allow-request-override:是否允許request中的屬性覆寫model中同名屬性;預設false;
3,spring.freemarker.allow-session-override:是否允許session中的屬性覆寫model中同名屬性;預設false;
4,spring.freemarker.cache:是否支援模闆緩存;預設false;
5,spring.freemarker.charset=UTF-8:模闆編碼
6,spring.freemarker.content-type=text/html:模闆contenttype;
7,spring.freemarker.expose-request-attributes:是否開啟request屬性expose,預設false;
8,spring.freemarker.expose-session-attributes:是否開啟session屬性expose,預設false;
9,spring.freemarker.expose-spring-macro-helpers:是否開啟spring的freemarker宏支援;預設為false;
10,spring.freemarker.prefer-file-system-access:預設為true,支援實時檢查模闆修改;
11,spring.freemarker.prefix:加載模闆時候的字首;
12,spring.freemarker.settings.*:直接配置freemarker參數
13,spring.freemarker.suffix:模闆檔案字尾;
14,spring.freemarker.template-loader-path=classpath:/templates/:模闆加載位址
一般情況下我們會把以下配置加入進去的 系統會自動讀取
application.properties
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html;charset=UTF-8
spring.freemarker.expose-session-attributes=true
Springboot錯誤統一處理(@ControllerAdvice)
1).@ControllerAdvice
通過使用@ControllerAdvice定義統一的異常處理類,而不是在每個Controller中逐個定義。@ExceptionHandler用來定義函數針對的異常類型。
GlobalExceptionHandler.java
@ControllerAdvice
public class GlobalExceptionHandler {
//@ExceptionHandler(logicException.class)也可以分情況處理異常
@ExceptionHandler(Exception.class)
public String errorHandler(Model model, Exception e) {
model.addAttribute("error", e.getMessage());
//到模闆找到err.ftl将錯誤資訊顯示出來
return "err";
}
}
2)統一的異常頁面
1,SpringBoot預設情況下,把所有錯誤都重新定位到/error這個處理路徑上,由BasicErrorController類完成處理;
2,SpringBoot提供了預設的替換錯誤頁面的路徑:
1,靜态錯誤頁面預設結構:(按照這個目錄結構放置錯誤頁面報錯時就會自動找到相應的界面)
src/ resources/public/error/404.html
src/ resources/public/error/ 403.html
src/ resources/public/error/ 5xx.html
2,也可以使用模闆頁面:
src/resources/templates/error/5xx.ftl
該路徑方式是通過ErrorMvcAutoConfiguration中的DefaultErrorViewResolver完成的;
Springboot內建DataSource和mybatis
內建DataSource方式1:
先加入依賴
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.14</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
DatasourceController .java
@Controller
public class DatasourceController {
@Autowired
private DataSource dataSource;
@RequestMapping("ds")
@ResponseBody
public String datasource() {
return dataSource.getClass() + " " + dataSource.toString();
}
}
運作main
@SpringBootApplication
public class App {
//使用代碼的方式實作datasource
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql:///p2p");
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setInitialSize(5);
dataSource.setMinIdle(5);
return dataSource;
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
內建DataSource方式2:
使用配置檔案的方式
application.properties
ds.username=root
ds.password=123456
ds.url=jdbc:mysql:///p2p
ds.driverClassName=com.mysql.jdbc.Driver
ds.initialSize=3
App.java
@Bean
@ConfigurationProperties(prefix = "ds")
public DataSource dataSource(Properties properties) throws Exception {
return DruidDataSourceFactory.createDataSource(properties);
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
內建DataSource方式3:
修改配置檔案
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql:///p2p
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.initialSize=3
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
Springboot內建mybatis
mybatis內建:
使用mybatis-spring-boot-starter來完成mybatis內建;
1,引入依賴:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
2,正常完成mapper接口和mapper.xml
3,mybatis-spring-boot-starter提供了以下配置(具體參考MyBatisProperties對象):
mybatis.configLocation:mybatis的配置檔案位址;
mybatis.mapperLocations:映射檔案位址;
mybatis.typeAliasesPackage:别名掃描包;
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql:///p2p
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.initialSize=3
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
mybatis.mapperLocation=classpath:com/jd/springboot/mybatis3/*Mapper.xml
mybatis.typeAliasesPackage=com.jd.springboot.mybatis3
4,使用@MapperScan标簽掃描mapper接口
@SpringBootApplication
@MapperScan(basePackages="com.jd.springboot.mybatis3")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
1,直接開啟@EnableTransactionManagement注解;相當于在xml中配置<tx:annotation-driven/>
@SpringBootApplication
@MapperScan(basePackages="com.jd.springboot.demo.mybatis1.mapper")
@EnableTransactionManagement
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
如果在classpath中添加的是spring-boot-starter-jdbc,那麼springboot自動建立DataSourceTranscationManager;
2,使用代碼的方式:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
s1,如果開啟了@EnableTransactionManagement,隻需要在service上面使用@Transactional即可;
2,使用xml配置
将事務相關配置抽取到XML中,使用importResource引入
1,引入aop
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2,application-tx.xml
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="list*" read-only="true" />
<tx:method name="get*" read-only="true" />
<tx:method name="query*" read-only="true" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.jd.springboot.demo..service.*Service.*(..))"
id="pointCut" />
<aop:advisor advice-ref="advice" pointcut-ref="pointCut" />
</aop:config>
3,引入配置
@SpringBootApplication
@MapperScan(basePackages = "com.jd.springboot.demo.mybatis1.mapper")
@ImportResource(locations="classpath:application-tx.xml")
public class App {}
1,仍然使用MultipartFile完成上傳,Springboot是使用Servlet3中的Part對象完成上傳,不是使用的fileupload;
2,上傳相關配置:
spring.http.multipart.enabled=true:是否允許處理上傳;
spring.http.multipart.maxFileSize=1MB:允許最大的單檔案上傳大小,機關可以是kb,mb;
spring.http.multipart.maxRequestSize=10MB:允許的最大請求大小;
3,也可以通過建立一個MultipartConfigElement類型的bean對上傳進行配置:
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory mcf = new MultipartConfigFactory();
mcf.setMaxFileSize("1MB");
mcf.setMaxRequestSize("10MB");
return mcf.createMultipartConfig();
}
4,關于上傳檔案的處理:
因為應用是打成jar包,是以一般會把上傳的檔案放到其他位置,并通過設定
spring.resources.static-locations
來完成資源位置映射。
spring.resources.static-locations=classpath:/META-INF/resources/,
classpath:/resources/,
classpath:/static/,
classpath:/public/,
file:/Users/zhangshuai/devs/workspace/springboot-demo/upload/
SpringBoot總結
1.Maven中項目的繼承依賴包的管理
第1:在父項目中添加dependency,子項目不需要添加
第2:在父項目中添加dependencyManagement标簽,然後在添加dependency,子類對應的添加需要的dependency,但不需要寫版本号
2.項目分為前台和背景兩個應用的好處
從安全性考慮,背景是給公司管理人員用的,前台是給使用者用的,通路的URL位址是不一樣的,那這樣的話前台使用者就不可能通過各種嘗試去通路背景管理系統了。
從性能方面考慮,項目分成前台和背景把請求分發到不同的伺服器中,降低單個伺服器的壓力。
3.什麼是樂觀鎖?樂觀鎖能解決什麼問題?
樂觀鎖(Optimistic Lock): 顧名思義,就是很樂觀,每次去拿資料的時候都認為别人不會修改,是以不會上鎖,但是在更新的時候會判斷一下在此期間别人有沒有去更新這個資料
sql 上的展現:加版本/時間戳控制語句
update set version = version+1 ... from .... where version = xxx
解決的問題:資料并發問題(丢失更新/髒讀)
4.事務是什麼?事務有哪些特性?事務用來幹什麼?
(1)在資料庫中,所謂事務是指一組邏輯操作單元,使資料從一種狀态變換到另一種狀态。
特性:
- 原子性(Atomicity)原子性是指事務是一個不可分割的工作機關,事務中的操作要麼都發生,要麼都不發生。
- 一緻性(Consistency)事務必須使資料庫從一個一緻性狀态變換到另外一個一緻性狀态。(資料不被破壞)
- 隔離性(Isolation)事務的隔離性是指一個事務的執行不能被其他事務幹擾,即一個事務内部的操作及使用的資料對并發的其他事務是隔離的,并發執行的各個事務之間不能互相幹擾(事務空間)。
- 持久性(Durability)持久性是指一個事務一旦被送出,它對(3)資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響
為確定資料庫中資料的一緻性,資料的操縱應當是離散的成組的邏輯單元:當它全部完成時,資料的一緻性可以保持,而當這個單元中的一部分操作失敗,整個事務應全部視為錯誤,所有從起始點以後的操作應全部回退到開始狀态。
5.Springboot應用的啟動原理?
Springboot應用可以在一個主啟動類中運作main方法或者打成jar包直接運作該jar包。
因為Springboot應用一定會在主啟動類貼上一個@SpringBootApplication注解,該注解有包含很多配置,相當于spring的主配置檔案,并且springboot應用内嵌web伺服器,在我們啟動應用時,會先根據@SpringBootApplication注解的配置初始化spring容器,并運作在内嵌的web伺服器上。
6.@Configuration标簽,@ComponentScan和@Bean标簽各自的作用;
@Configuration:貼上該注解的類會被spring當成配置對象解析,可以在該配置對象建立bean注入到spring容器(相當于之前我們application.xml寫的配置)
@ComponentScan:該注解與@Configuration:結合一起使用,可以掃描應用中的元件,比如貼了@Controller,@Service,@Component的類,并注入到spring容器中。此外,改注解可以填寫掃描的包路徑,如果不寫的話就預設掃描貼了該注解的類所在的包及其子包。
@Bean:該注解結合@Configuration一起使用,作用是把貼上該注解的方法傳回的類注入到spring容器中。
7.@ConfigurationProperties标簽的作用;
該注解起到參數綁定的作用,可以非常友善的把配置檔案的配置資訊綁定到Properties對象上,并且可以控制到具體哪些字首的配置資訊需要綁定
8.日志級别:
error>warn>Info>debug>trace
我的部落格即将入駐“雲栖社群”,誠邀技術同仁一同入駐。