1、JDK自帶(java.lang)
"@Deprecated 和 @Override" 類似,"@Documented, @Inherited, @Retention, @Target" 類似。
1.1 @ Override
若某個(gè)方法被 @Override 的標(biāo)注,則意味著該方法會(huì)覆蓋父類中的同名方法。如果有方法被 @Override 標(biāo)示,但父類中卻沒有"被 @Override 標(biāo)注"的同名方法,則編譯器會(huì)報(bào)錯(cuò)。
public class OverrideTest {
/**
* toString() 在java.lang.Object中定義;
* 因此,這里用 @Override 標(biāo)注是對的。
*/
@Override
public String toString(){
return "Override toString";
}
/**
* getString() 沒有在OverrideTest的任何父類中定義;
* 但是,這里卻用 @Override 標(biāo)注,因此會(huì)產(chǎn)生編譯錯(cuò)誤!
* 將 getString() 上面的 @Override注釋掉",即可解決該錯(cuò)誤。
*/
@Override
public String getString(){
return "get toString";
}
}
1.2 @Deprecated
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
/*
說明:
(01) @interface -- 它的用來修飾 Deprecated,意味著 Deprecated 實(shí)現(xiàn)了 java.lang.annotation.Annotation 接口;即 Deprecated 就是一個(gè)注解。 (02) @Documented -- 它的作用是說明該注解能出現(xiàn)在 javadoc 中。
(03) @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定 Deprecated 的策略是 RetentionPolicy.RUNTIME。這就意味著,編譯器會(huì)將Deprecated 的信息保留在 .class 文件中,并且能被虛擬機(jī)讀取。
(04) @Deprecated 所標(biāo)注內(nèi)容,不再被建議使用。
*/
}
比如,若某個(gè)方法被@Deprecated標(biāo)注,則該方法不在便建議使用,如果再用或者重寫該方法,編譯器會(huì)有相應(yīng)的警告信息:
public class DeprecatedTest {
// @Deprecated 修飾 getString1(),表示 它是建議不被使用的函數(shù)
@Deprecated
private static void getString1(){
System.out.println("Deprecated Method");
}
private static void getString2(){
System.out.println("Normal Method");
}
// Date是日期/時(shí)間類。java已經(jīng)不建議使用該類了
private static void testDate() {
Date date = new Date(113, 8, 25);
System.out.println(date.getYear());
}
// Calendar是日期/時(shí)間類。java建議使用Calendar取代Date表示"日期/時(shí)間"
private static void testCalendar() {
Calendar cal = Calendar.getInstance();
System.out.println(cal.get(Calendar.YEAR));
}
public static void main(String[] args) {
getString1(); //建議不再使用 getString1();
getString2();//沒有被 @Deprecated 標(biāo)注,它的顯示正常;
testDate(); //java 已經(jīng)建議不再使用;
testCalendar();//調(diào)用了 Calendar 的 API 來操作日期/時(shí)間,java 建議用 Calendar 取代 Date。因此,操作 Calendar 不會(huì)產(chǎn)生 warning。
}
}
1.3 @Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
/*
說明:
(01) @interface -- 它的用來修飾 Inherited,意味著 Inherited 實(shí)現(xiàn)了 java.lang.annotation.Annotation 接口;即 Inherited 就是一個(gè)注解。
(02) @Documented -- 它的作用是說明該注解能出現(xiàn)在 javadoc 中。
(03) @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定 Inherited 的策略是 RetentionPolicy.RUNTIME。這就意味著,編譯器會(huì)將 Inherited 的信息保留在 .class 文件中,并且能被虛擬機(jī)讀取。
(04) @Target(ElementType.ANNOTATION_TYPE) -- 它的作用是指定 Inherited 的類型是 ANNOTATION_TYPE。這就意味著,@Inherited 只能被用來標(biāo)注 "Annotation 類型"。
(05) @Inherited 的含義是,它所標(biāo)注的Annotation將具有繼承性。
*/
}
假設(shè),我們定義了某個(gè) Annotaion,它的名稱是 MyAnnotation,并且 MyAnnotation 被標(biāo)注為 @Inherited。現(xiàn)在,某個(gè)類 Base 使用了MyAnnotation,則 Base 具有了"具有了注解 MyAnnotation";現(xiàn)在,Sub 繼承了 Base,由于 MyAnnotation 是 @Inherited的(具有繼承性),所以,Sub 也 "具有了注解 MyAnnotation"。
/**
* 自定義的Annotation。
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Inheritable {
}
@Inheritable
class InheritableFather {
public InheritableFather() {
// InheritableBase是否具有 Inheritable Annotation
System.out.println("InheritableFather:"+InheritableFather.class.isAnnotationPresent(Inheritable.class));
}
}
/**
* InheritableSon 類只是繼承于 InheritableFather,
*/
public class InheritableSon extends InheritableFather {
public InheritableSon() {
super(); // 調(diào)用父類的構(gòu)造函數(shù)
// InheritableSon類是否具有 Inheritable Annotation
System.out.println("InheritableSon:"+InheritableSon.class.isAnnotationPresent(Inheritable.class));
}
public static void main(String[] args) {
InheritableSon is = new InheritableSon();
}
}
運(yùn)行結(jié)果:
InheritableFather:true
InheritableSon:true
現(xiàn)在,我們對 InheritableSon.java 進(jìn)行修改:注釋掉 "Inheritable 的 @Inherited 注解"。
InheritableFather:true
InheritableSon:false
對比上面的兩個(gè)結(jié)果,我們發(fā)現(xiàn):當(dāng)注解 Inheritable 被 @Inherited 標(biāo)注時(shí),它具有繼承性。否則,沒有繼承性。
1.4 @SuppressWarnings
/*
說明:
(01) @interface -- 它的用來修飾 SuppressWarnings,意味著 SuppressWarnings 實(shí)現(xiàn)了 java.lang.annotation.Annotation 接口;即 SuppressWarnings 就是一個(gè)注解。
(02) @Retention(RetentionPolicy.SOURCE) -- 它的作用是指定 SuppressWarnings 的策略是 RetentionPolicy.SOURCE。這就意味著,SuppressWarnings 信息僅存在于編譯器處理期間,編譯器處理完之后 SuppressWarnings 就沒有作用了。
(03) @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -- 它的作用是指定 SuppressWarnings 的類型同時(shí)包括TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE。
TYPE 意味著,它能標(biāo)注"類、接口(包括注釋類型)或枚舉聲明"。
FIELD 意味著,它能標(biāo)注"字段聲明"。
METHOD 意味著,它能標(biāo)注"方法"。
PARAMETER 意味著,它能標(biāo)注"參數(shù)"。
CONSTRUCTOR 意味著,它能標(biāo)注"構(gòu)造方法"。
LOCAL_VARIABLE 意味著,它能標(biāo)注"局部變量"。
(04) String[] value(); 意味著,SuppressWarnings 能指定參數(shù)
(05) SuppressWarnings 的作用是,讓編譯器對"它所標(biāo)注的內(nèi)容"的某些警告保持靜默。
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
例如,"@SuppressWarnings(value={"deprecation", "unchecked"})" 表示對"它所標(biāo)注的內(nèi)容"中的 "SuppressWarnings 不再建議使用警告"和"未檢查的轉(zhuǎn)換時(shí)的警告"保持沉默。示例如下:
/*
SuppressWarnings 常用的關(guān)鍵字的表格
deprecation -- 使用了不贊成使用的類或方法時(shí)的警告
unchecked -- 執(zhí)行了未檢查的轉(zhuǎn)換時(shí)的警告,例如當(dāng)使用集合時(shí)沒有用泛型 (Generics) 來指定集合保存的類型。
fallthrough -- 當(dāng) Switch 程序塊直接通往下一種情況而沒有 Break 時(shí)的警告。
path -- 在類路徑、源文件路徑等中有不存在的路徑時(shí)的警告。
serial -- 當(dāng)在可序列化的類上缺少 serialVersionUID 定義時(shí)的警告。
finally -- 任何 finally 子句不能正常完成時(shí)的警告。
all -- 關(guān)于以上所有情況的警告。
boxing -- 禁止與裝箱/拆箱操作相關(guān)的警告
cast -- 強(qiáng)制轉(zhuǎn)換以抑制與強(qiáng)制轉(zhuǎn)換操作相關(guān)的警告
dep-ann -- 用于抑制相對于已棄用注釋的警告
hiding -- 隱藏以抑制相對于隱藏變量的本地警告
incomplete-switch -- 在switch語句(enum案例)中,incomplete-switch用來抑制相對于丟失條目的警告
javadoc -- 禁止與javadoc警告相關(guān)的警告
nls -- 使用nls來抑制相對于非nls字符串的警告。
null -- 空值來抑制相對于空值分析的警告
rawtypes -- 拒絕與使用原始類型相關(guān)的警告
resource -- 用于抑制與使用類型為Closeable的資源相關(guān)的警告的資源
restriction --限制禁止與使用不鼓勵(lì)或禁止引用相關(guān)的警告
static-access --靜態(tài)訪問,抑制相對于不正確的靜態(tài)訪問的警告
static-method --靜態(tài)方法,用于抑制相對于可以聲明為靜態(tài)的方法的警告
super -- 超級-來抑制相對于在沒有超級調(diào)用的情況下重寫方法的警告
synthetic-access-- 用于抑制相對于內(nèi)部類的未優(yōu)化訪問的警告的合成訪問
sync-override -- 在覆蓋同步方法時(shí),由于缺少同步而取消警告
unchecked -- 未選中以抑制與未選中操作相關(guān)的警告
unqualified-field-access-- 不限定字段訪問來抑制與字段訪問不限定相關(guān)的警告
unused -- 不常用來抑制與未使用代碼和死代碼相關(guān)的警告
*/
public class SuppressWarningTest {
//沒有使用 @SuppressWarnings(value={"deprecation"}) , 而 Date 屬于 java 不再建議使用的類。因此,調(diào)用 Date 的 API 時(shí),會(huì)產(chǎn)生警告。
//@SuppressWarnings(value={"deprecation"})
public static void doSomething() {
Date date = new Date(113, 8, 26);
System.out.println(date);
}
public static void main(String[] args) {
doSomething();
}
}
1.5 @SafeVarargs
堆污染警告。
出現(xiàn):使用泛型+可變參數(shù)的時(shí)候就會(huì)出現(xiàn)堆污染警告。
@SafeVarargs
public static<T> T useVarargs(T... args){
return args.length > 0?args[0]:null;
}
@Test
public void testSafeVarargs(){
System.out.println(useVarargs(Arrays.asList("s1","s2")));
}
1.6 @FunctionalInterface
在Java SE 8中引入的 ,申明某個(gè)接口是函數(shù)式接口(函數(shù)式接口是就只含有一個(gè)抽象方法的接口)。加上該注解,當(dāng)你寫的接口不符合函數(shù)式接口定義的時(shí)候,編譯器會(huì)報(bào)錯(cuò)。該注解只是提醒編譯器去檢查該接口是否僅包含一個(gè)抽象方法。
@FunctionalInterface
interface GreetingService {
void sayMessage(String message);
}
//那么就可以使用Lambda表達(dá)式來表示該接口的一個(gè)實(shí)現(xiàn)(注:JAVA 8 之前一般是用匿名類實(shí)現(xiàn)的):
//GreetingService greetService1 = message -> System.out.println("Hello " + message);
2、第三方注解
2.1 基礎(chǔ)注解1(spring-context下org.springframework.stereotype)
2.1.1 @Component組合注解
用于標(biāo)注各個(gè)層級的注解,注入到spring容器管理。
@Controller @Service @Repository @Configuration 都是@Component組合注解,只是區(qū)分層級關(guān)系:
- @Controller 標(biāo)注于控制層
- @Service 標(biāo)注于業(yè)務(wù)層
- @Repository 標(biāo)注于dao持久層
- @Configuration 標(biāo)注于配置層
- @Component 泛指組件,當(dāng)組件不好歸類時(shí)可用
2.1.1 @Bean
@Bean等價(jià)于<Bean></Bean>,添加的bean的id為方法名。
@Configuration
public class AppConfig {
//@bean 也可以依賴其他任意數(shù)量的bean,如果TransferService 依賴 AccountRepository,我們可以通過方法參數(shù)實(shí)現(xiàn)這個(gè)依賴
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
這個(gè)配置就等同于之前在xml里的配置:
@Configuration可理解為用spring的時(shí)候xml里面的<beans>標(biāo)簽
@Bean可理解為用spring的時(shí)候xml里面的<bean>標(biāo)簽
<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl" depends-on="accountRepository"/>
</beans>
2.2 基礎(chǔ)注解2(spring-web下org.springframework.web.bind.annotation)
2.2.1 @ResponseBody
被注解的方法返回的結(jié)果直接寫入 HTTP 響應(yīng)正文(ResponseBody)中。
一般在異步獲取數(shù)據(jù)時(shí)使用,通常是在使用 @RequestMapping 后,返回值通常解析為跳轉(zhuǎn)路徑,加上 @Responsebody 后返回結(jié)果不會(huì)被解析為跳轉(zhuǎn)路徑,而是直接寫入HTTP 響應(yīng)正文中。
/***********************例子一*******************************/
@RequestMapping(value="user/login")
@ResponseBody
//將ajax(datas)發(fā)出的請求寫入U(xiǎn)ser對象中,返回json對象響應(yīng)回去
public User login(User user) {
User user = new User();
user.setUserid(1);
user.setUsername("MrF");
user.setStatus("1");
return user ;
}
/***********************例子二*******************************/
@Controller
public class UserController {
@GetMapping("/hello")
@ResponseBody public String hello() {
return "hello spring";
}
}
2.2.2 @ RequestBody
將 HTTP 請求正文插入方法中,使用適合的 HttpMessageConverter 將請求體寫入某個(gè)對象。換句話就是:用于接收前端請求的Json參數(shù),并且封裝到對應(yīng)的JavaBean。
@RequestMapping(value = "user/login")
@ResponseBody
// 將ajax(datas)發(fā)出的請求寫入U(xiǎn)ser對象中
public User login(@RequestBody User user) {
// 這樣就不會(huì)再被解析為跳轉(zhuǎn)路徑,而是直接將user對象寫入 HTTP 響應(yīng)正文中
return user;
}
提交時(shí), 根據(jù)request header Content-Type的值來判斷:
- application/x-www-form-urlencoded -- 可選(GET,POST),必須(PUT)
GET,POST -- 這種情況的數(shù)據(jù)@RequestParam,@ModelAttribute也可以處理,當(dāng)然@RequestBody也能處理 - multipart/form-data -- 不能處理
即使用@RequestBody不能處理這種格式的數(shù)據(jù) - 其他格式 -- 必須
其他格式包括application/json,application/xml等。這些格式的數(shù)據(jù),必須使用@RequestBody來處理
2.2.3 @RequestMapping
用來處理請求地址映射的注解。
- @GetMapping = @RequestMapping(method = RequestMethod.GET)
- @PostMapping = @RequestMapping(method = RequestMethod.POST)
/**
RequestMapping注解有六個(gè)屬性,下面我們把她分成三類進(jìn)行說明。
1、value, method
value: 指定請求的實(shí)際地址,指定的地址可以是URI Template 模式(后面將會(huì)說明)
method:指定請求的method類型,GET、POST、PUT、DELETE等
2、consumes,produces
consumes: 指定處理請求的提交內(nèi)容類型(Content-Type),例如application/json, text/html;
produces: 指定返回的內(nèi)容類型,僅當(dāng)request請求頭中的(Accept)類型中包含該指定類型才返回;
3、params,headers
params:指定request中必須包含某些參數(shù)值是,才讓該方法處理。
headers:指定request中必須包含某些指定的header值,才能讓該方法處理請求。
*/
//用于類上,可以沒有
@RequestMapping(value = "/controllerDemo")
public class ControllerDemo {
// 用于方法上,必須有
@RequestMapping(value = "/methodDemo")
public String methodDemo() {
return "helloWorld";
}
}
2.2.4 @PathVariable、@RequestParam
用于接受前端url路徑參數(shù),通過路徑參數(shù)作為接口接受的參數(shù),Result風(fēng)格
區(qū)分:
- @RequestParam -- URL是這樣的:http://host:port/path?參數(shù)名=參數(shù)值
- @PathVariable -- URL是這樣的:http://host:port/path/參數(shù)值
//訪問路徑:localhost:8080/hello/1
@GetMapping("/hello/{id}")
public String func(@PathVariable String id) {
return id;
}
2.2.5 @RequestParam
用于接受前端提交的參數(shù)。
//訪問路徑:localhost:8080/hello?name=張三
@GetMapping("/hello")
/*
String value name別名
String name 請求參數(shù)對應(yīng)的屬性
boolean required 是否必傳
Stirng defaultValue 默認(rèn)值
*/
public String func(@RequestParam(name = "name", required = false, defaultValue = "張三") String name) {
return "OK";
}
2.2.6 @RestController
相當(dāng)于@ResponseBody + @Controller。
- Controller中的方法無法返回jsp頁面,返回的內(nèi)容就是Return 里的內(nèi)容。
2.3 persistence注解(javax.persistence)
2.3.1 @Entity,@Table,@Column
@Entity表明該類是實(shí)體類,并且使用默認(rèn)的orm規(guī)則,即class名即數(shù)據(jù)庫表中表名,class字段名即表中的字段名。如果class名和數(shù)據(jù)庫表中名字不一致就用@Table,如果class字段名和表中的字段名不一直就用@Column
@Column用來標(biāo)識(shí)實(shí)體類中屬性與數(shù)據(jù)表中字段的對應(yīng)關(guān)系
- name:被標(biāo)注字段在數(shù)據(jù)庫表中所對應(yīng)字段的名稱
- unique:表示該字段是否為唯一標(biāo)識(shí),默認(rèn)為false。也可以使用@Table標(biāo)記中的@UniqueConstraint。
- nullable:表示該字段是否可以為null值,默認(rèn)為true。
- insertable:表示在使用“INSERT”腳本插入數(shù)據(jù)時(shí),是否需要插入該字段的值。
- updatable:表示在使用“UPDATE”腳本插入數(shù)據(jù)時(shí),是否需要更新該字段的值。insertable和updatable屬性一般多用于只讀的屬性,例如主鍵和外鍵等。這些字段的值通常是自動(dòng)生成的。
- columnDefinition:表示創(chuàng)建表時(shí),該字段創(chuàng)建的SQL語句,一般用于通過Entity生成表定義時(shí)使用。(也就是說,如果DB中表已經(jīng)建好,該屬性沒有必要使用。)
- table:表示當(dāng)映射多個(gè)表時(shí),指定表的表中的字段。默認(rèn)值為主表的表名。
- length:表示字段的長度,當(dāng)字段的類型為varchar時(shí),該屬性才有效,默認(rèn)為255個(gè)字符。
- precision:和scaleprecision屬性和scale屬性表示精度,當(dāng)字段類型為double時(shí),precision表示數(shù)值的總長度,scale表示小數(shù)點(diǎn)所占的位數(shù)。
示例見2.3.2。
2.3.2 @Id,@Temporal,@GeneratedValue, @Generated
- @Id表名該字段是主鍵,如果要開啟自增主鍵就用@GeneratedValue。
- @Temporal幫Java的Date類型進(jìn)行格式化,一共有三種注解值:
-- @Temporal(TemporalType.DATE)— yyyy-MM-dd的 Date類型
-- @Temporal(TemporalType.TIME)—hh-MM-ss的 Date類型
-- @Temporal(TemporalType.TIMESTAMP)—yyyy-MM-dd hh:MM:ss”的 Date類型 - @Generated自動(dòng)生成:
-- generated= never 標(biāo)明此屬性值不是從數(shù)據(jù)庫中生成
-- generated默認(rèn)值是never
-- generated= insert 標(biāo)明此屬性值在insert的時(shí)候生成,但是不會(huì)在隨后的 update時(shí)重新生成
-- generated= always 標(biāo)明此屬性值在insert和update時(shí)都會(huì)被生成
@Entity
@Table(name = "batch")
public class Batch{
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Integer id;
//在插入的時(shí)候自動(dòng)賦值當(dāng)前時(shí)間
@Column(insertable = false)
@Temporal(TemporalType.TIMESTAMP)
@Generated(GenerationTime.INSERT)
private Date createdTime;
//自動(dòng)變化更新時(shí)間
@Temporal(TemporalType.TIMESTAMP)
@Column(insertable = false, updatable = false)
@Generated(GenerationTime.ALWAYS)
private Date updatedTime;
//在插入的時(shí)候自動(dòng)賦值1
@Column(insertable = false ,columnDefinition="Short default 1")
@Generated(GenerationTime.INSERT)
private Short status;
}
2.4 resteasy注解(jaxrs-api下javax.ws.rs)
resteasy 是java體系中比較成熟的rest框架,也是jax-rs規(guī)范的實(shí)現(xiàn)之一,dubbox的REST服務(wù)框架,就是采用的resteasy實(shí)現(xiàn)。
默認(rèn)情況下,resteasy使用jackson和jaxb來實(shí)現(xiàn)json及xml格式的序列化。應(yīng)用啟動(dòng)時(shí),會(huì)自動(dòng)掃描帶@Provider的包,找到最合適的provider。
這個(gè)可以用來做分布式,可以通過okhttp3協(xié)議來進(jìn)行交互。
2.4.1 @Path、@POST、@Produces、@Consumes、@Context
@Path("/td")
public interface PayIntegrationService {
@Path("/pay")
@POST
@Produces({ ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
@Consumes({ ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
public JsonResponse pay(@Context HttpServletRequest request);
}
2.5 validation注解(validation-api下javax.validation)
用于前端請求參數(shù)校驗(yàn),@Valid需要配合BindingResult使用,以及配合下面各種校驗(yàn)注解進(jìn)行使用:
- @Null 限制只能為null
- @NotNull 限制必須不為null
- @AssertFalse 限制必須為false
- @AssertTrue 限制必須為true
- @DecimalMax(value) 限制必須為一個(gè)不大于指定值的數(shù)字
- @DecimalMin(value) 限制必須為一個(gè)不小于指定值的數(shù)字
- @Digits(integer,fraction) 限制必須為一個(gè)小數(shù),且整數(shù)部分的位數(shù)不能超過integer,小數(shù)部分的位數(shù)不能超過fraction
- @Future 限制必須是一個(gè)將來的日期
- @Max(value) 限制必須為一個(gè)不大于指定值的數(shù)字
- @Min(value) 限制必須為一個(gè)不小于指定值的數(shù)字
- @Past 限制必須是一個(gè)過去的日期
- @Pattern(value) 限制必須符合指定的正則表達(dá)式
- @Size(max,min) 限制字符長度必須在min到max之間
- @Past 驗(yàn)證注解的元素值(日期類型)比當(dāng)前時(shí)間早
- @NotEmpty 驗(yàn)證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0)
- @NotBlank 驗(yàn)證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應(yīng)用于字符串且在比較時(shí)會(huì)去除字符串的空格
- @Email 驗(yàn)證注解的元素值是Email,也可以通過正則表達(dá)式和flag指定自定義的email格式
/**
* 接受前端的請求并且根據(jù)User實(shí)體類注解進(jìn)行校驗(yàn)
*/
@PostMapping("/hello/user")
public String hello(@Valid @RequestBody User user, BindingResult result) {
if (result.hasErrors()) {
result.getAllErrors().forEach(System.out::println);
}
System.out.println(user);
return "hello spring";
}
@Data
public class User {
@NotBlank(message = "用戶名不能為空")
private String username;
@NotBlank(message = "密碼名不能為空")
private String password;
}
2.6 lombok常用注解
傳送門:lombok安裝和基本使用介紹
2.7 tkMapper注解
沒用過,以后更新。
2.8 springboot常用注解
2.8.1 @ConfigurationProperties
將配置文件中配置的每一個(gè)屬性的值,映射到這個(gè)組件中。
**
* @ConfigurationProperties:
* prefix = "person":配置文件下面的所有屬性和類的屬性進(jìn)行一一映射
*
* 只有這個(gè)組件是容器中的組件,才能容器提供的@ConfigurationProperties功能;
*
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
配置文件:
person:
lastName: hello
age: 18
boss: false
birth: 2017/12/12
maps: {k1: v1,k2: 12}
lists:
- lisi
- zhaoliu
dog:
name: 小狗
age: 12
導(dǎo)入配置文件處理器,之后編寫配置就有提示了
<!--導(dǎo)入配置文件處理器,配置文件進(jìn)行綁定就會(huì)有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2.8.2 @MapperScan
掃描接口,放啟動(dòng)類上面
//掃描dao接口
@MapperScan("com.test.dao")
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
2.8.3 @ SpringBootApplication
SpringBootApplication啟動(dòng)時(shí)會(huì)默認(rèn)掃描主類當(dāng)前包及子包,如果需要掃描主類當(dāng)前包外的其他包就用@SpringBootApplication
//指定掃描的包
@SpringBootApplication(scanBasePackages = {"com.test"})
2.9 注入Bean的三個(gè)注解
@Autowired是spring自帶的,@Inject是JSR330規(guī)范實(shí)現(xiàn)的,@Resource是JSR250規(guī)范實(shí)現(xiàn)的,需要導(dǎo)入不同的包
@Autowired、@Inject用法基本一樣,不同的是@Autowired有一個(gè)request屬性
@Autowired、@Inject是默認(rèn)按照類型匹配的,@Resource是按照名稱匹配的
@Autowired如果需要按照名稱匹配需要和@Qualifier一起使用,@Inject和@Name一起使用
2.9.1 @Inject(javax.inject)
根據(jù)類型進(jìn)行自動(dòng)裝配的,默認(rèn)需要配置與變量名一致。如果需要按名稱進(jìn)行裝配,則需要配合@Named;
@Inject可以作用在變量、setter方法、構(gòu)造函數(shù)上
2.9.2 @Autowired ( org.springframework下sping-beans)
根據(jù)類型進(jìn)行自動(dòng)裝配的,名稱不一樣也沒事,如果需要按名稱進(jìn)行裝配,則需要配合@Qualifier;
@Autowired有個(gè)屬性為required,可以配置為false,如果配置為false之后,當(dāng)沒有找到相應(yīng)bean的時(shí)候,系統(tǒng)不會(huì)拋錯(cuò);
@Autowired可以作用在變量、setter方法、構(gòu)造函數(shù)上。
2.9.3 @Resource (jdk下rt.jar下的javax.annotation)
根據(jù)名稱進(jìn)行自動(dòng)裝配的,默認(rèn)需要配置與變量名一致,一般會(huì)指定一個(gè)name屬性。
@Resource可以作用在變量、setter方法上。
3、在反射中使用示例
/**
* Annotation在反射函數(shù)中的使用示例
*/
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String[] value() default "unknown";
}
/**
* Person類。它會(huì)使用MyAnnotation注解。
*/
class Person {
/**
* empty()方法同時(shí)被 "@Deprecated" 和 "@MyAnnotation(value={"a","b"})"所標(biāo)注
* (01) @Deprecated,意味著empty()方法,不再被建議使用
* (02) @MyAnnotation, 意味著empty() 方法對應(yīng)的MyAnnotation的value值是默認(rèn)值"unknown"
*/
@MyAnnotation
@Deprecated
public void empty(){
System.out.println("\nempty");
}
/**
* sombody() 被 @MyAnnotation(value={"girl","boy"}) 所標(biāo)注,
* @MyAnnotation(value={"girl","boy"}), 意味著MyAnnotation的value值是{"girl","boy"}
*/
@MyAnnotation(value={"girl","boy"})
public void somebody(String name, int age){
System.out.println("\nsomebody: "+name+", "+age);
}
}
public class AnnotationTest {
public static void main(String[] args) throws Exception {
// 新建Person
Person person = new Person();
// 獲取Person的Class實(shí)例
Class<Person> c = Person.class;
// 獲取 somebody() 方法的Method實(shí)例
Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});
// 執(zhí)行該方法
mSomebody.invoke(person, new Object[]{"lily", 18});
iteratorAnnotations(mSomebody);
// 獲取 somebody() 方法的Method實(shí)例
Method mEmpty = c.getMethod("empty", new Class[]{});
// 執(zhí)行該方法
mEmpty.invoke(person, new Object[]{});
iteratorAnnotations(mEmpty);
}
public static void iteratorAnnotations(Method method) {
// 判斷 somebody() 方法是否包含MyAnnotation注解
if(method.isAnnotationPresent(MyAnnotation.class)){
// 獲取該方法的MyAnnotation注解實(shí)例
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
// 獲取 myAnnotation的值,并打印出來
String[] values = myAnnotation.value();
for (String str:values)
System.out.printf(str+", ");
System.out.println();
}
// 獲取方法上的所有注解,并打印出來
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations){
System.out.println(annotation);
}
}
}
運(yùn)行結(jié)果:
somebody: lily, 18
girl, boy,
@cn.bcsoft.annotation.MyAnnotation(value=[girl, boy])
empty
unknown,
@cn.bcsoft.annotation.MyAnnotation(value=[unknown])
@java.lang.Deprecated()
參考文檔: