springboot注解
[TOC]
啟動類入口程序—啟動注解@SpringBootApplication
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableTransactionManagement
public class PlatsystemApplication {
這是一個復合注解,它包含了@ComponentScan
,和@SpringBootConfiguration
,@EnableAutoConfiguration
等注解。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@SpringBootConfiguration
繼承自@Configuration
,二者功能也一致,標注當前類是配置類,並會將當前類內聲明的一個或多個以@Bean
注解標記的方法的實例納入到srping
容器中,並且實例名就是方法名。@EnableAutoConfiguration
的作用啟動自動的配置,@EnableAutoConfiguration
注解的意思就是Springboot
根據你添加的jar包來配置你項目的默認配置,比如根據spring-boot-starter-web
,來判斷你的項目是否需要添加了webmvc
和tomcat
,就會自動的幫你配置web項目中所需要的默認配置。在下面博客會具體分析這個注解,快速入門的demo實際沒有用到該注解。@ComponentScan
,掃描當前包及其子包下被@Component
,@Controller
,@Service
,@Repository
注解標記的類並納入到spring容器中進行管理。是以前的<context:component-scan>
(以前使用在xml中使用的標簽,用來掃描包配置的平行支持)。所以本demo中的User為何會被spring
容器管理。
@SpringBootApplication參數:
- Class<?>[] exclude() default : 根據class來排除,排除特定的類加入spring容器,傳入參數value類型是class類型。
- String[] excludeName() default : 根據class name來排除,排除特定的類加入spring容器,傳入參數value類型是class的全類名字符串數組。
- String[] scanBasePackages() default : 指定掃描包,參數是包名的字符串數組。
- Class<?>[] scanBasePackageClasses() default : 掃描特定的包,參數類似是Class類型數組。
配置類相關注解
@Configuration
帶有 @Configuration 的注解類表示這個類可以使用 Spring IoC 容器作為 bean 定義的來源(一般配合@Bean注解使用)。@Bean 注解告訴 Spring,一個帶有 @Bean 的注解方法將返回一個對象,該對象應該被注冊為在 Spring 應用程序上下文中的 bean。最簡單可行的 @Configuration 類如下所示:
package org.wzh.di.demo1.congiration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HelloWorldConfig {
@Bean
public HelloWorld helloWorld() {
return new HelloWorld();
}
}
因為**@Configuration本身也是一個@Component**,因此配置類本身也會被注冊到應用上下文,並且也可以使用IOC的**@Autowired@Inject**等注解來注入所需bean。
使用外部數據
在配置類中,可以通過注入環境和配置相關參數對象,之后再構建Bean時,可以使用這些外部數據。
//在配置類中,從環境變量獲取數據並傳遞到Bean中
@Configuration
public class AppConfig {
@Autowired
public Environment env;
@Bean
IBean appBean(){
AppBean appBean = new AppBean();
appBean.setName(env.getProperty("xxx"));//此處xxx需要替換成環境中存在的值
return appBean;
}
}
@Configuration組合使用
//新建一個配置類,例如數據庫配置類:
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource(){
return new DataSource(){...};
}
}
//然后在AppConfig中用@Import來導入配置類
@Configuration
@Import(DatabaseConfig.class)
public class AppConfig {
@Autowired
public DataSource dataSource; //注入的bean在DatabaseConfig.class中定義
@Bean
IBean appBean(){
return new AppBean();
}
}
同@Profile注解組合使用
在配置類中可以申明@Profile注解,僅當滿足profile條件時,才會處理配置類,也可以將@Profile注解加載配置類中的每一個@Bean來實現更細粒度的條件控制。(@Profile 注解的作用在不同的場景下,給出不同的類實例。比如在生產環境中給出的 DataSource 實例和測試環境給出的 DataSource 實例是不同的。)
@Configuration
@Profile("develop")
public class DatabaseConfig {
@Bean
public DataSource dataSource(){
return new DataSource(){...};
}
}
同@ImportReource注解組合使用
新建spring xml配置文件config_other_bean.xml
<beans>
<bean class="com.zhaolin81.spring.framework.config.annotation.otherconfig.DatabaseConfig"></bean>
</beans>
修改配置類
@Configuration
@ImportResource("classpath:config_other_bean.xml")
public class AppConfig {
@Autowired
public DataSource dataSource; //注入的bean在config_other_bean.xml中定義
@Bean
IBean appBean(){
return new AppBean();
}
}
組件添加
@Component
把普通pojo實例化到spring容器中,相當於配置文件中的<bean id="" class=""/>。
@Component
泛指組件,當組件不好歸類的時候(不屬於@Controller、@Services等的時候),我們可以使用這個注解進行標注。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
String value() default "";
}
default
參數用來指定bean的名稱,若不指定,則以類名首字母小寫
為默認bean的名稱
不指定名稱:
@Component
public class IncomeMonDBService {
bean名稱為incomeMonDBService
,可以通過ApplicationContext.getBean("incomeMonDBService")或ApplicationContext.getBean(IncomeMonDBService.class)從spring容器中拿到對應實例。
指定名稱:
@Component("incService")
public class IncomeMonDBService {
bean的名稱為incService
。
@controller
用於標注控制層組件(注入服務)
@Controller
@RequestMapping("/invcomp")
public class InvCompController extends AbstractCommonController {
@service
用於標注業務層組件,進行業務的邏輯處理
@Service
@Lazy
public class InsertCompInfoImpl implements IService {
@repository
用於標注數據訪問層,也可以說用於標注數據訪問組件,即DAO組件,實現dao訪問
@Scope
以上組件注解默認都是單例模式,即scope="singleton"。另外scope還有prototype、request、session、global session作用域。
@Service
@Scope("prototype")
@Lazy
public class InsertCompInfoImpl implements IService {
若想更改bean的作用域,可以使用@Scope注解
1.singleton單例模式,
全局有且僅有一個實例
2.prototype原型模式,
每次獲取Bean的時候會有一個新的實例
3.request
request表示該針對每一次HTTP請求都會產生一個新的bean,同時該bean僅在當前HTTP request內有效
4.session
session作用域表示該針對每一次HTTP請求都會產生一個新的bean,同時該bean僅在當前HTTP session內有效
5.global session
global session作用域類似於標准的HTTP Session作用域,不過它僅僅在基於portlet的web應用中才有意義。Portlet規范定義了全局Session的概念,它被所有構成某個 portlet web應用的各種不同的portlet所共享。在global session作用域中定義的bean被限定於全局portlet Session的生命周期范圍內。如果你在web中使用global session作用域來標識bean,那么web會自動當成session類型來使用
@Lazy
用於標識bean是否需要延遲加載。
ApplicationContext實現的默認行為就是在啟動服務器時將所有singleton bean提前進行實例化 (也就是依賴注入)。提前實例化意味着作為初始化過程的一部分,applicationContext實例會創 建並配置所有的singleton bean。通常情況下這是一件好事,因為這樣在配置中的任何錯誤就會 被立刻實現(否則的話可能要話幾個小時甚至幾天)。
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
boolean value() default true;
}
只有一個參數,默認是true,也就是說只要加了這個注解,bean將不會在ApplicationContext啟動時提前被實例化,而是第一次向容器通過getBean索取bean時實例化的。
注意:
如果一個設置了立即加載的bean1,引用了一個延時加載的bean2,那么bean1在容器啟動時被實例化,而bean2 由於被bean1引用,所以也被實例化,這種情況也符合延時加載的bean在第一次調用時才被實例化的規則。
如果@Configuration 上使用了Lazy,則@Configuration 中的所有都會被懶加載。
除了作用於@Component組件或其@Bean初始化方法,也作用於Inject和Autowired。就是Autowired注釋的bean會默認進行懶加載,除非他之前就被加載了。
@Bean
@Bean是一個方法級別上的注解,主要用在@Configuration注解的類里,也可以用在@Component注解的類里。添加的bean的id為方法名
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
@bean 也可以依賴其他任意數量的bean,如果TransferService 依賴 AccountRepository,我們可以通過方法參數實現這個依賴
@Configuration
public class AppConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
任何使用@Bean定義的bean,也可以執行生命周期的回調函數,類似@PostConstruct and @PreDestroy的方法。用法如下
public class Foo {
public void init() {
// initialization logic
}
}
public class Bar {
public void cleanup() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public Foo foo() {
return new Foo();
}
@Bean(destroyMethod = "cleanup")
public Bar bar() {
return new Bar();
}
}
默認使用javaConfig配置的bean,如果存在close或者shutdown方法,則在bean銷毀時會自動執行該方法,如果你不想執行該方法,則添加@Bean(destroyMethod="")來防止出發銷毀方法
@Autowired
@Autowired可以對類成員變量、方法及構造函數進行標注,完成自動裝配的工作。 通過 @Autowired的使用來消除 set ,get方法。
@Component
public class InvoiceOperationUtil {
}
@Service
@Lazy
public class InvalidInvoiceImpl implements IService {
private static Logger logger = LoggerFactory.getLogger(InvalidInvoiceImpl.class);
@Autowired
private InvoiceOperationUtil invoiceOperationUtil;
}
InvalidInvoiceImpl實現類有一個InvoiceOperationUtil類型的屬性,通過@Autowired自動裝配方式,從IoC容器中去查找到,並返回給該屬性。
其實在啟動spring IoC時,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor后置處理器,當容器掃描到@Autowied、@Resource或@Inject時,就會在IoC容器自動查找需要的bean,並裝配給該對象的屬性
注意事項:
在使用@Autowired時,首先在容器中查詢對應類型的bean
如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的數據
如果查詢的結果不止一個,那么@Autowired會根據屬性名稱來查找。
如果查詢的結果為空,那么會拋出異常。解決方法時,使用required=false
JSR-250規范定義的注解
@Resource、@PostConstruct以及@PreDestroy
@PostConstruct相當於init-method,使用在方法上,當Bean初始化時執行。
@PreDestroy相當於destory-method,使用在方法上,當Bean銷毀時執行。
@Resource的作用相當於@Autowired,只不過@Autowired按byType自動注入,而@Resource默認按 byName
自動注入罷了。@Resource有兩個屬性是比較重要的,分是name和type,Spring將@Resource注解的name屬性
解析為bean的名字,而type屬性則解析為bean的類型。所以如果使用name屬性,則使用byName的自動注入策
略,而使用type屬性時則使用byType自動注入策略。如果既不指定name也不指定type屬性,這時將通過反射機制使用byName自動注入策略。
@Resource裝配順序
如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常
如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個
原始類型進行匹配,如果匹配則自動裝配;
@Autowired 與@Resource的區別:
1、 @Autowired與@Resource都可以用來裝配bean. 都可以寫在字段上,或寫在setter方法上。
2、 @Autowired默認按類型裝配(這個注解是屬業spring的),默認情況下必須要求依賴對象必須存在,如果要
允許null值,可以設置它的required屬性為false,如:@Autowired(required=false) ,如果我們想使用名稱裝配
可以結合@Qualifier注解進行使用,如下:
`@Autowired``()``@Qualifier``(``"baseDao"``)``private``BaseDao baseDao;`
3、@Resource(這個注解屬於J2EE的),默認按照名稱進行裝配,名稱可以通過name屬性進行指定,如果沒有
指定name屬性,當注解寫在字段上時,默認取字段名進行安裝名稱查找,如果注解寫在setter方法上默認取屬性
名進行裝配。當找不到與名稱匹配的bean時才按照類型進行裝配。但是需要注意的是,如果name屬性一旦指
定,就只會按照名稱進行裝配。
`@Resource``(name=``"baseDao"``)``private``BaseDao baseDao;`
@Qualifier
一般作為@Autowired()的修飾用
@Autowired是根據類型進行自動裝配的。如果當Spring上下文中存在不止一個UserDao類型的bean時,就會拋
出BeanCreationException異常;如果Spring上下文中不存在UserDao類型的bean,也會拋出
BeanCreationException異常。我們可以使用@Qualifier配合@Autowired來解決這些問題。如下:
①可能存在多個UserDao實例
@Autowired
@Qualifier("userServiceImpl")
public IUserService userService;
或者
@Autowired
public void setUserDao(@Qualifier("userDao") UserDao userDao) {
this.userDao = userDao;
}
這樣Spring會找到id為userServiceImpl和userDao的bean進行裝配。
配置文件相關注解
@ConfigurationProperties
想要讀取配置文件的信息並自動封裝成實體類,可以使用@ConfigurationProperties,它可以把同類的配置信息自動封裝成實體類
首先在配置文件里面,這些信息是這樣子的:
connection.username=admin
connection.password=kyjufskifas2jsfs
connection.remoteAddress=192.168.1.1
這時候可以定義一個實體類在裝載配置文件信息
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
private String username;
private String remoteAddress;
private String password ;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getRemoteAddress() {
return remoteAddress;
}
public void setRemoteAddress(String remoteAddress) {
this.remoteAddress = remoteAddress;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
還可以把@ConfigurationProperties還可以直接定義在@bean的注解上,這是bean實體類就不用@Component和@ConfigurationProperties了
@SpringBootApplication
public class DemoApplication{
//...
@Bean
@ConfigurationProperties(prefix = "connection")
public ConnectionSettings connectionSettings(){
return new ConnectionSettings();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
如果發現@ConfigurationPropertie不生效,有可能是項目的目錄結構問題,
可以通過@EnableConfigurationProperties(ConnectionSettings.class)來明確指定需要用哪個實體類來裝載配置信息
@Configuration
@EnableConfigurationProperties(ConnectionSettings.class)
public class MailConfiguration {
@Autowired private MailProperties mailProperties;
@Bean public JavaMailSender javaMailSender() {
// omitted for readability
}
}
@PropertySource
加載指定的配置文件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
/**
* 資源的名稱
*/
String name() default "";
/**
* 資源文件路徑,可以是數據多個文件地址
* 可以是classpath地址如:
* "classpath:/com/myco/app.properties"
* 也可以是對應的文件系統地址如:
* "file:/path/to/file"
*/
String[] value();
/**
* 是否忽略文件資源是否存在,默認是false,也就是說配置不存在的文件地址spring啟動將會報錯
*/
boolean ignoreResourceNotFound() default false;
/**
* 這個沒什么好說的了就是對應的字符編碼了,默認是空值,如果配置文件中有中文應該設置為utf-8 */
String encoding() default "";
/**
* 關鍵的元素了 讀取對應資源文件的工廠類了 默認的是PropertySourceFactory
*/
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
例子:
/**
* 將配置文件中配置的每一個屬性的值,映射到這個組件中
* @ConfigurationProperties:告訴SpringBoot將本類中的所有屬性和配置文件中相關的配置進行綁定;
* prefix = "person":配置文件中哪個下面的所有屬性進行一一映射
*
* @ConfigurationProperties(prefix = "person")默認從全局配置文件中獲取值;
*
*/
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
}
通過Environment設置
@Configuration
@PropertySource("classpath:jdbc.properties")
public class PropertiesWithJavaConfig {
@Autowired
private Environment env;
}
接着就可以用env.getProperty("jdbc.driver")得到相應的屬性值
Mybatis-數據源相關注解
@MapperScan
用@MapperScan注解,指定basePackages,掃描mybatis Mapper接口類
@Configuration
@MapperScan(basePackages = {"com.lqt.db2dao.mapper"}, sqlSessionFactoryRef = "db2SqlSessionFactory")
public class Db2DatasourceConfig {
@Transactional
事務管理
@Transactional(value = "db2TransactionManager", rollbackFor = Exception.class)
public Map<String, Object> insertdbOperate(InvGoodsInfo goodsInfo, InvGoodsReln goodsReln) throws DataAccessException {
}
要啟用聲明式事務,還得在啟動類上添加@EnableTransactionManagement注解
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableTransactionManagement
public class PlatsystemApplication {
public static void main(String[] args) {
SpringApplication.run(PlatsystemApplication.class, args);
}
}
@Transactional屬性
屬性 | 類型 | 描述 |
---|---|---|
value | String | 可選的限定描述符,指定使用的事務管理器 |
propagation | enum: Propagation | 可選的事務傳播行為設置 |
isolation | enum: Isolation | 可選的事務隔離級別設置 |
readOnly | boolean | 讀寫或只讀事務,默認讀寫 |
timeout | int (in seconds granularity) | 事務超時時間設置 |
rollbackFor | Class對象數組,必須繼承自Throwable | 導致事務回滾的異常類數組 |
rollbackForClassName | 類名數組,必須繼承自Throwable | 導致事務回滾的異常類名字數組 |
noRollbackFor | Class對象數組,必須繼承自Throwable | 不會導致事務回滾的異常類數組 |
noRollbackForClassName | 類名數組,必須繼承自Throwable | 不會導致事務回滾的異常類名字數組 |
用法
由Spring來統一管理業務對象,這樣業務對象上面的事務才會生效。
如果業務對象是通過new產生的,即沒有注冊bean,數據庫是不會執行回滾的。
@Transactional 可以作用於接口、接口方法、類以及類方法上。當作用於類上時,該類的所有 public 方法將都具有該類型的事務屬性,同時,我們也可以在方法級別使用該標注來覆蓋類級別的定義。
雖然 @Transactional 注解可以作用於接口、接口方法、類以及類方法上,但是 Spring 建議不要在接口或者接口方法上使用該注解,因為Spring數據庫事務的約定,其實現原理是AOP,而AOP的原理是動態代理,只有在使用基於接口的代理時它才會生效。另外, @Transactional 注解應該只被應用到 public 方法上,這是由 Spring AOP 的本質決定的。如果你在 protected、private 或者默認可見性的方法上使用 @Transactional 注解,這將被忽略,也不會拋出任何異常。
默認情況下,只有來自外部的方法調用才會被AOP代理捕獲,也就是,類內部方法調用本類內部的其他方法並不會引起事務行為,即使被調用方法使用@Transactional注解進行修飾。
要解決這個問題,可以用一個service去調用另一個service,這樣就是代理對象的調用;也可以從Spring IOC容器中獲取代理對象去啟動AOP。
spring事務回滾規則
指示spring事務管理器回滾一個事務的推薦方法是在當前事務的上下文內拋出異常。spring事務管理器會捕捉任何未處理的異常,然后依據規則決定是否回滾拋出異常的事務。
默認配置下,spring只有在拋出的異常為運行時unchecked異常時才回滾該事務,也就是拋出的異常為RuntimeException的子類(Errors也會導致事務回滾),而拋出checked異常則不會導致事務回滾。 可以明確的配置在拋出那些異常時回滾事務,包括checked異常。也可以明確定義那些異常拋出時不回滾事務。
還可以編程性的通過setRollbackOnly()方法來指示一個事務必須回滾,在調用完setRollbackOnly()后你所能執行的唯一操作就是回滾。
@Primary
當一個接口有2個不同實現時,使用@Autowired注解時會報org.springframework.beans.factory.NoUniqueBeanDefinitionException異常信息
Primary可以理解為默認優先選擇,同時不可以同時設置多個
另外,在配置多數據源是,一定要配置在其中一個數據源上加上@Primary注解。
測試相關注解
@RunWith
當一個類用@RunWith注釋或繼承一個用@RunWith注釋的類時,JUnit將調用它所引用的類來運行該類中的測試而不是開發者去在junit內部去構建它。
@RunWith就是一個運行器
@RunWith(JUnit4.class)就是指用JUnit4來運行
@RunWith(SpringJUnit4ClassRunner.class),讓測試運行於Spring測試環境
@RunWith(SpringRunner.class)(SpringRunner 繼承了SpringJUnit4ClassRunner,沒有擴展任何功能;使用SpringRunner,名字簡短而已。)
@RunWith(Suite.class)的話就是一套測試集合
@ContextConfiguration Spring整合JUnit4測試時,使用注解引入多個配置文件
單個文件 @ContextConfiguration(Locations="classpath:applicationContext.xml") @ContextConfiguration(classes = SimpleConfiguration.class)
多個文件時,可用
@ContextConfiguration(locations = { "classpath:spring1.xml", "classpath:spring2.xml" })
@SpringBootTest
使用@SpringBootTest注解可以運行環境,測試后台代碼。
@RunWith(SpringRunner.class)
@SpringBootTest(classes = StartUpApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PlatsystemApplicationTests {
}
//其中,classes屬性指定啟動類,SpringBootTest.WebEnvironment.RANDOM_PORT經常和測試類中@LocalServerPort一起在注入屬性時使用。會隨機生成一個端口號。
springboot單元測試關節注解接受
@RunWith(SpringJUnit4ClassRunner.class),這是JUnit的注解,通過這個注解讓SpringJUnit4ClassRunner這個類提供Spring測試上下文。
@SpringApplicationConfiguration(classes = 啟動類.class),這是Spring Boot注解,為了進行集成測試,需要通過這個注解加載和配置Spring應用上下文。這是一個元注解(meta-annoation),它包含了@ContextConfiguration( loader = SpringApplicationContextLoader.class)這個注解,測試框架通過這個注解使用Spring Boot框架的SpringApplicationContextLoader加載器創建應用上下文。
@WebAppConfiguration 表明是WEB應用環境,不能和@WebIntegrationTest一起使用
@WebIntegrationTest(“server.port:0”),這個注解表示當前的測試是集成測試(integration test),因此需要初始化完整的上下文並啟動應用程序。這個注解一般和@SpringApplicationConfiguration一起出現。server.port:0指的是讓Spring Boot在隨機端口上啟動Tomcat服務,隨后在測試中程序通過@Value(“$”)獲得這個端口號,並賦值給port變量。當在Jenkins或其他持續集成服務器上運行測試程序時,這種隨機獲取端口的能力可以提供測試程序的並行性。
@SpringBootTest(classes = AppApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK) 指定啟動類,web環境
- WebEnvironment.MOCK—提供一個Mock的Servlet環境,內置的Servlet容器並沒有真實的啟動,主要搭配使用@AutoConfigureMockMvc
- WebEnvironment.RANDOM_PORT — 提供一個真實的Servlet環境,也就是說會啟動內置容器,然后使用的是隨機端口
- WebEnvironment.DEFINED_PORT — 這個配置也是提供一個真實的Servlet環境,使用的默認的端口,如果沒有配置就是8080
- WebEnvironment.NONE — 這是個神奇的配置,跟Mock一樣也不提供真實的Servlet環境。
JUnit相關注解
//在所有測試方法前執行一次,一般在其中寫上整體初始化的代碼
@BeforeClass
//在所有測試方法后執行一次,一般在其中寫上銷毀和釋放資源的代碼
@AfterClass
//在每個測試方法前執行,一般用來初始化方法(比如我們在測試別的方法時,類中與其他測試方法共享的值已經被改變,為了保證測試結果的有效性,我們會在@Before注解的方法中重置數據)
@Before
//在每個測試方法后執行,在方法執行完成后要做的事情
@After
// 測試方法執行超過1000毫秒后算超時,測試將失敗
@Test(timeout = 1000)
// 測試方法期望得到的異常類,如果方法執行沒有拋出指定的異常,則測試失敗
@Test(expected = Exception.class)
// 執行測試時將忽略掉此方法,如果用於修飾類,則忽略整個類
@Ignore(“not ready yet”)
@Test
打包測試
正常情況下我們寫了5個測試類,我們需要一個一個執行。 打包測試,就是新增一個類,然后將我們寫好的其他測試類配置在一起,然后直接運行這個類就達到同時運行其他幾個測試的目的。
@RunWith(Suite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {
// 類中不需要編寫代碼
}
多環境測試
@ActiveProfiles(profiles = "test")
//在測試類上面指定profiles,可以改變當前spring 的profile,來達到多環境的測試
MockMvc 模擬外部環境測試
@RunWith(SpringRunner.class.class)
@SpringBootTest(classes = AppApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class AppApplication{
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setupMockMvc() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
/***
* 測試添加用戶接口
* @throws Exception
*/
@Test
public void testAddUser() throws Exception {
//構造添加的用戶信息
UserInfo userInfo = new UserInfo();
userInfo.setName("testuser2");
userInfo.setAge(29);
userInfo.setAddress("北京");
ObjectMapper mapper = new ObjectMapper();
//調用接口,傳入添加的用戶參數
mockMvc.perform(post("/user/adduser")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(mapper.writeValueAsString(userInfo)))
//判斷返回值,是否達到預期,測試示例中的返回值的結構如下{"errcode":0,"errmsg":"OK","p2pdata":null}
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
//使用jsonPath解析返回值,判斷具體的內容
.andExpect(jsonPath("$.errcode", is(0)))
.andExpect(jsonPath("$.p2pdata", notNullValue()))
.andExpect(jsonPath("$.p2pdata.id", not(0)))
.andExpect(jsonPath("$.p2pdata.name", is("testuser2")));
}
}