Spring的注解大全


轉載:https://blog.csdn.net/achenyuan/article/details/72786759

轉載:https://www.cnblogs.com/alter888/p/9083963.html

一.Spring使用的注解大全

注解 解釋
@Controller 組合注解(組合了@Component注解),應用在MVC層(控制層),DispatcherServlet會自動掃描注解了此注解的類,然后將web請求映射到注解了@RequestMapping的方法上。
@Service 組合注解(組合了@Component注解),應用在service層(業務邏輯層)
@Reponsitory 組合注解(組合了@Component注解),應用在dao層(數據訪問層)
@Component 表示一個帶注釋的類是一個“組件”,成為Spring管理的Bean。當使用基於注解的配置和類路徑掃描時,這些類被視為自動檢測的候選對象。同時@Component還是一個元注解。
@Autowired Spring提供的工具(由Spring的依賴注入工具(BeanPostProcessor、BeanFactoryPostProcessor)自動注入。)
@Resource JSR-250提供的注解
@Inject JSR-330提供的注解
@Configuration 聲明當前類是一個配置類(相當於一個Spring配置的xml文件)
@ComponentScan 自動掃描指定包下所有使用@Service,@Component,@Controller,@Repository的類並注冊
@Bean 注解在方法上,聲明當前方法的返回值為一個Bean。返回的Bean對應的類中可以定義init()方法和destroy()方法,然后在@Bean(initMethod=”init”,destroyMethod=”destroy”)定義,在構造之后執行init,在銷毀之前執行destroy。
@Aspect 聲明一個切面(就是說這是一個額外功能)
@After 后置建言(advice),在原方法前執行。
@Before 前置建言(advice),在原方法后執行。
@Around 環繞建言(advice),在原方法執行前執行,在原方法執行后再執行(@Around可以實現其他兩種advice)
@PointCut 聲明切點,即定義攔截規則,確定有哪些方法會被切入
@Transactional 聲明事務(一般默認配置即可滿足要求,當然也可以自定義)
@Cacheable 聲明數據緩存
@EnableAspectJAutoProxy 開啟Spring對AspectJ的支持
@Value 值得注入。經常與Sping EL表達式語言一起使用,注入普通字符,系統屬性,表達式運算結果,其他Bean的屬性,文件內容,網址請求內容,配置文件屬性值等等
@PropertySource 指定文件地址。提供了一種方便的、聲明性的機制,用於向Spring的環境添加PropertySource。與@configuration類一起使用。
@PostConstruct 標注在方法上,該方法在構造函數執行完成之后執行。
@PreDestroy 標注在方法上,該方法在對象銷毀之前執行。
@Profile 表示當一個或多個指定的文件是活動的時,一個組件是有資格注冊的。使用@Profile注解類或者方法,達到在不同情況下選擇實例化不同的Bean。@Profile(“dev”)表示為dev時實例化。
@EnableAsync 開啟異步任務支持。注解在配置類上。
@Async 注解在方法上標示這是一個異步方法,在類上標示這個類所有的方法都是異步方法。
@EnableScheduling 注解在配置類上,開啟對計划任務的支持。
@Scheduled 注解在方法上,聲明該方法是計划任務。支持多種類型的計划任務:cron,fixDelay,fixRate
@Conditional 根據滿足某一特定條件創建特定的Bean
@Enable* 通過簡單的@Enable*來開啟一項功能的支持。所有@Enable*注解都有一個@Import注解,@Import是用來導入配置類的,這也就意味着這些自動開啟的實現其實是導入了一些自動配置的Bean(1.直接導入配置類2.依據條件選擇配置類3.動態注冊配置類)
@RunWith 這個是Junit的注解,springboot集成了junit。一般在測試類里使用:@RunWith(SpringJUnit4ClassRunner.class) — SpringJUnit4ClassRunner在JUnit環境下提供Sprng TestContext Framework的功能
@ContextConfiguration 用來加載配置ApplicationContext,其中classes屬性用來加載配置類:@ContextConfiguration(classes = {TestConfig.class(自定義的一個配置類)})
@ActiveProfiles 用來聲明活動的profile–@ActiveProfiles(“prod”(這個prod定義在配置類中))
@EnableWebMvc 用在配置類上,開啟SpringMvc的Mvc的一些默認配置:如ViewResolver,MessageConverter等。同時在自己定制SpringMvc的相關配置時需要做到兩點:1.配置類繼承WebMvcConfigurerAdapter類2.就是必須使用這個@EnableWebMvc注解。
@RequestMapping 用來映射web請求(訪問路徑和參數),處理類和方法的。可以注解在類和方法上,注解在方法上的@RequestMapping路徑會繼承注解在類上的路徑。同時支持Serlvet的request和response作為參數,也支持對request和response的媒體類型進行配置。其中有value(路徑),produces(定義返回的媒體類型和字符集),method(指定請求方式)等屬性。
@ResponseBody 將返回值放在response體內。返回的是數據而不是頁面
@RequestBody 允許request的參數在request體中,而不是在直接鏈接在地址的后面。此注解放置在參數前。
@PathVariable 放置在參數前,用來接受路徑參數。
@RestController 組合注解,組合了@Controller和@ResponseBody,當我們只開發一個和頁面交互數據的控制層的時候可以使用此注解。
@ControllerAdvice 用在類上,聲明一個控制器建言,它也組合了@Component注解,會自動注冊為Spring的Bean。
@ExceptionHandler 用在方法上定義全局處理,通過他的value屬性可以過濾攔截的條件:@ExceptionHandler(value=Exception.class)–表示攔截所有的Exception。
@ModelAttribute 將鍵值對添加到全局,所有注解了@RequestMapping的方法可獲得次鍵值對(就是在請求到達之前,往model里addAttribute一對name-value而已)。
@InitBinder 通過@InitBinder注解定制WebDataBinder(用在方法上,方法有一個WebDataBinder作為參數,用WebDataBinder在方法內定制數據綁定,例如可以忽略request傳過來的參數Id等)。
@WebAppConfiguration 一般用在測試上,注解在類上,用來聲明加載的ApplicationContext是一個WebApplicationContext。他的屬性指定的是Web資源的位置,默認為src/main/webapp,我們可以修改為:@WebAppConfiguration(“src/main/resources”)。
@EnableAutoConfiguration 此注釋自動載入應用程序所需的所有Bean——這依賴於Spring Boot在類路徑中的查找。該注解組合了@Import注解,@Import注解導入了EnableAutoCofigurationImportSelector類,它使用SpringFactoriesLoader.loaderFactoryNames方法來掃描具有META-INF/spring.factories文件的jar包。而spring.factories里聲明了有哪些自動配置。
@SpingBootApplication SpringBoot的核心注解,主要目的是開啟自動配置。它也是一個組合注解,主要組合了@Configurer,@EnableAutoConfiguration(核心)和@ComponentScan。可以通過@SpringBootApplication(exclude={想要關閉的自動配置的類名.class})來關閉特定的自動配置。
@ImportResource 雖然Spring提倡零配置,但是還是提供了對xml文件的支持,這個注解就是用來加載xml配置的。例:@ImportResource({“classpath
@ConfigurationProperties 將properties屬性與一個Bean及其屬性相關聯,從而實現類型安全的配置。例:@ConfigurationProperties(prefix=”authot”,locations={“classpath
@ConditionalOnBean 條件注解。當容器里有指定Bean的條件下。
@ConditionalOnClass 條件注解。當類路徑下有指定的類的條件下。
@ConditionalOnExpression 條件注解。基於SpEL表達式作為判斷條件。
@ConditionalOnJava 條件注解。基於JVM版本作為判斷條件。
@ConditionalOnJndi 條件注解。在JNDI存在的條件下查找指定的位置。
@ConditionalOnMissingBean 條件注解。當容器里沒有指定Bean的情況下。
@ConditionalOnMissingClass 條件注解。當類路徑下沒有指定的類的情況下。
@ConditionalOnNotWebApplication 條件注解。當前項目不是web項目的條件下。
@ConditionalOnResource 條件注解。類路徑是否有指定的值。
@ConditionalOnSingleCandidate 條件注解。當指定Bean在容器中只有一個,后者雖然有多個但是指定首選的Bean。
@ConditionalOnWebApplication 條件注解。當前項目是web項目的情況下。
@EnableConfigurationProperties 注解在類上,聲明開啟屬性注入,使用@Autowired注入。例:@EnableConfigurationProperties(HttpEncodingProperties.class)。
@AutoConfigureAfter 在指定的自動配置類之后再配置。例:@AutoConfigureAfter(WebMvcAutoConfiguration.class)

二.注解解釋

注解是個好東西,但好東西我們也是看見過,整理過,理解過,用過才知道好。不求我們每個都記住,但求保有印象,在需要的時候能提取出來再查找相關資料,平時工作就不會顯得那么被動了。


1.@Configuration注解

該類等價 與XML中配置beans,相當於Ioc容器,它的某個方法頭上如果注冊了@Bean,就會作為這個Spring容器中的Bean,與xml中配置的bean意思一樣。

@Configuration注解的類必需使用<context:component-scanbase-package="XXX"/>掃描.如下:

@Configuration
public class MainConfig {

//在properties文件里配置
@Value("${wx_appid}")
public String appid;

protected MainConfig(){}

@Bean
public WxMpService wxMpService() {
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
return wxMpService;
}
}

定義一個MainConfig,用@Configuration注解,那MainConfig相當於xml里的beans,里面用@Bean注解的和xml里定義的bean等價,用<context:component-scanbase-package=”XXX”/>掃描該類,最終我們可以在程序里用@AutoWired或@Resource注解取得用@Bean注解的bean,和用xml先配置bean然后在程序里自動注入一樣。目的是減少xml里配置。

 

2.@Value注解

為了簡化從properties里取配置,可以使用@Value, 可以properties文件中的配置值。

在dispatcher-servlet.xml里引入properties文件。

<context:property-placeholder location="classpath:test.properties" />
在程序里使用@Value:

@Value("${wx_appid}")

publicString appid;
即使給變量賦了初值也會以配置文件的值為准。

 

 

3. @Controller, @Service, @Repository,@Component

目前4種注解意思是一樣,並沒有什么區別,區別只是名字不同。使用方法:

1.使用<context:component-scanbase-package="XXX"/>掃描被注解的類

2. 在類上寫注解:

@Controller

public class TestController {

 

}

 

 

4. @PostConstruct 和 @PreDestory 


實現初始化和銷毀bean之前進行的操作,只能有一個方法可以用此注釋進行注釋,方法不能有參數,返回值必需是void,方法需要是非靜態的。

例如:
public class TestService {

@PostConstruct
public void init(){
System.out.println("初始化");
}

@PreDestroy
public void dostory(){
System.out.println("銷毀");
}
}

@PostConstruct:在構造方法和init方法(如果有的話)之間得到調用,且只會執行一次。

@PreDestory:注解的方法在destory()方法調用后得到執行。

網上拷貝的流程圖:

 


引深一點,Spring 容器中的 Bean 是有生命周期的,Spring 允許在 Bean 在初始化完成后以及 Bean 銷毀前執行特定的操作,常用的設定方式有以下三種:

1.通過實現 InitializingBean/DisposableBean 接口來定制初始化之后/銷毀之前的操作方法;

2.通過 <bean> 元素的 init-method/destroy-method屬性指定初始化之后 /銷毀之前調用的操作方法;

3.在指定方法上加上@PostConstruct 或@PreDestroy注解來制定該方法是在初始化之后還是銷毀之前調用

但他們之前並不等價。即使3個方法都用上了,也有先后順序.

Constructor > @PostConstruct >InitializingBean > init-method

 

 

5. @Primary

自動裝配時當出現多個Bean候選者時,被注解為@Primary的Bean將作為首選者,否則將拋出異常。

例如:

@Component
public class Apple implements Fruit{

@Override
public String hello() {
return "我是蘋果";
}
}

@Component
@Primary
public class Pear implements Fruit{

@Override
public String hello(String lyrics) {
return "梨子";
}
}

public class FruitService {

//Fruit有2個實例子類,因為梨子用@Primary,那么會使用Pear注入
@Autowired
private Fruit fruit;

public String hello(){
return fruit.hello();
}
}

 

6. @Lazy(true)

    用於指定該Bean是否取消預初始化,用於注解類,延遲初始化。

 

 

7. @Autowired

Autowired默認先按byType,如果發現找到多個bean,則,又按照byName方式比對,如果還有多個,則報出異常。

1.可以手動指定按byName方式注入,使用@Qualifier。

//通過此注解完成從spring配置文件中 查找滿足Fruit的bean,然后按//@Qualifier指定pean

@Autowired

@Qualifier("pean")

public Fruit fruit;

2.如果要允許null 值,可以設置它的required屬性為false,如:@Autowired(required=false) 

public Fruit fruit;

 

 

8. @Resource

默認按 byName自動注入,如果找不到再按byType找bean,如果還是找不到則拋異常,無論按byName還是byType如果找到多個,則拋異常。

可以手動指定bean,它有2個屬性分別是name和type,使用name屬性,則使用byName的自動注入,而使用type屬性時則使用byType自動注入。

@Resource(name=”bean名字”)

@Resource(type=”bean的class”)

這個注解是屬於J2EE的,減少了與spring的耦合。

 

 

9. @Async

    java里使用線程用3種方法:

1.  繼承Thread,重寫run方法

2.  實現Runnable,重寫run方法

3.  使用Callable和Future接口創建線程,並能得到返回值。

前2種簡單,第3種方式特別提示一下,例子如下:

class MyCallable implements Callable<Integer> {
private int i = 0;
// 與run()方法不同的是,call()方法具有返回值
@Override
public Integer call() {
int sum = 0;
for (; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
sum += i;
}
return sum;
}
}


main方法:

public static void main(String[] args) {
Callable<Integer> myCallable = new MyCallable(); // 創建MyCallable對象
FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //使用FutureTask來包裝MyCallable對象
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30) {
Thread thread = new Thread(ft); //FutureTask對象作為Thread對象的target創建新的線程
thread.start(); //線程進入到就緒狀態
}
}
System.out.println("主線程for循環執行完畢..");
try {
int sum = ft.get(); //取得新創建的新線程中的call()方法返回的結果
System.out.println("sum = " + sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}

而使用@Async可視為第4種方法。基於@Async標注的方法,稱之為異步方法,這個注解用於標注某個方法或某個類里面的所有方法都是需要異步處理的。被注解的方法被調用的時候,會在新線程中執行,而調用它的方法會在原來的線程中執行。

application.xml形勢的配置:

第一步配置XML。

<!--掃描注解,其中包括@Async -->
<context:component-scan base-package="com.test"/>
<!-- 支持異步方法執行, 指定一個缺省的executor給@Async使用-->
<task:annotation-driven executor="defaultAsyncExecutor" />
<!—配置一個線程執行器-->
<task:executor id=" defaultAsyncExecutor "pool-size="100-10000" queue-capacity="10" keep-alive =”5”/>

參數解讀:

<task:executor />配置參數:

id:當配置多個executor時,被@Async("id")指定使用;也被作為線程名的前綴。

pool-size:

core size:最小的線程數,缺省:1

max size:最大的線程數,缺省:Integer.MAX_VALUE

queue-capacity:當最小的線程數已經被占用滿后,新的任務會被放進queue里面,當這個queue的capacity也被占滿之后,pool里面會創建新線程處理這個任務,直到總線程數達到了max size,這時系統會拒絕這個任務並拋出TaskRejectedException異常(缺省配置的情況下,可以通過rejection-policy來決定如何處理這種情況)。缺省值為:Integer.MAX_VALUE

keep-alive:超過core size的那些線程,任務完成后,再經過這個時長(秒)會被結束掉

rejection-policy:當pool已經達到max size的時候,如何處理新任務

ABORT(缺省):拋出TaskRejectedException異常,然后不執行DISCARD:不執行,也不拋出異常

DISCARD_OLDEST:丟棄queue中最舊的那個任務

CALLER_RUNS:不在新線程中執行任務,而是有調用者所在的線程來執行

第二步在類或方法上添加@Async,當調用該方法時,則該方法即是用異常執行的方法單獨開個新線程執行。

@Async(“可以指定執行器id,也可以不指定”)
public static void testAsyncVoid (){
try {
//讓程序暫停100秒,相當於執行一個很耗時的任務
System.out.println(“異常執行打印字符串”);
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

當在外部調用testAsync方法時即在新線程中執行,由上面<task: annotation-driven/>執行器去維護線程。

總結:先用context:component-scan去掃描注解,讓spring能識別到@Async注解,然后task:annotation-driven去驅動@Async注解,並可以指定默認的線程執行器executor。那么當用@Async注解的方法或類得到調用時,線程執行器會創建新的線程去執行。

 

上面方法是無返回值的情況,還有異常方法有返回值的例子。

@Async
public Future<String> testAsyncReturn () {
System.out.println("Execute method asynchronously - "
+ Thread.currentThread().getName());
try {
Thread.sleep(5000);
return new AsyncResult<String>("hello world !!!!");
} catch (InterruptedException e) {
//
}
return null;
}

返回的數據類型為Future類型,接口實現類是AsyncResult.

調用方法如下:

public void test(){
Future<String> future = cc.testAsyncReturn();
while (true) { ///這里使用了循環判斷,等待獲取結果信息
if (future.isDone()) { //判斷是否執行完畢
System.out.println("Result from asynchronous process - " + future.get());
break;
}
System.out.println("Continue doing something else. ");
Thread.sleep(1000);
}
}

通過不停的檢查Future的狀態來獲取當前的異步方法是否執行完畢

參考文章

編程的方式使用@Async:

@Configuration
@EnableAsync
public class SpringConfig {

private int corePoolSize = 10;
private int maxPoolSize = 200;
private int queueCapacity = 10;
private String ThreadNamePrefix = "MyLogExecutor-";

@Bean
public Executor logExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix(ThreadNamePrefix);
// rejection-policy:當pool已經達到max size的時候,如何處理新任務
// CALLER_RUNS:不在新線程中執行任務,而是有調用者所在的線程來執行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}

 

10.@Named

@Named和Spring的@Component功能相同。@Named可以有值,如果沒有值生成的Bean名稱默認和類名相同。比如

@Named public class Person 

@Named("cc") public class Person

 

 

11. @Inject

使用@Inject需要引用javax.inject.jar,它與Spring沒有關系,是jsr330規范。

與@Autowired有互換性。

 

 

12. @Singleton

只要在類上加上這個注解,就可以實現一個單例類,不需要自己手動編寫單例實現類。

 

 

13.@Valid,@Valided

@Valid

   網上一大片使用@Valid失效不能用的情況。為什么呢?

1.@Valid必需使用在以@RequestBody接收參數的情況下。

2.使用ajax以POST方式提示數據,禁止用Fiddler以及瀏覽器直接訪問的方式測試接口

3.用<mvc:annotation-driven />添加注解驅動。

4.@Valid是應用在javabean上的校驗。

5.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.5.3</version>

這些jar包是需要的。@Valid是使用hibernate validation的時候使用,可參數下面介紹的@RequestBody

6.@Valid下后面緊跟BindingResult result,驗證結果保存在result

 

例如:

@RequestMapping("/test")
public String testValid(@Valid User user, BindingResult result){
if (result.hasErrors()){
List<ObjectError> errorList = result.getAllErrors();
for(ObjectError error : errorList){
System.out.println(error.getDefaultMessage());
}
}
return "test";
}

在入參User上添加了@Valid做校驗,在User類里屬性上實行實際的特定校驗。

例如在User的name屬性上加

@NotBlank

private String name;

 

全部參數校驗如下:

空檢查

@Null       驗證對象是否為null

@NotNull    驗證對象是否不為null, 無法查檢長度為0的字符串

@NotBlank 檢查約束字符串是不是Null還有被Trim的長度是否大於0,只對字符串,且會去掉前后空格.

@NotEmpty 檢查約束元素是否為NULL或者是EMPTY.

 

Booelan檢查

@AssertTrue     驗證 Boolean 對象是否為 true 

@AssertFalse    驗證 Boolean 對象是否為 false 

 

長度檢查

@Size(min=, max=) 驗證對象(Array,Collection,Map,String)長度是否在給定的范圍之內 

@Length(min=, max=)驗證注解的元素值長度在min和max區間內

日期檢查

@Past           驗證 Date 和 Calendar 對象是否在當前時間之前 

@Future     驗證 Date 和 Calendar 對象是否在當前時間之后 

@Pattern    驗證 String 對象是否符合正則表達式的規則

 

數值檢查,建議使用在Stirng,Integer類型,不建議使用在int類型上,因為表單值為“”時無法轉換為int,但可以轉換為Stirng為"",Integer為null

@Min(value=””)            驗證 Number 和 String 對象是否大等於指定的值 

@Max(value=””)             驗證 Number 和 String 對象是否小等於指定的值 

@DecimalMax(value=值) 被標注的值必須不大於約束中指定的最大值. 這個約束的參數是一個通過BigDecimal定義的最大值的字符串表示.小數存在精度

@DecimalMin(value=值) 被標注的值必須不小於約束中指定的最小值. 這個約束的參數是一個通過BigDecimal定義的最小值的字符串表示.小數存在精度

@Digits     驗證 Number 和 String 的構成是否合法 

@Digits(integer=,fraction=)驗證字符串是否是符合指定格式的數字,interger指定整數精度,fraction指定小數精度。

 

@Range(min=, max=) 檢查數字是否介於min和max之間.

@Range(min=10000,max=50000,message="range.bean.wage")

private BigDecimal wage;

 

@Valid 遞歸的對關聯對象進行校驗, 如果關聯對象是個集合或者數組,那么對其中的元素進行遞歸校驗,如果是一個map,則對其中的值部分進行校驗.(是否進行遞歸驗證)

@CreditCardNumber信用卡驗證

@Email  驗證是否是郵件地址,如果為null,不進行驗證,算通過驗證。

@ScriptAssert(lang=,script=, alias=)

@URL(protocol=,host=,port=,regexp=, flags=)

 

@Validated

@Valid是對javabean的校驗,如果想對使用@RequestParam方式接收參數方式校驗使用@Validated

使用@Validated的步驟:

第一步:定義全局異常,讓該全局異常處理器能處理所以驗證失敗的情況,並返回給前台失敗提示數據。如下,該類不用在任何xml里配置。
import javax.validation.ValidationException;

import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
@Component
public class GlobalExceptionHandler {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}

@ExceptionHandler
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handle(ValidationException exception) {
System.out.println("bad request, " + exception.getMessage());
return "bad request, " + exception.getMessage();
}
}
第二步。在XXController.java頭上添加@Validated,然后在@RequestParam后台使用上面介紹的驗證注解,比如@NotBlank,@Rank.

如下:

@Controller
@RequestMapping("/test")
@Validated
public class TestController extends BaseController {

@RequestMapping(value = "testValidated", method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Object testValidated(@RequestParam(value = "pk", required = true) @Size(min = 1, max = 3) String pk,
@RequestParam(value = "age", required = false) @Range(min = 1, max = 3) String age) {
try {
return "pk:" + pk + ",age=" + age;
} catch (Throwable t) {

return buildFailure("消息列表查詢失敗");
}
}
}

當入非法參數是,會被全局處理器攔截到,(Spring切面編程方式),如果參數非法即刻給前台返回錯誤數據。

測試:http://127.0.0.1:8080/TestValidate/test/testValidated?pk=2&age=12

返回:


注意

@Valid是使用hibernateValidation.jar做校驗

@Validated是只用springValidator校驗機制使用

gitHub下載地址


@Validated與@RequestBody結合使用時,在接口方法里要增加@Valid。例如:

public Object edit(@Valid @RequestBody AddrRo addrRo) {.....}

14.@RequestBody

@RequestBody(required=true)

:有個默認屬性required,默認是true,當body里沒內容時拋異常。

application/x-www-form-urlencoded:窗體數據被編碼為名稱/值對。這是標准的編碼格式。這是默認的方式
multipart/form-data:窗體數據被編碼為一條消息,頁上的每個控件對應消息中的一個部分。二進制數據傳輸方式,主要用於上傳文件

注意:必需使用POST方式提交參數,需要使用ajax方式請求,用Fiddler去模擬post請求不能。

引用jar包:

Spring相關jar包。

以及

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

dispatchServlet-mvc.xml配置
第一種,直接配置MappingJackson2HttpMessageCoverter:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
</property>
</bean>

第二種:<mvc:annotation-driven/> 就不用配置上面bean,默認會配好。

   Ajax請求:

function testRequestBody() {
var o = {"status":9};
jQuery.ajax({
type: "POST",
url: "http://127.0.0.1:8080/TestValidate/test/testValid",
xhrFields:{
withCredentials:true
},
data: JSON.stringify(o),
contentType: "application/json",
dataType: "json",
async: false,
success:function (data) {
console.log(data);
},

error: function(res) {
console.log(res);
}
});
}

后台XXXcontroller.java:

@RequestMapping(value="/ testValid ",method=RequestMethod.POST)
@ResponseBody
public Object setOrderInfo(@RequestBody InfoVO infoVO,HttpServletRequest request, HttpServletResponse response){
InfoVO cVo = getInfoVo(infoVO);
return "success";
}
開發時,不是報415,就是400錯誤,頭都大了。還是細節沒做到位,注意下面幾個要點:

Content-Type必需是application/json

需要jackson-databind.jar

<mvc:annotation-driven/>要配置或直接配置bean

XXXController.jar在post方式接收數據

最最重要的,使用ajax以post方式請求。不能用Fiddler模擬,不然會出錯。

 


15.@CrossOrigin

是Cross-Origin ResourceSharing(跨域資源共享)的簡寫

   作用是解決跨域訪問的問題,在Spring4.2以上的版本可直接使用。在類上或方法上添加該注解

例如:

@CrossOrigin
public class TestController extends BaseController {

XXXX

}
如果失效則可能方法沒解決是GET還是POST方式,指定即可解決問題。

 


16.@RequestParam

作用是提取和解析請求中的參數。@RequestParam支持類型轉換,類型轉換目前支持所有的基本Java類型

@RequestParam([value="number"], [required=false])  String number 

將請求中參數為number映射到方法的number上。required=false表示該參數不是必需的,請求上可帶可不帶。

 

 

17. @PathVariable,@RequestHeader,@CookieValue,@RequestParam, @RequestBody,@SessionAttributes, @ModelAttribute;
@PathVariable:處理requet uri部分,當使用@RequestMapping URI template 樣式映射時, 即someUrl/{paramId}, 這時的paramId可通過 @Pathvariable注解綁定它傳過來的值到方法的參數上

例如:

@Controller
@RequestMapping("/owners/{a}")
public class RelativePathUriTemplateController {
@RequestMapping("/pets/{b}")
public void findPet(@PathVariable("a") String a,@PathVariable String b, Model model) {
// implementation omitted
}
}

@RequestHeader,@CookieValue: 處理request header部分的注解

將頭部信息綁定到方法參數上:

@RequestMapping("/test")
public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,
@RequestHeader("Keep-Alive")long keepAlive) {

//...

}

//將cookie里JSESSIONID綁定到方法參數上

@RequestMapping("/test")
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {

//...

}

@RequestParam,  @RequestBody: 處理request body部分的注解,已經介紹過,不用介紹了。
@SessionAttributes,@ModelAttribute:處理attribute類型是注解。XXXX

 

 

18.@Scope

配置bean的作用域。

@Controller

@RequestMapping("/test")

@Scope("prototype")

public class TestController {

 

 

}

默認是單例模式,即@Scope("singleton"),

singleton:單例,即容器里只有一個實例對象。

prototype:多對象,每一次請求都會產生一個新的bean實例,Spring不無法對一個prototype bean的整個生命周期負責,容器在初始化、配置、裝飾或者是裝配完一個prototype實例后,將它交給客戶端,由程序員負責銷毀該對象,不管何種作用域,容器都會調用所有對象的初始化生命周期回調方法,而對prototype而言,任何配置好的析構生命周期回調方法都將不會被調用

request:對每一次HTTP請求都會產生一個新的bean,同時該bean僅在當前HTTP request內有效

web.xml增加如下配置:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
session:該針對每一次HTTP請求都會產生一個新的bean,同時該bean僅在當前HTTP session內有效。也要在web.xml配置如下代碼:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
global session:作用不大,可不用管他。

 


19.@ResponseStatus

@ResponseStatus用於修飾一個類或者一個方法,修飾一個類的時候,一般修飾的是一個異常類,當處理器的方法被調用時,@ResponseStatus指定的code和reason會被返回給前端。value屬性是http狀態碼,比如404,500等。reason是錯誤信息

當修改類或方法時,只要該類得到調用,那么value和reason都會被添加到response里

例如:

@ResponseStatus(value=HttpStatus.FORBIDDEN, reason="出現了錯誤")
public class UserException extends RuntimeException{

XXXXX
}


當某處拋出UserException時,則會把value和reason返回給前端。

@RequestMapping("/testResponseStatus")
public String testResponseStatus(int i){
if(i==0)
throw new UserNotMatchException();
return "hello";
}

修改方法:

@ControllerAdvice
@Component
public class GlobalExceptionHandler {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}

@ExceptionHandler
@ResponseBody
@ResponseStatus(value=HttpStatus.BAD_REQUEST,reason="哈哈")
public String handle(ValidationException exception) {
System.out.println("bad request, " + exception.getMessage());
return "bad request, " + exception.getMessage();
}
}

結果如下:

 

正如上面所說,該方法得到調用,不論是否拋異常,都會把value和reason添加到response里。

總結:@ResponseStatus是為了在方法或類得到調用時將指定的code和reason添加到response里返前端,就像服務器常給我們報的404錯誤一樣,我們可以自己指定高逼格錯誤提示。

 

 

20. @RestController

@RestController = @Controller + @ResponseBody。

是2個注解的合並效果,即指定了該controller是組件,又指定方法返回的是String或json類型數據,不會解決成jsp頁面,注定不夠靈活,如果一個Controller即有SpringMVC返回視圖的方法,又有返回json數據的方法即使用@RestController太死板。

靈活的作法是:定義controller的時候,直接使用@Controller,如果需要返回json可以直接在方法中添加@ResponseBody

 

 

21.@ControllerAdvice

官方解釋是:It is typically used todefine@ExceptionHandler,

 @InitBinder, and@ModelAttribute methods that apply to all@RequestMapping methods

意思是:即把@ControllerAdvice注解內部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法應用到所有的 @RequestMapping注解的方法。非常簡單,不過只有當使用@ExceptionHandler最有用,另外兩個用處不大。

@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(SQLException.class)
@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR,reason=”sql查詢錯誤”)
@ResponseBody
public ExceptionResponse handleSQLException(HttpServletRequest request, Exception ex) {
String message = ex.getMessage();
return ExceptionResponse.create(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
}
}

即表示讓Spring捕獲到所有拋出的SQLException異常,並交由這個被注解的handleSQLException方法處理,同時使用@ResponseStatus指定了code和reason寫到response上,返回給前端。

 


22.元注解包括  @Retention @Target @Document @Inherited四種

元注解是指注解的注解,比如我們看到的ControllerAdvice注解定義如下。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
XXX
}

@Retention: 定義注解的保留策略:

@Retention(RetentionPolicy.SOURCE)   //注解僅存在於源碼中,在class字節碼文件中不包含

@Retention(RetentionPolicy.CLASS)     //默認的保留策略,注解會在class字節碼文件中存在,但運行時無法獲得,

@Retention(RetentionPolicy.RUNTIME)  //注解會在class字節碼文件中存在,在運行時可以通過反射獲取到

 

@Target:定義注解的作用目標:

@Target(ElementType.TYPE)   //接口、類、枚舉、注解

@Target(ElementType.FIELD) //字段、枚舉的常量

@Target(ElementType.METHOD) //方法

@Target(ElementType.PARAMETER) //方法參數

@Target(ElementType.CONSTRUCTOR)  //構造函數

@Target(ElementType.LOCAL_VARIABLE)//局部變量

@Target(ElementType.ANNOTATION_TYPE)//注解

@Target(ElementType.PACKAGE) ///包   

 由以上的源碼可以知道,他的elementType 可以有多個,一個注解可以為類的,方法的,字段的等等

 

@Document:說明該注解將被包含在javadoc中

 

@Inherited:說明子類可以繼承父類中的該注解

 

比如@Valid注解定義是

 

 

 

表示該注解只能用在方法,屬性,構造函數及方法參數上。該注意會被編譯到class里可通過反射得到。

 

 

23.@RequestMapping

處理映射請求的注解。用於類上,表示類中的所有響應請求的方法都是以該地址作為父路徑。有6個屬性。

1、 value, method:
value:指定請求的實際地址,指定的地址可以是URI Template 模式;
method:指定請求的method類型, GET、POST、PUT、DELETE等;
比如:
@RequestMapping(value = "/testValid", method = RequestMethod.POST)
@ResponseBody
public Object testValid(@RequestBody @Valid Test test,BindingResult result, HttpServletRequest request, HttpServletResponse response) {
XXX
}

value的uri值為以下三類:
A) 可以指定為普通的具體值;如@RequestMapping(value ="/testValid")
B)  可以指定為含有某變量的一類值;如@RequestMapping(value="/{day}")
C) 可以指定為含正則表達式的一類值;如@RequestMapping(value="/{textualPart:[a-z-]+}.{numericPart:[\\d]+}")  可以匹配../chenyuan122912請求。
 

2、 consumes,produces:
consumes: 指定處理請求的提交內容類型(Content-Type),例如@RequestMapping(value = "/test", consumes="application/json")處理application/json內容類型

produces:    指定返回的內容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回;

 

3 params、headers:
params: 指定request中必須包含某些參數值是,才讓該方法處理。

例如:

@RequestMapping(value = "/test", method = RequestMethod.GET, params="name=chenyuan")
public void findOrd(String name) {
// implementation omitted
}

僅處理請求中包含了名為“name”,值為“chenyuan”的請求.

 

headers: 指定request中必須包含某些指定的header值,才能讓該方法處理請求。

@RequestMapping(value = "/test", method = RequestMethod.GET, headers="Referer=www.baidu.com")
public void findOrd(String name) {
// implementation omitted
}

僅處理request的header中包含了指定“Refer”請求頭和對應值為“www.baidu.com”的請求

 

 

另贈spring提供的注解:

 

24. @GetMapping和@PostMapping

 @GetMapping(value = "page")等價於@RequestMapping(value = "page", method = RequestMethod.GET)

 @PostMapping(value = "page")等價於@RequestMapping(value = "page", method = RequestMethod.POST)




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM