1. 程式人生 > >Spring入門(十三):Spring MVC常用註解講解

Spring入門(十三):Spring MVC常用註解講解

在使用Spring MVC開發Web應用程式時,控制器Controller的開發非常重要,雖然說檢視(JSP或者是Thymeleaf)也很重要,因為它才是直接呈現給使用者的,不過由於現在前端越來越重要,很多公司都開始採用前後端分離的開發模式,所以我們暫時可以將精力放在開發控制器上。

使用Spring MVC開發控制器主要使用以下7個註解:

  1. @Controller
  2. @RequestMapping
  3. @ResponseBody
  4. @RequestParam
  5. @PathVariable
  6. @RequestBody
  7. @RestController

接下來,我們依次講解每個註解的使用方法。

1. @Controller

先回顧下上篇部落格中新建的簡單控制器HelloController:

package chapter05.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HelloController {
    @RequestMapping(value = "index", method = RequestMethod.GET)
    public String hello() {
        // 這裡返回的邏輯檢視名
        return "index";
    }
}

這裡@Controller註解的作用是用來宣告控制器,它的原始碼如下所示:

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    String value() default "";
}

這裡值得注意的是,@Controller註解使用了@Component註解,而@Component註解我們並不陌生,它用來宣告一個Bean。

雖然有些書中說可以把@Controller註解替換為@Component註解,執行沒有差別,只是表意性差一點,但是如果你將上面程式碼中的@Controller註解修改為@Component註解,然後重新打包釋出到Tomcat,會發現訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/index時,報如下所示的404錯誤:

@Component註解還原為@Controller註解,然後重新打包釋出到Tomcat,再次訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/index時,訪問正常:

所以,在Spring MVC中宣告控制器時,推薦使用@Controller註解。

注意事項:程式設計師在閱讀技術書籍時,要多思考,多嘗試,因為書籍中講解的,很可能是錯的。

2. @RequestMapping

@RequestMapping註解用來對映Web請求,它有2種使用形式:

  1. 應用在方法級別,如上面的程式碼中展示的那樣。
  2. 應用在類級別,當控制器在類級別上新增@RequestMapping註解時,這個註解會應用到控制器的所有處理器方法上,處理器方法上的@RequestMapping註解會對類級別上的@RequestMapping註解的宣告進行補充。

@RequestMapping註解常用的3個引數如下所示:

  1. value:指定對映的URL地址,如index
  2. method:指定對映的請求型別,如GET請求、POST請求等
  3. produces:指定返回的response的媒體型別和字符集,如application/json;charset=UTF-8。

指定method值時使用org.springframework.web.bind.annotation.RequestMethod列舉:

package org.springframework.web.bind.annotation;

public enum RequestMethod {
    GET,
    HEAD,
    POST,
    PUT,
    PATCH,
    DELETE,
    OPTIONS,
    TRACE;

    private RequestMethod() {
    }
}

指定produces值時一般使用org.springframework.http.MediaType類下的常量:

public static final String APPLICATION_JSON_VALUE = "application/json";
public static final MediaType APPLICATION_JSON_UTF8 = valueOf("application/json;charset=UTF-8");
public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";

為了更好的理解,我們在HelloController類上新增如下程式碼:

package chapter05.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/hello")
public class HelloController {
    @RequestMapping(value = "index", method = RequestMethod.GET)
    public String hello() {
        // 這裡返回的邏輯檢視名
        return "index";
    }
}

重新打包並部署到Tomcat中,此時的訪問地址從之前的http://localhost:8080/spring-action-1.0-SNAPSHOT/index變成了http://localhost:8080/spring-action-1.0-SNAPSHOT/hello/index,如下所示:

@RequestMapping註解的value屬性還支援接受一個String型別的陣列,如下所示:

@RequestMapping({"/hello", "/index"})
public class HelloController {
    // 省略其它程式碼
}

此時也可以通過地址http://localhost:8080/spring-action-1.0-SNAPSHOT/index/index進行訪問:

3. @ResponseBody

在上面的程式碼中,我們的方法是返回邏輯檢視名index,然後由檢視解析器最終找到執行時的/WEB-INF/classes/views/index.jsp檢視,但有時我們不需要返回一個頁面,而是直接返回資料給到前端。

此時我們可以使用@ResponseBody註解,該註解可以放在返回值前或者方法上,用於將返回值放在response體內,而不是返回一個頁面。

為了更好的理解,我們新建個DemoAnnoController控制器如下所示:

package chapter05.controller;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/anno")
public class DemoAnnoController {
    @RequestMapping(value = "/index", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
    public @ResponseBody
    String index(HttpServletRequest request) {
        return "url:" + request.getRequestURI() + " can access";
    }
}

重新打包並部署到Tomcat中,訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/index,效果如下所示:

也可以將@ResponseBody註解放在方法上,如下所示:

@RequestMapping(value = "/index", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String index(HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access";
}

4. @RequestParam

@RequestParam註解用於接收URL中的引數資訊。

為了更好的理解 ,我們在DemoAnnoController控制器中新增如下方法:

@RequestMapping(value = "/requestParam", method = RequestMethod.GET, produces = "text/plain;charset=UTF-8")
@ResponseBody
public String passRequestParam(@RequestParam("id") Long id, @RequestParam("name") String name, HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access,id: " + id + ",name=" + name;
}

重新打包並部署到Tomcat中,訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam?id=1&name=zwwhnly ,效果如下所示:

注意事項:上面示例中,Url中的引數名稱和方法中的變數名稱完全一致,所以可以省略掉@RequestParam註解,不過為了程式碼的易讀性,建議保留@RequestParam註解。

如果不傳遞引數,訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam,則會提示如下資訊:

或者只傳遞其中1個引數,訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam?id=1,則會提示如下資訊:

由此也說明,使用了@RequestParam註解的引數,在Url中必須傳遞。

不過,@RequestParam註解提供了defaultValue屬性,可以給引數指定預設值,比如我們給引數id設定預設值1,給引數name設定預設值zwwhnly,然後訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam,效果如下所示:

或者訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam?id=2,效果如下所示:

不過,還是有一個異常場景需要注意,就是Url中傳遞的引數和方法中定義的引數型別不匹配,比如我們將id的值傳錯,訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/requestParam?id=zwwhnly&name=zwwhnly,會看到如下報錯資訊:

5. @PathVariable

@PathVariable註解也是用於接收URL中的引數資訊,不過和@RequestParam註解稍有不同。

@PathVariable註解用於解析Url中的路徑引數,如https://www.cnblogs.com/zwwhnly/中的zwwhnly部分,而@RequestParam註解用於解析Url中的查詢引數,如https://i.cnblogs.com/posts?page=2中的page部分。

為了更好的理解 ,我們在DemoAnnoController控制器中新增如下方法:

@RequestMapping(value = "/pathvar/{str}", produces = "text/plain;charset=UTF-8")
public @ResponseBody
String demoPathVar(@PathVariable("str") String str, HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access,str: " + str;
}

重新打包並部署到Tomcat中,訪問地址http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/pathvar/zwwhnly ,效果如下所示:

注意事項:如果@PathVariable註解中指定value屬性的話,它會假設佔位符的名稱與方法的引數名相同。

因為這裡方法的引數名正好與佔位符的名稱相同,所以我們可以去掉@PathVariable註解的value屬性:

@RequestMapping(value = "/pathvar/{str}", produces = "text/plain;charset=UTF-8")
public @ResponseBody
String demoPathVar(@PathVariable String str, HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access,str: " + str;
}

6. @RequestBody

@RequestBody註解允許request的引數在request體中,而不是直接連結在地址後面,該註解放在引數前。

為了更好的理解 ,我們在DemoAnnoController控制器中新增如下方法:

@RequestMapping(value = "/obj", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String passObj(@RequestBody DemoObj demoObj, HttpServletRequest request) {
    return "url:" + request.getRequestURI() + " can access,demoObj id:" + demoObj.getId() +
            " demoObj name:" + demoObj.getName();
}

重新打包並部署到Tomcat中,然後使用Postman工具呼叫介面http://localhost:8080/spring-action-1.0-SNAPSHOT/anno/passObj,效果如下所示:

7. @RestController

@RestController是一個組合註解,它組合了@Controller註解和@ResponseBody註解,原始碼如下所示:

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Controller;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    String value() default "";
}

因此,如果某個控制器中所有的方法都只是返回資料而不是頁面的話,就可以使用@RestController註解。

為了更好的理解 ,我們舉個具體的示例。

首先,在pom.xml中新增如下依賴,用於物件和json之間的轉換:

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

然後新建控制器DemoRestController如下所示:

package chapter05.controller;

import chapter05.model.DemoObj;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/rest")
public class DemoRestController {
    @RequestMapping(value = "/getjson", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DemoObj getjson(@RequestBody DemoObj demoObj) {
        return new DemoObj(demoObj.getId(), demoObj.getName());
    }
}

因為使用@RestController註解,相當於同時使用了@Controller註解和@ResponseBody註解,所以上面的程式碼等價於下面的程式碼:

package chapter05.controller;

import chapter05.model.DemoObj;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
@ResponseBody
@RequestMapping("/rest")
public class DemoRestController {
    @RequestMapping(value = "/getjson", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DemoObj getjson(@RequestBody DemoObj demoObj) {
        return new DemoObj(demoObj.getId(), demoObj.getName());
    }
}

重新打包並部署到Tomcat中,然後使用Postman工具呼叫介面http://localhost:8080/spring-action-1.0-SNAPSHOT/rest/getjson,效果如下所示:

8. 原始碼及參考

原始碼地址:https://github.com/zwwhnly/spring-action.git,歡迎下載。

Craig Walls 《Spring實戰(第4版)》

汪雲飛《Java EE開發的顛覆者:Spring Boot實戰》

9. 最後

歡迎掃碼關注微信公眾號:「申城異鄉人」,定期分享Java技術乾貨,讓我們一起進步。

相關推薦

Spring入門(十三)Spring MVC常用註解講解

在使用Spring MVC開發Web應用程式時,控制器Controller的開發非常重要,雖然說檢視(JSP或者是Thymeleaf)也很重要,因為它才是直接呈現給使用者的,不過由於現在前端越來越重要,很多公司都開始採用前後端分離的開發模式,所以我們暫時可以將精力放在開發控制器上。 使用Spring MVC開

Spring入門(一)Spring注入

概念 Spring注入是指在啟動Spring容器載入bean配置的時候,完成對變數的賦值行為 常用的兩種注入方式 設值注入 構造注入 設值注入 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns

Spring入門(五)Spring Bean Scope講解

1. 前情回顧 Spring入門(一):建立Spring專案 Spring入門(二):自動化裝配bean Spring入門(三):通過JavaConfig裝配bean Spring入門(四):使用Maven管理Spring專案 2. 什麼是Bean的Scope? Scope描述的是Spring容器是如何新

Spring入門(七)Spring Profile使用講解

1. 使用場景 在日常的開發工作中,我們經常需要將程式部署到不同的環境,比如Dev開發環境,QA測試環境,Prod生產環境,這些環境下的一些配置肯定是不一樣的,比如資料庫配置,Redis配置,RabbitMQ配置。 如果每次切換髮布環境,都需要修改配置重新構建的話,那對程式設計師來說將是噩夢,針對這種場景,S

Spring入門(十)Spring AOP使用講解

1. 什麼是AOP? AOP是Aspect Oriented Programming的縮寫,意思是:面向切面程式設計,它是通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。 可以認為AOP是對OOP(Object Oriented Programming 面向物件程式設計)的補充,主要使用在日誌

spring mvc常用註解的說明

control debug mvc ref this mediatype display 說明 tom 最近一段時間學習了springboot,所以熟悉一下mvc中常用的註解,這樣可以方便開發 簡介: @RequestMapping RequestMa

Spring MVC常用註解

常用註解 Controller 註解一個類表示控制器,Spring MVC會自動掃描標註了這個註解的類。 RequestMapping 請求路徑對映,可以標註類,也可以是方法,可以指定請求型別,預設不指定為全部接收。 RequestParam 放在引數前,

spring mvc常用註解@Component @Controller @Service @Repository

註解用了之後,會在*.xml檔案中大大減少配置量。以前我們每個Bean都得到配置檔案中配置關聯下。spring2.5後,引入了完整的annotation配置註解,使得我們的程式配置更簡單更容易維護。 @Component;@Controller;@Service;@Repo

Spring MVC常用註解的理解

因為工作中經常用到的註解,特此寫個部落格,記錄一下,方便自己和他人解決問題 NO.1 @requestMapping @requestMapping(name/value = {"/vip/list","/svip/list"}, method = {requestMeth

spring mvc常用註解詳解

1、@Controller 在SpringMVC 中,控制器Controller 負責處理由DispatcherServlet 分發的請求,它把使用者請求的資料經過業務處理層處理之後封裝成一個Model ,然後再把該Model 返回給對應的View 進行展示。在Spri

day39-Spring 08-Spring的AOP基於AspectJ的註解

ima spring mage 開發 技術 asp day3 cnblogs ring 基於AspectJ的註解的開發要重點掌握. day39-Spring 08-Spring的AOP:基於AspectJ的註解

《Java從入門到放棄》入門spring中IOC的註入姿勢

java ioc spring IOC到底是個什麽東東呢?控制反轉(Inversion of Control,英文縮寫為IoC),其實就是這個東東。你隨便百度一下就會得到比較書面的解釋:通過引入實現了IoC模式的IoC容器,即可由IoC容器來管理對象的生命周期、依賴關系等,從而使得應用程序的配置和

《01.Spring Boot連載Spring Boot入門介紹》

spring boot maven 1 Spring Boot的概述Spring Boot是開發者和Spring 本身框架的中間層,幫助開發者統籌管理應用的配置,提供基於實際開發中常見配置的默認處理(即習慣優於配置),簡化應用的開發,簡化應用的運維;總的來說,其目的Spring Boot就是為了對Ja

spring入門框架整體簡介

mil object web開發 spa tor 對象 j2ee 就是 cor 1:spring的基本框架主要包含六大模塊:DAO、ORM、AOP、JEE、WEB、CORE   DAO:(Data Access Object) 數據訪問對象,是一個面向對象的數據庫接口。  

Spring入門之五-------SpringIoC之通過註解實現

string類型 protected abstract 準備工作 @service urn 解決辦法 sin val 一、準備工作 創建一個Class註解@Configuration,如下例子: @Configuration // 該註解可理解為將當前class等同於一個

Spring第一天Spring的概述、SpringIOC入門(XML)、Spring的Bean管理、Spring屬性注入

以前也學習過Spring框架,不過好久沒用,當時學完也沒做什麼總結,都忘的差不多了,今天再從頭開始學習一遍。無論是SSH還是SSM都離不開Spring,所以Spring還是很重要的,對於一個想要從事JavaEE開發的人,一定要好好學習Spring框架。Spring的學習計劃如下: 第一

十三Spring Cloud 之Hystrix Dashboard

1. 簡介 Hystrix是Netflix解決自己業務不穩定性的一個限流容錯框架,可以幫助我們解決微服務架構體系中的限流、降級、熔斷等功能。提高系統穩定性,提供了完善的監控實現,並且Hystrix可

Sprng boot(十三)Spring boot 小技巧

初始化資料 使用jpa 在使用Spring boot jpa的情況下設定 spring.jpa.hibernate.ddl-auto 的屬性為 create 或 create-drop ,Spring boot啟動時預設會掃描classpath下面(專案一般是

Spring第二天Spring的IOC的註解方式、Spring的AOP開發(XML)

   Spring第二天繼續,今天要學習的是Spring的IOC的註解方式和Spring的AOP開發(XML) 目錄 1.Spring的IOC註解方式開發 1.1Spring的IOC註解開發入門 1.1.1建立Web專案引入Jar包 1.1.2引入Spri

Spring框架中Bean管理的常用註解

1. @Component:元件.(作用在類上)可以作用在任何一個類上 2. Spring中提供@Component的三個衍生註解:(功能目前來講是一致的) * @Controller -- 作用在WEB層(同樣可以使用@Component,因為@Controller是@Componen