spring註解們

component
Service
Repository
Controller
RequestBody
ResponseBody
RestController
Resource
Autowired & Qualifier
RequestMapping
PathVariable
RequestParam
Scheduled
Param
JsonAlias & JsonProperty
JSONType
JSONField
Scope
PostConstruct & PreDestroy

在類上加上註解後,這個時候Spring還不認識它,這個時候需要把這個bean交給Spring來管理。有兩種方式可以管理:

<!--基於註解的裝配-->
<!--方式一-->
<bean class="com.HelloWorld"/>

<!--方式二-->
<context:component-scan base-package="com"/>
or
<!--如果只想掃描包下的@Controller或其他內容,則設置use-default-filters屬性爲false-->
<context:component-scan base-package="com" user-default-filters="false">
    <context:include-filter type="regex" expression="com.tan.*"/>
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

@component

作用:
Component是一個元註解,帶此註解的類看爲組件,當使用基於註解的配置和類路徑掃描的時候,這些類就會被實例化
Component可以註解其他類註解,如:@Controller @Service @Repository @Aspect
把普通pojo實例化到spring容器中,相當於配置文件中的 <bean id="" class=""/>

位置:

屬性:
不指定bean的名稱,默認爲類名首字母小寫
指定bean的名稱@Component(“xxx”)

細節:

@Component("demo")
public class Demo(){}

ApplicationContext ctx  = new ClassPathXmlApplicationContext("beans.xml");
Demo demo = (Demo)ctx.getBean("xxx");

@Service

作用:
springvmc採用經典的三層分層控制結構 :業務層
服務,注入dao,用於標註服務層,主要用來進行業務的邏輯處理

位置:

屬性:
不指定bean的名稱,默認爲類名首字母小寫
指定bean的名稱@Service(“xxx”)


@Repository

作用:
springvmc採用經典的三層分層控制結構:持久層
用於標註數據訪問層,也可以說用於標註數據訪問組件,即DAO組件,實現dao訪問

位置:

屬性:
不指定bean的名稱,默認爲類名首字母小寫
指定bean的名稱@Repository(“xxx”)

細節:
先定義一個接口

public interface IIocDao{
    public void add();
}

然後實現類

//Dao層中定義了一些接口 表示將Dao類聲明爲bean
@Repository
public class IocDao implements IIocDao{
    public void add(){System.out.println("調用了Dao"); }
}

@Controller

作用:
springvmc採用經典的三層分層控制結構:控制層
使用它標記的類就是一個SpringMvc Controller對象,分發處理器會掃描使用該註解的類的方法,並檢測該方法是否使用了@RequestMapping註解。Controller只是定義了一個控制器類,而使用@RequestMapping註解的方法纔是處理請求的處理器。
@controller 控制器(注入服務)

位置:

細節:

@Controller
public class HelloWorld{
	@RequestMapping(value="/demo")
	public String printHello() {
		return "hello";
	}

    @Autowried
    private IocSerevce service;
    public void add(){service.add(); }
}

@RequestBody

示例詳細說明: 一定要看!
https://blog.csdn.net/justry_deng/article/details/80972817

作用:
@RequestBody主要用來接收前端傳遞給後端的json字符串中的數據的(請求體中的數據的);GET方式無請求體,所以使用@RequestBody接收數據時,前端不能使用GET方式提交數據,而是用POST方式進行提交。在後端的同一個接收方法裏,@RequestBody與@RequestParam()可以同時使用,@RequestBody最多隻能有一個,而@RequestParam()可以有多個。

位置:
形參列表

屬性:
當同時使用@RequestParam()和@RequestBody時,@RequestParam()指定的參數可以是普通元素、數組、集合、對象等等(即:當,@RequestBody 與@RequestParam()可以同時使用時,原SpringMVC接收參數的機制不變,只不過RequestBody 接收的是請求體裏面的數據;而RequestParam接收的是key-value裏面的參數,所以它會被切面進行處理從而可以用普通元素、數組、集合、對象等接收)。即:如果參數時放在請求體中,傳入後臺的話,那麼後臺要用@RequestBody才能接收到;如果不是放在請求體中的話,那麼後臺接收前臺傳過來的參數時,要用@RequestParam來接收,或則形參前什麼也不寫也能接收。

如果參數前寫了@RequestParam(xxx),那麼前端必須有對應的xxx名字纔行(不管其是否有值,當然可以通 過設置該註解的required屬性來調節是否必須傳),如果沒有xxx名的話,那麼請求會出錯,報400。

如果參數前不寫@RequestParam(xxx)的話,那麼就前端可以有可以沒有對應的xxx名字纔行,如果有xxx名的話,那麼就會自動匹配;沒有的話,請求也能正確發送。

這裏與feign消費服務時不同;feign消費服務時,如果參數前什麼也不寫,那麼會被默認是@RequestBody的。

細節:
如果後端參數是一個對象,且該參數前是以@RequestBody修飾的,那麼前端傳遞json參數時,必須滿足以下要求:

  • 後端@RequestBody註解對應的類在將HTTP的輸入流(含請求體)裝配到目標類(即:@RequestBody後面的類)時,會根據json字符串中的key來匹配對應實體類的屬性,如果匹配一致且json中的該key對應的值符合(或可轉換爲),實體類的對應屬性的類型要求時,會調用實體類的setter方法將值賦給該屬性。
  • json字符串中,如果value爲"“的話,後端對應屬性如果是String類型的,那麼接受到的就是”",如果是後端屬性的類型是Integer、Double等類型,那麼接收到的就是null。
  • json字符串中,如果value爲null的話,後端對應收到的就是null。
  • 如果某個參數沒有value的話,在傳json字符串給後端時,要麼乾脆就不把該字段寫到json字符串中;要麼寫value時, 必須有值,null 或"“都行。千萬不能有類似"stature”:,這樣的寫法,如:
{
	"stature":,             // 錯誤
	"age":null,             // 正確
	"name":""               // 正確
}

@RequestBody與前端傳過來的json數據的匹配規則
聲明:根據不同的Content-Type等情況,Spring-MVC會採取不同的HttpMessageConverter實現來進行信息轉換解析。下面介紹的是最常用的:前端以Content-Type 爲application/json,傳遞json字符串數據;後端以@RequestBody模型接收數據的情況。

解析json數據大體流程概述:
Http傳遞請求體信息,最終會被封裝進com.fasterxml.jackson.core.json.UTF8StreamJsonParser中(提示:Spring採CharacterEncodingFilter設置了默認編碼爲UTF-8),然後在public class BeanDeserializer extends BeanDeserializerBase implements java.io.Serializable中,通過public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException方法進行解析


@ResponseBody

作用:
@ResponseBody的作用其實是將java對象轉爲json格式的數據。
@ResponseBody 表示該方法的返回結果直接寫入 HTTP response body 中,一般在異步獲取數據時使用【也就是AJAX】,在使用 @RequestMapping後,返回值通常解析爲跳轉路徑,但是加上 @ResponseBody 後返回結果不會被解析爲跳轉路徑,而是直接寫入 HTTP response body 中。 比如異步獲取 json 數據,加上 @ResponseBody 後,會直接返回 json 數據。@RequestBody 將 HTTP 請求正文插入方法中,使用適合的 HttpMessageConverter 將請求體寫入某個對象。當方法上面沒有寫ResponseBody,底層會將方法的返回值封裝爲ModelAndView對象。

假如是字符串則直接將字符串寫到客戶端,假如是一個對象,此時會將對象轉化爲json串然後寫到客戶端。這裏需要注意的是,如果返回對象,按utf-8編碼。如果返回String,默認按iso8859-1編碼,頁面可能出現亂碼。因此在註解中我們可以手動修改編碼格式,例如@RequestMapping(value="/cat/query",produces=“text/html;charset=utf-8”),前面是請求的路徑,後面是編碼格式。

位置:
通常使用在控制層(controller)的方法上
controller類上

屬性:

@ResponseBody
@RequestMapping("/login.do")
public Object login(@RequestBody User loginUuser, HttpSession session) {
	user = userService.checkLogin(loginUser);
	session.setAttribute("user", user);
	return new JsonResult(user);
}

細節:
在使用此註解之後不會再走視圖處理器,而是直接將數據寫入到輸入流中,他的效果等同於通過response對象輸出指定格式的數據。


@RestController

@Controller和@RestController的區別?
作用:
Spring中@RestController的作用等同於@Controller + @ResponseBody。

位置:

屬性:

  1. 如果只是使用@RestController註解Controller,則Controller中的方法無法返回jsp頁面,或者html,配置的視圖解析器 InternalResourceViewResolver不起作用,返回的內容就是Return 裏的內容。
  2. 如果需要返回到指定頁面,則需要用 @Controller配合視圖解析器InternalResourceViewResolver纔行。
  3. 如果需要返回JSON,XML或自定義mediaType內容到頁面,則需要在對應的方法上加上@ResponseBody註解。

@Resource

作用:
@Resource(name=“XXX”)//默認按name注入,可以通過name和type屬性進行選擇性注入,如名稱無找到則通過類型注入
如果name屬性一旦指定,就只會按照名稱進行裝配

位置:
字段,setter方法

屬性:
@Resource的作用相當於@Autowired,只不過@Autowired按byType自動注入,而@Resource默認按 byName自動注入罷了。@Resource有兩個屬性是比較重要的,分是name和type,Spring將@Resource註解的name屬性解析爲bean的名字,而type屬性則解析爲bean的類型。所以如果使用name屬性,則使用byName的自動注入策略,而使用type屬性時則使用byType自動注入策略。如果既不指定name也不指定type屬性,這時將通過反射機制使用byName自動注入策略。

細節:
@Resource 由jdk提供
@Resource裝配順序
  1. 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常
  2. 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
  3. 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
  4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退爲一個原始類型進行匹配,如果匹配則自動裝配;


@Autowired & @Qualifier

作用:
@Autowired 默認是按照byType進行注入的,如果發現找到多個bean,則,又按照byName方式比對,如果還有多個,則報出異常。
@Autowired也可以手動指定按照byName方式注入,使用@Qualifier標籤,例如:
@Autowired () @Qualifier ( “baseDao” ) //一般作爲@Autowired()的修飾用

位置:
@Autowired 可以對成員變量、方法以及構造函數進行註釋,而 @Qualifier 的標註對象是成員變量、方法入參、構造函數入參。

屬性:

細節:
@Autowired 由spring提供
@Autowired默認情況下必須要求依賴對象必須存在,如果要允許null值,可以設置它的required屬性爲false,如:@Autowired(required=false)


@RequestMapping

作用:
使用@RequestMapping 註解映射請求路徑
類級別的註解負責將一個特定(或符合某種模式)的請求路徑映射到一個控制器上,同時通過方法級別的註解來細化映射,即
根據特定的HTTP請求方法(GET、POST 方法等)、HTTP請求中是否攜帶特定參數等條件,將請求映射到匹配的方法上

位置:
類,方法

屬性:
映射單個URL@RequestMapping("")@RequestMapping(value="")
映射多個URL@RequestMapping({"",""})@RequestMapping(value={"",""})
路徑開頭是否加斜槓/均可,建議加上,如:@RequestMapping("/hello")

RequestMapping註解有六個屬性,下面我們把她分成三類進行說明。

1、 value, method;
value: 指定請求的實際地址,指定的地址可以是URI Template 模式;
method: 指定請求的method類型, GET、POST、PUT、DELETE等;

2、 consumes,produces;
consumes: 指定處理請求的提交內容類型(Content-Type),例如application/json, text/html;
produces: 指定返回的內容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回;

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

細節:
@RequestMapping 一共有五種映射方式:
1、標準URL 映射
@RequestMapping("/hello")@RequestMapping({"/hello","/world"})

2、Ant 風格的 URL 映射

通配符 說明
? 匹配任何單字符
* 匹配任意數量的字符(含 0 個)
** 匹配任意數量的目錄(含 0 個)

例如:

1@RequestMapping("/?/hello/")2@RequestMapping("/*/hello")3@RequestMapping("/**/hello")

3、佔位符URL 映射
URL 中可以通過一個或多個 {} 佔位符映射
例如:@RequestMapping("/user/{userId}/show")
可以通過@PathVariable("") 註解將佔位符中的值綁定到方法參數上

/**
* 如果 URL 中的 userId 是純數字,那麼使用 @PathVariable
* 做綁定時,可以根據自己的需求將方法參數類型設置爲 Long、Integer、String
*/
@RequestMapping("/user/{userId}/show")
public ModelAndView show(@PathVariable("userId") Long userId) {
	// 創建 ModelAndView 對象,並設置視圖名稱
	ModelAndView mv = new ModelAndView("show");
	// 添加模型數據
	mv.addObject("msg", "User ID:" + userId);
	return mv;
}

注意:@PathVariable("") 不能簡寫爲 @PathVariable。因爲在正常編譯時,Java 類反射對象不包含方法的參數名稱。如果在編
譯時將Debug 打開(javac -debug=no),方法的參數名稱纔會記錄到類中,此時才能簡寫,但不建議簡寫。

4、限制請求方法的URL 映射
在HTTP 請求中最常用的請求方法是 GET、POST,還有其他的一些方法,如:DELET、PUT、HEAD 等
限制請求方法,例如:@RequestMapping(value="/hello", method=RequestMethod.POST) 如需限制多個請求方法,以大括號包圍,逗號隔開即可,例如:method={RequestMethod.GET,RequestMethod.POST}

5、限制請求參數的URL 映射
限制請求參數來映射URL,例如:@RequestMapping(value="/user/show", params="userId")即請求中必須帶有userId 參數參數的限制規則如下:

1)params="userId"              //請求參數中必須包含 userId2)params="!userId"             //請求參數中不能包含 userId3)params="userId!=1"           //請求參數中必須包含 userId,但不能爲 14)params={"userId","userName"} //必須包含 userId 和 userName 參數

//可以通過@RequestParam("") 註解將請求參數綁定到方法參數上
@RequestMapping(value="/user/show",params="userId")
public ModelAndView show(@RequestParam("userId") Long userId) {
	// 創建 ModelAndView 對象,並設置視圖名稱
	ModelAndView mv = new ModelAndView("show");
	// 添加模型數據
	mv.addObject("msg", "User ID:" + userId);
	return mv;
}

要注意@PathVariable("") 和 @RequestParam("") 的不同:
@PathVariable("") 是將 URL 中佔位符處的值綁定到方法參數上
@RequestParam("") 是將 URL 後的請求參數綁定到方法參數上


@PathVariable

作用:
@PathVariable 映射 URL 綁定的佔位符,帶佔位符的 URL 是 Spring3.0 新增的功能,該功能在SpringMVC 向 REST 目標挺進發展過程中具有里程碑的意義
@PathVariable 可以將 URL 中佔位符參數綁定到控制器處理方法的入參中:URL 中的 {xxx} 佔位符可以通過@PathVariable(“xxx“) 綁定到操作方法的入參中。

位置:
方法形參

屬性:
@PathVariable只支持一個屬性value,類型是爲String,代表綁定的屬性名稱。默認不傳遞時,綁定爲同名的形參。 應用時,在@RequestMapping請求路徑中,將需要傳遞的參數用花括號{}括起來,然後,通過@PathVariable(“參數名稱”)獲取URL中對應的參數值。如果@PathVariable標明參數名稱,則參數名稱必須和URL中參數名稱一致。

//@PathVariable可以用來映射URL中的佔位符到目標方法的參數中
	@RequestMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable("id") Integer id)
    {
        System.out.println("testPathVariable:"+id);
        return SUCCESS;
    }
    
//@Description @PathVariable未標註參數名稱,則被註解參數名必須後URL中的一致
//URI 模板 “/owners/{ownerId}” 指定了一個名叫 ownerId的變量。當控制器處理這個請求時,ownerId的值被設置爲從 URI 中解析出來。比如,當請求 /viewUser/100 進來時,100 就是 ownerId的值
    @RequestMapping("/owners/{ownerId}")
    public Map<String, Object> viewUser2(@PathVariable Integer ownerId) {
        System.out.println("@PathVariable中 請求參數 ownerId = " + ownerId);
        return user;
    }

細節:
REST:即 Representational State Transfer。(資源)表現層狀態轉化。是目前最流行的一種互聯網軟件架構。它結構清晰、符合標準、易於理解、擴展方便,所以正得到越來越多網站的採用。
1) 資源(Resources):網絡上的一個實體,或者說是網絡上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的存在。可以用一個URI(統一資源定位符)指向它,每種資源對應一個特定的 URI 。要獲取這個資源,訪問它的URI就可以,因此 URI 即爲每一個資源的獨一無二的識別符。
2)表現層(Representation):把資源具體呈現出來的形式,叫做它的表現層(Representation)。比如,文本可以用 txt 格式表現,也可以用 HTML 格式、XML 格式、JSON 格式表現,甚至可以採用二進制格式。
3)狀態轉化(State Transfer):每發出一個請求,就代表了客戶端和服務器的一次交互過程。HTTP協議,是一個無狀態協議,即所有的狀態都保存在服務器端。因此,如果客戶端想要操作服務器,必須通過某種手段,讓服務器端發生“狀態轉化”(State Transfer)。而這種轉化是建立在表現層之上的,所以就是 “表現層狀態轉化”。具體說,就是 HTTP 協議裏面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET 用來獲取資源,POST 用來新建資源,PUT 用來更新資源,DELETE 用來刪除資源。


@RequestParam

作用:
將請求參數綁定到你控制器的方法參數上

位置:
方法形參

屬性:
@RequestParam(value=”參數名”, required=true/false, defaultValue=””)
1)value:請求參數名(必須配置)單一參數時,可簡化如下:

   /**
    * @Description:    url參數中的name必須要和@RequestParam("name")一致
    */
    @GetMapping("edit1")
    public String edit1(@RequestParam("userId") Integer userId, Model model) {
        System.out.println("*******************" + userId);
        model.addAttribute("userId" , userId);
        return "/admin/ronghe/rongheMobileList/edit";
    }
    /**
     * @Description:    url參數中的name必須要和@RequestParam("name")一致
     *                  參數名字不一樣
     */
    @GetMapping("edit2")
    public String edit2(@RequestParam("userId") Integer id, Model model) {
        System.out.println("*******************" + id);
        model.addAttribute("id" , id);
        return "/admin/ronghe/rongheMobileList/edit";
    }

(2)required:是否必需,默認爲 true,即 請求中必須包含該參數,如果沒有包含,將會拋出異常(可選配置)

   /**
    * @Description:    required = true時必須有參數id,否則會報錯
    *                  required = false時參數id可不傳,默認爲null,所以此時參數類型不能爲int
    */
    @GetMapping("edit3")
    public String edit3(@RequestParam(value = "id", required = true) Integer id, Model model) {
        System.out.println("*******************" + id);
        model.addAttribute("id" , id);
        return "/admin/ronghe/rongheMobileList/edit";
    }

(3)defaultValue:默認值,如果設置了該值,required 將自動設爲 false,無論你是否配置了required,配置了什麼值,都是 false;如果沒有傳該參數,就使用默認值(可選配置)

   /**
    * @Description:    設置defaultValue值時,required無論設置是何值,都默認爲false
    */
    @GetMapping("edit4")
    public String edit4(@RequestParam(value = "id", required = false, defaultValue = "10") Integer id, Model model) {
        System.out.println("*******************" + id);
        model.addAttribute("id" , id);
        return "/admin/ronghe/rongheMobileList/edit";
    }

細節:
如果@requestParam註解的參數是int類型,並且required=false,此時如果不傳參數的話,會報錯。原因是,required=false時,不傳參數的話,會給參數賦值null,這樣就會把null賦值給了int,因此會報錯。

 //接收的參數ids是數組
    @PostMapping("delete")
    @ResponseBody
    public RestResponse delete(@RequestParam(value = "ids[]", required = false) List<Long> ids) {
        if (null == ids) {
            return RestResponse.failure("ID不能爲空" );
        }
        for (Long id : ids) {
            rongheMobileListService.deleteById(id);
        }
        return RestResponse.success();
    }
    
//接收的參數data是Map<String, Object>
    @PostMapping("entry")
    @ResponseBody
    public RestResponse add(@RequestParam(value = "data[mobile]") String mobile,
                            @RequestParam(value = "data[pro]") String pro,
                            @RequestParam(value = "data[realTime]", required = false) String realTime,
                            @RequestParam(value = "data[sjbm]", required = false) String sjbm,
                            @RequestParam(value = "data[sjmc]", required = false) String sjmc,
                            @RequestParam(value = "data[mobBm]", required = false) String mobBm,
                            @RequestParam(value = "data[mobMc]", required = false) String mobMc,
                            @RequestParam(value = "data[orderId]", required = false) String orderId,
                            @RequestParam(value = "data[sn]") String sn,
                            @RequestParam(value = "data[bakMobile]", required = false) String bakMobile) {
 
        return RestResponse.success();
    }

@Scheduled

在線cron表達式生成器:http://cron.qqe2.com/
在線cron執行時間計算: https://tool.lu/crontab/

作用:
spring-quartz定時器註解

位置:
方法

屬性:
fixedRate 和 fixedDelay 的區別
fixedRate任務兩次執行時間間隔是任務的開始點,而 fixedDelay 的間隔是前次任務的結束與下次任務的開始。

// fixedDelay 
// 上一次執行完畢時間點之後多長時間再執行。
@Scheduled(fixedDelay = 5000) //上一次執行完畢時間點之後5秒再執行

// fixedDelayString 
// 與fixedDelay 意思相同,只是使用字符串的形式。唯一不同的是支持佔位符。
@Scheduled(fixedDelayString = "5000")  //上一次執行完畢時間點之後5秒再執行
//佔位符的使用(配置文件中有配置:time.fixedDelay=5000):
    @Scheduled(fixedDelayString = "${time.fixedDelay}")
    void testFixedDelayString() {
        System.out.println("Execute at " + System.currentTimeMillis());
    }
    
// fixedRate
// 上一次開始執行時間點之後多長時間再執行。
@Scheduled(fixedRate = 5000) //上一次開始執行時間點之後5秒再執行

// fixedRateString
// 與fixedRate 意思相同,只是使用字符串的形式。唯一不同的是支持佔位符。

// initialDelay
// 第一次延遲多長時間後再執行。
@Scheduled(initialDelay=1000, fixedRate=5000) //第一次延遲1秒後執行,之後按fixedRate的規則每5秒執行一次

// initialDelayString
// 與initialDelay 意思相同,只是使用字符串的形式。唯一不同的是支持佔位符。

配置方法:
1)在xml里加入task的命名空間

xmlns:task="http://www.springframework.org/schema/task"   
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd  

2)啓用註解驅動的定時任務

<task:annotation-driven scheduler="myScheduler"/>

3)配置定時任務的線程池
推薦配置線程池,若不配置多任務下會有問題。

<task:scheduler id="myScheduler" pool-size="5"/>  

4)寫我們的定時任務
@Scheduled註解爲定時任務,cron表達式裏寫執行的時機

import org.springframework.scheduling.annotation.Scheduled;  
import org.springframework.stereotype.Component;   
@Component  
public class quartzDemo{  
       @Scheduled(cron="0/10 * *  * * ? ")   //每10秒執行一次       
       public void demo(){ System.out.println("10s exec on time...");}      
}    

cron
在這裏插入圖片描述
Cron格式中特殊字符說明
在這裏插入圖片描述
注意:
LW:這兩個字符可以連用,表示在某個月最後一個工作日,即最後一個星期五。
#:用於確定每個月第幾個星期幾,只能出現在DayofMonth域。例如在4#2,表示某月的第二個星期三。


@Param

作用:
@Param是MyBatis所提供的(org.apache.ibatis.annotations.Param),作爲Dao層的註解,作用是用於傳遞參數,從而可以與SQL中的的字段名相對應,一般在2=<參數數<=5時使用最佳。

位置:
dao類方法入參

屬性:

//在userDAO類中有這麼一個函數:
public User selectByNameAndPwd(@Param("userName") String name,@Param("Password") String )

//在其對應的dao.xml文件中的查詢語句則爲:
select  username,password from user where username=${userName} and  password=${Password}

例子:
當只有一個參數,傳進去一個值也只有一個參數可以匹配。當存在多個參數時,傳進去的值就區分不開了,這時可以考慮用Map

public List<Role> findRoleByMap(Map<String, Object> parameter);

xml 配置

<select id="findRoleByMap" parameterType="map" resultType="role">
    SELECT id,name FROM t_role
    WHERE roleName=#{roleName}
    AND note=#{note}
<select>

測試文件

RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
Map<String, Object> parameter = new HashMap<>();
parameter.put("roleName", "劍士");
parameter.put("note", "決戰紫禁之巔");
List<Role> roles = roleMapper.findRolesByMap(parameter);

使用@Param
修改接口

public List<Role> findRoleByAnnotation(@Param("roleName") String roleName, @Param("note") String note);

這樣就可以直接傳入對應的值了。當然也可以使用Java Bean來傳遞多個參數,定義一個POJO

public class RoleParam {
    private String roleName;
    private String note;
}

接口變爲:

public List<Role> findRoleByBean(RoleParam role);

這樣對應的xml文件與1處的區別就在於id和parameterType發生了變化,id對應的方法和parameterType對應該類的權限定名。
而使用更多的場景可能是這樣的,對應多個POJO

public List<Role> findRoleByMix(@Param("roleP") RoleParam role, @Param("permissionP") PermissionParam permission);

xml 注意此時並不需要寫出parameterType屬性,Mybatis會進行自動搜索。

<select id="findRoleByMix" resultType="role">
    SELECT id,name FROM t_role WHERE roleName=#{roleP.roleName} AND note=#{rolep.note} AND level=#{permissionP.level}
<select>

細節:
在不使用@Param註解的時候,函數的參數只能爲一個,並且在查詢語句取值時只能用#{},且其所屬的類必須爲Javabean,而使用@Param註解則可以使用多個參數,在查詢語句中使用時可以使用#{}或者${}
@Param和@RequestParam沒有關係


@JsonAlias & @JsonProperty

給出Controller中的測試類:
在這裏插入圖片描述

給出模型中的屬性(setter/getter方法沒截出來):
在這裏插入圖片描述
使用postman測試一下,示例:
在這裏插入圖片描述
在這裏插入圖片描述

全面的結論:
結論①:@JsonAlias註解,實現:json轉模型時,使json中的特定key能轉化爲特定的模型屬性;但是模型轉json時,
對應的轉換後的key仍然與屬性名一致,見:上圖示例中的name字段的請求與響應。
以下圖進一步說明:
在這裏插入圖片描述
此時,json字符串轉換爲模型時,json中key爲Name或爲name123或爲name的都能識別。

結論②:@JsonProperty註解,實現:json轉模型時,使json中的特定key能轉化爲指定的模型屬性;同樣的,模
型轉json時,對應的轉換後的key爲指定的key,見:示例中的motto字段的請求與響應。
以下圖進一步說明:
在這裏插入圖片描述
此時,json字符串轉換爲模型時,key爲MOTTO的能識別,但key爲motto的不能識別。

結論③:@JsonAlias註解需要依賴於setter、getter,而@JsonProperty註解不需要。
結論④:在不考慮上述兩個註解的一般情況下,key與屬性匹配時,默認大小寫敏感。
結論⑤:有多個相同的key的json字符串中,轉換爲模型時,會以相同的幾個key中,排在最後的那個key的值給模
型屬性複製,因爲setter會覆蓋原來的值。見示例中的gender屬性。
結論⑥:後端@RequestBody註解對應的類在將HTTP的輸入流(含請求體)裝配到目標類(即:@RequestBody後面
的類)時,會根據json字符串中的key來匹配對應實體類的屬性,如果匹配一致且json中的該key對應的值
符合(或可轉換爲)實體類的對應屬性的類型要求時,會調用實體類的setter方法將值賦給該屬性。


@JSONType

作用:
定製序列化JSON

位置:

屬性:
放在實體類中就會只裝配列舉的字段

@JSONType(includes = {"name","sex"})      //只裝配 name, sex 
@JSONType(ignores ={"id", "sex"})         // 忽略 id , sex
@JSONType(orders={"id", "name", "sex"})   // 按照順序裝配

@JSONField

作用:
改變JSON輸出的屬性

位置:
方法(method),屬性(field)以及方法中的參數(parameter)

屬性:
JSONField中的name屬性用來指定JSON串中key的名稱

// @JSONField作用在Field時,其name不僅定義了輸入key的名稱,同時也定義了輸出的名稱。
public class Person {
    @JSONField(name = "name") // 注意觀察生成的JSON串中name和age的區別
    private String name;
    @JSONField(name = "AGE")
    private String age;

    public String getName() { return name; }
    public void setName(String name) {this.name = name; }
    public String getAge() {return age;}
    public void setAge(String age) {this.age = age;}
}

// @JSONField也可以直接作用在get或set方法上
@JSONField(name = "name")
public String getName() {return name;}

@JSONField(name = "name")
public void setName(String name) {this.name = name;}

@JSONField(name = "AGE")
public String getAge() {return age;}

@JSONField(name = "AGE")
public void setAge(String age) {this.age = age;}
// FastJson在進行操作時,是根據getter和setter的方法進行的,並不是依據Field進行。

demo

public class PersonTest {
    private Person person;

    /**
    * 初始化對象
    */
    @Before
    public void setUp() {
        person = new Person();
        person.setName("gyl");
        person.setAge("20");
    }

    @Test
    public void test() {
        String jsonStr = JSONObject.toJSONString(person);
        System.out.println("bean to json:" + jsonStr);
        person = JSONObject.toJavaObject(JSONObject.parseObject(jsonStr), Person.class);
        System.out.println("json to bean:" + person.getName());
    }
}
///////
Output:
bean to json:{"AGE":"20","name":"gyl"}
json to bean:gyl

JSONField默認支持的類型

public @interface JSONField {
    int ordinal() default 0;
    String name() default "";
    String format() default "";
    boolean serialize() default true;
    boolean deserialize() default true;
    SerializerFeature[] serialzeFeatures() default {};
    Feature[] parseFeatures() default {};
    String label() default "";
    boolean jsonDirect() default false;
    Class<?> serializeUsing() default Void.class;
    Class<?> deserializeUsing() default Void.class;
    String[] alternateNames() default {};
    boolean unwrapped() default false;
}

format規定日期格式

@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date date;

ordinal規定字段的順序

@JSONField(ordinal = 3)
private int f0;
@JSONField(ordinal = 2)
private int f1;
@JSONField(ordinal = 1)
private int f2;
//fastjson序列化⼀個java bean,是根據fieldName的字母序進⾏序列的你可以通過ordinal指定字段的順序。

serialize/deserialize指定字段不序列化

@JSONField(serialize=false)
public Date date;

@Scope

作用:
@Scope註解是springIoc容器中的一個作用域,在 Spring IoC 容器中具有以下幾種作用域:
基本作用域singleton(單例)、prototype(多例),Web 作用域(reqeust、session、globalsession),自定義作用域
@Scope(“singleton”)

位置:

屬性:
a.singleton單例模式 – 全局有且僅有一個實例
b.prototype原型模式 – 每次獲取Bean的時候會有一個新的實例
c.request – request表示該針對每一次HTTP請求都會產生一個新的bean,同時該bean僅在當前HTTP request內有效
d.session – session作用域表示該針對每一次HTTP請求都會產生一個新的bean,同時該bean僅在當前HTTP session內有效
e.globalsession – global session作用域類似於標準的HTTP Session作用域,不過它僅僅在基於portlet的web應用中才有意義

直接在bean對象方法上增加@Scope註解就可以如下:
@Scope註解默認的singleton實例,singleton實例的意思不管你使用多少次在springIOC容器中只會存在一個實例,演示如下只打印了一次創建實例:

細節:
幾乎90%以上的業務使用singleton單實例就可以,所以spring默認的類型也是singleton,singleton雖然保證了全局是一個實例,對性能有所提高,但是如果實例中有非靜態變量時,會導致線程安全問題,共享資源的競爭

當設置爲prototype時:每次連接請求,都會生成一個bean實例,也會導致一個問題,當請求數越多,性能會降低,因爲創建的實例,導致GC頻繁,gc時長增加

Spring 只幫我們管理單例模式 Bean 的完整生命週期,對於 prototype 的 bean ,Spring 在創建好交給使用者之後則不會再管理後續的生命週期。

@PostConstruct & @PreDestroy

瞭解即可,詳細:https://blog.csdn.net/tuesdayma/article/details/80532867

PostConstruct相當於init-method,使用在方法上,當Bean初始化時執行。
PreDestroy相當於destory-method,使用在方法上,當Bean銷燬時執行。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
 
@Component
public class MyUtils {
 
    private static MyUtils taticInstance = new MyUtils();
 
    @Autowired
    private MyMethorClassService myService;
 
    @PostConstruct
    public void init(){
        staticInstance.myService = myService;
    }
    @PreDestroy
    public void destory(){
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章