SpringMVC--基礎(chǔ)--注解(五)

一、@RequestMapping

通過 RequestMapping 注解可以定義不同的處理器映射規(guī)則。

二、 url 映射

定義 controller 方法對應(yīng)的 url,進行處理器映射使用。

@RequestMapping(value="/user")或@RequestMapping("/user)

value 的值是數(shù)組,可以將多個 url 映射到同一個方法

  1. 窄化請求映射
    在 class 上添加@RequestMapping(url)指定通用請求前綴,限制此類下的所有方法請求 url 必
    須以請求前綴開頭,通過此方法對 url 進行分類管理。
    如下:
// 放在類名上邊,設(shè)置請求前綴
@RequestMapping 
@Controller
@RequestMapping("/user")

方法名上邊設(shè)置請求映射 url:
@RequestMapping 放在方法名上邊,如下:

@RequestMapping("/list")

訪問地址為:/user/list

  1. 請求方法限定
    ◆ 限定 GET 方法
@RequestMapping(method = RequestMethod.GET)

如果通過 Post 訪問則報錯:

HTTP Status 405 - Request method 'POST' not supported

例如:

@RequestMapping(value="/user",method=RequestMethod.GET)

◆ 限定 POST 方法

@RequestMapping(method = RequestMethod.POST)

如果通過 GET 訪問則報錯:
HTTP Status 405 - Request method 'GET' not supported
◆ GET 和 POST 都可以

@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})

三、 controller 方法的返回值

  1. 返回 ModelAndView
    controller 方法中定義 ModelAndView 對象并返回,對象中可添加 model 數(shù)據(jù)、指定view。
  2. 返回 void
    在 controller 方法形參上可以定義 request 和 response,使用 request 或 response 指定響應(yīng)結(jié)果:
    A. 使用 request 轉(zhuǎn)向頁面,如下:
request.getRequestDispatcher("頁面路徑").forward(request, response);

B. 也可以通過 response 頁面重定向:

response.sendRedirect("url")

C. 也可以通過 response 指定響應(yīng)結(jié)果,例如響應(yīng) json 數(shù)據(jù)如下:

response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json 串");
  1. 返回字符串
    A. 邏輯視圖名
    controller 方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析為物理視圖地址。
//指定邏輯視圖名,經(jīng)過視圖解析器解析為jsp物理路徑:
/WEBINF/views/user/list.jsp
return "user/list";

B. Redirect 重定向
Contrller 方法返回結(jié)果重定向到一個 url 地址,如下商品修改提交后重定向到商品查詢方法,參數(shù)無法帶到商品查詢方法中。

// 重定向到 list 地址,request 無法帶過去
return "redirect:list";

redirect 方式相當(dāng)于“response.sendRedirect()”,轉(zhuǎn)發(fā)后瀏覽器的地址欄變?yōu)檗D(zhuǎn)發(fā)后的地址,因為轉(zhuǎn)發(fā)即執(zhí)行了一個新的 request 和 response。
由于新發(fā)起一個 request 原來的參數(shù)在轉(zhuǎn)發(fā)時就不能傳遞到下一個 url,如果要傳參數(shù)可以/user/list 后邊加參數(shù),如下:

/user/list?...&…..

C. forward 轉(zhuǎn)發(fā)
controller 方法執(zhí)行后繼續(xù)執(zhí)行另一個 controller 方法。

// 結(jié)果轉(zhuǎn)發(fā)到 list,request 可以帶過去
return "forward:list";

forward 方式相當(dāng)于

“request.getRequestDispatcher().forward(request,response)”

轉(zhuǎn)發(fā)后瀏覽器地址欄還是原來的地址。轉(zhuǎn)發(fā)并沒有執(zhí)行新的 request 和 response,而是和轉(zhuǎn)發(fā)前的請求共用一個 request 和 response。所以轉(zhuǎn)發(fā)前請求的參數(shù)在轉(zhuǎn)發(fā)后仍然可以讀取到。

四、參數(shù)綁定

處理器適配器在執(zhí)行 Handler 之前需要把 http 請求的 key/value 數(shù)據(jù)綁定到 Handler 方法形參數(shù)上。
spring 參數(shù)綁定過程

  1. 默認支持的類型
    直接在 controller 方法形參上定義下邊類型的對象,就可以使用這些對象。在參數(shù)綁定過程中,如果遇到下邊類型直接進行綁定。
    A. HttpServletRequest
    通過 request 對象獲取請求信息
    B. HttpServletResponse
    通過 response 處理響應(yīng)信息
    C. HttpSession
    通過 session 對象得到 session 中存放的對象
    D. Model/ModelMap
    ? 控制器類:
@RequestMapping("/testUser")
public String testUser(Model model,ModelMap map){
model.addAttribute("user", "張三");
map.addAttribute("date", new Date());
return "userShow";
}

? 頁面顯示:

<body>
${user }
${date }
</body>

ModelMap 是 Model 接口的實現(xiàn)類,通過 Model 或 ModelMap 向頁面?zhèn)鬟f數(shù)據(jù),如下:

//調(diào)用 service 查詢商品信息
Items item = itemService.findItemById(id);
model.addAttribute("item", item);

頁面通過${item.XXXX}獲取 item 對象的屬性值。
使用 Model 和 ModelMap 的效果一樣,如果直接使用 Model,springmvc 會實例化ModelMap。
注解適配器對 RequestMapping 標(biāo)記的方法進行適配,對方法中的形參會進行參數(shù)綁定,早期 springmvc 采用 PropertyEditor(屬性編輯器)進行參數(shù)綁定將 request 請求的參數(shù)綁定到方法形參上,3.X 之后 springmvc 就開始使用 Converter 進行參數(shù)綁定。

  1. 簡單類型
    當(dāng)請求的參數(shù)名稱和處理器形參名稱一致時會將請求參數(shù)與形參進行綁定。
    A. 整型
public String editItem(Model model,Integer id) throws Exception{
}

B. 字符串

public String editItem(Model model,String id) throws Exception{
}

C. 單精度/雙精度

public String editItem(Model model,Float id) throws Exception{
}

D. 布爾型

public String editItem(Model model,Boolean id) throws Exception{
}

處理器方法:

public String editItem(Model model,Integer id,Boolean status) throws Exception

請求 url:

http://localhost:8080/springmvc_mybatis/item/editItem.action?id=2&status=false

說明:對于布爾類型的參數(shù),請求的參數(shù)值為 true 或 false。
E. 使用@RequestParam 常用于處理簡單類型的綁定。
value:參數(shù)名字,即入?yún)⒌恼埱髤?shù)名字,如 value=“itemid”表示請求的參數(shù)區(qū)中的名字為 itemid 的參數(shù)的值將傳入;
required:是否必須,默認是 true,表示請求中一定要有相應(yīng)的參數(shù),否則將報;
TTP Status 400 - Required Integer parameter 'XXXX' is not present
defaultValue:默認值,表示如果請求中沒有同名參數(shù)時的默認值
定義如下:

public String editItem(@RequestParam(value="item_id",required=true) String id) {
}

形參名稱為 id,但是這里使用 value=" itemid"限定請求的參數(shù)名為 itemid,所以頁面?zhèn)鬟f參數(shù)的名必須為 itemid。
注意:如果請求參數(shù)中沒有 item_id 將跑出異常:
HTTP Status 500 - Required Integer parameter 'itemid' is not present
這里通過 required=true 限定 itemid 參數(shù)為必需傳遞,如果不傳遞則報 400 錯誤,可以使用 defaultvalue 設(shè)置默認值,即使 required=true 也可以不傳 itemid 參數(shù)值。

  1. pojo綁定
    將pojo對象中的屬性名于傳遞進來的屬性名對應(yīng),如果傳進來的參數(shù)名稱和對象中的屬性名稱一致則將參數(shù)值設(shè)置在pojo對象中
    A. 頁面定義如下;
<input type="text" name="name"/>
<input type="text" name="price"/>

B. Contrller方法定義如下:

@RequestMapping("/editItemSubmit")
    public String editItemSubmit(Items items)throws Exception{
    System.out.println(items);
}

請求的參數(shù)名稱和pojo的屬性名稱一致,會自動將請求參數(shù)賦值給pojo的屬性。

  1. 包裝pojo
    如果采用類似struts中對象.屬性的方式命名,需要將pojo對象作為一個包裝對象的屬性,action中以該包裝對象作為形參。
    A. 包裝對象定義如下:
Public class QueryVo {
private Items items;
}

B. 頁面定義:
<input type="text" name="items.name" />
<input type="text" name="items.price" />
C. Controller方法定義如下:

public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItems());
}
  1. 自定義參數(shù)綁定
    根據(jù)業(yè)務(wù)需求自定義日期格式進行參數(shù)綁定。
    A. 自定義Converter
public class CustomDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return simpleDateFormat.parse(source);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

B. 配置方式1

    <mvc:annotation-driven conversion-service="conversionService">
    </mvc:annotation-driven>
    <!-- conversionService -->
    <bean id="conversionService"
    class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!-- 轉(zhuǎn)換器 -->
        <property name="converters">
            <list>
                <bean class="com.neuedu.converter.CustomDateConverter" />
            </list>
        </property>
    </bean>

C. 配置方式2

   <!-- 注解映射器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <!--注解適配器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="webBindingInitializer" ref="customBinder"></property>
    </bean>

    <!-- 自定義webBinder -->
    <bean id="customBinder"
          class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
        <property name="conversionService" ref="conversionService"/>
    </bean>
    <!--注解適配器 -->
    <bean id="conversionService"
          class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!-- 轉(zhuǎn)換器 -->
        <property name="converters">
            <list>
                <bean class="com.neuedu.converter.CustomDateConverter"/>
            </list>
        </property>
    </bean>

說明:
與配置方式1相同,只不過是手動加載映射器與適配器。

D. 實體類中加日期格式化注解

@DateTimeFormat(pattern = "yyyy-MM-dd")  
private Date receiveAppTime;

使用注解,一定要去掉原有添加的自定義時間轉(zhuǎn)換器,否則兩個沖突。
E、頁面把日期類型轉(zhuǎn)換成字符串JSP:
如果是JSON格式,一定要加以下注解。

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
或
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>   
<fmt:formatDate value="${job.jobtime }" pattern="yyyy-MM-dd HH:mm:ss"/>  

雖然時間格式正確了,但早了8小時,因為,jackson在序列化時間時是按照國際標(biāo)準(zhǔn)時間GMT進行格式化的,而在國內(nèi)默認時區(qū)使用的是CST時區(qū),兩者相差8小時。

 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")

因為 @JsonFormat 注解不是 Spring 自帶的注解,所以使用該注解前需要添加 jackson 相關(guān)的依賴包。當(dāng)然,如果是 SpringBoot 項目就不需要自己手動添加依賴了,因為在 spring-boot-start-web 下已經(jīng)包含了 jackson 相關(guān)依賴。

        <!--spring mvc-json依賴-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.9</version>
        </dependency>

總結(jié):
注解@JsonFormat主要是后臺到前臺的時間格式的轉(zhuǎn)換
注解@DataFormAT主要是前后到后臺的時間格式的轉(zhuǎn)換

  1. 集合類
    A. 字符串?dāng)?shù)組
    頁面定義如下:
    頁面選中多個checkbox向controller方法傳遞
<input type="checkbox" name="itemid" value="001"/>
<input type="checkbox" name=" itemid" value="002"/>
<input type="checkbox" name="itemid" value="002"/>

傳遞到controller方法中的格式是:001,002,003

Controller方法中可以用String[]接收,定義如下:
public String deleteitem(String[] itemid)throws Exception{
        System.out.println(itemid);
}

B. List
List中存放對象,并將定義的List放在包裝類中,action使用包裝對象接收。
List中對象:

Public class QueryVo {
Private List<Items> itemList;  // 商品列表
  //get/set方法..
}

包裝類中定義List對象,并添加get/set方法如下:
頁面定義如下:

    <tr>
        <td><input type="text" name=" itemsList[0].id" value="${item.id}" />
        </td>
        <td><input type="text" name=" itemsList[0].name"
            value="${item.name }" /></td>
        <td><input type="text" name=" itemsList[0].price"
            value="${item.price}" /></td>
    </tr>
    <tr>
        <td><input type="text" name=" itemsList[1].id" value="${item.id}" />
        </td>
        <td><input type="text" name=" itemsList[1].name"
            value="${item.name }" /></td>
        <td><input type="text" name=" itemsList[1].price"
            value="${item.price}" /></td>
    </tr>

上邊的靜態(tài)代碼改為動態(tài)jsp代碼如下:

<c:forEach items="${itemsList }" var="item" varStatus="s">
<tr>
    <td><input type="text" name="itemsList[${s.index }].name" value="${item.name }"/></td>
    <td><input type="text" name="itemsList[${s.index }].price" value="${item.price }"/></td>
    .....
    .....
</tr>
</c:forEach>

Contrller方法定義如下:

public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItemList());
}

C. Map
在包裝類中定義Map對象,并添加get/set方法,action使用包裝對象接收。
包裝類中定義Map對象如下:

Public class QueryVo {
    private Map<String, Object> itemInfo = new HashMap<String, Object>();
      //get/set方法..
    }

頁面定義如下:

<tr>
<td>學(xué)生信息:</td>
<td>
姓名:<inputtype="text" name="itemInfo['name']"/>
年齡:<inputtype="text" name="itemInfo['price']"/>
</td>
</tr>

Contrller方法定義如下:

public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getStudentinfo());
}

五、JSON數(shù)據(jù)

1. 請求參數(shù)添加注解:@RequestBody

  public RequestUser userJson(@RequestBody RequestUser requestUser) {}

2. 如果獲取響應(yīng)數(shù)據(jù)添加注解: @ResponseBody

@ResponseBody
public RequestUser userJson(@RequestBody RequestUser requestUser) {}

或:

public @ResponseBody RequestUser userJson(@RequestBody RequestUser requestUser) {

六、常用注解

注解 說明
@Controller 用于標(biāo)識是處理器類;
@RequestMapping 請求到處理器功能方法的映射規(guī)則;
@RequestParam 請求參數(shù)到處理器功能處理方法的方法參數(shù)上的綁定;
@ModelAttribute 請求參數(shù)到命令對象的綁定;
@SessionAttributes 用于聲明 session 級別存儲的屬性,放置在處理器類上,通常列出模型屬性(如@ModelAttribute)對應(yīng)的名稱,則這些屬性會透明的保存到 session 中;
@InitBinder 自定義數(shù)據(jù)綁定注冊支持,用于將請求參數(shù)轉(zhuǎn)換到命令對象屬性的對應(yīng)類型;
@CookieValue cookie 數(shù)據(jù)到處理器功能處理方法的方法參數(shù)上的綁定;
@RequestHeader 請求頭(header)數(shù)據(jù)到處理器功能處理方法的方法參數(shù)上的綁定;
@RequestBody 請求的 body 體的綁定(通過 httpMessageConverter 進行類型轉(zhuǎn)換);
@ResponseBody 處理器功能處理方法的返回值作為響應(yīng)體(通過

HttpMessageConverter 進行類型轉(zhuǎn)換);
@ResponseStatus |定義處理器功能處理方法/異常處理器返回的狀態(tài)碼和原因;
@ExceptionHandler |注解式聲明異常處理器;
@PathVariable | 請求 URI 中的模板變量部分到處理器功能處理方法的方法參數(shù)上的綁定,從而支持 RESTful 架構(gòu)風(fēng)格

六、常見錯誤:

  1. 嚴重: Unable to process Jar entry [module-info.class] from Jar [jar:file:/d:/.m2/org/ow2/asm/asm/7.1/asm-7.1.jar!/] for annotations
    解決:
    無法從Jar包[****]中處理Jar條目[module-info.class],而module-info.class用記事本打開后可以看到其內(nèi)容,而且在實際項目中,module-info.java經(jīng)常用來處理模塊之間的依賴關(guān)系等,可選擇直接刪除。


    刪除module-info.class
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容