3.一、定義一個控制器:使用 @Controller 和 @RequestMapping

1)用 @Controller 定義一個控制器

    註解 @Controller 指定一個特定的類擔任控制器的角色。Spring 不要求你集成任何控制器基類或者引用 Servlet API。不過,你仍然能夠根據須要使用指定的 Servlet 特性。
    註解 @Controller 對於被註解的類來講就像一個模板(stereotype),指示它的角色。收發器(dispatcher)爲被映射的方法掃描被註解的類,並檢測註解 @RequestMapping(見下一部分)。
    你能夠在分發器的上下文中使用標準的 Spring Bean 定義,來顯式地定義被註解的控制器。不過,@Controller 模板也容許自動檢測,就像 Spring 一般支持的在類路徑中自動檢測組件類並自動爲它們註冊 Bean 定義。
    爲了可以自動檢測到這樣被註解的控制器,你要添加組件掃描到你的配置中。像下面的 XML 片斷那樣使用 Spring 的 context'命名空間:html

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">

    <context:component-scan base-package="com.techmap.examples.controllers" />
    ......
</beans>

2)使用 @RequestMapping 映射請求

    使用註解 @RequestMapping 映射一個 URL(好比:/contex)到一個類或者一個特定的處理方法上。典型地,類級別的註解映射一個指定的請求路徑(或者是路徑匹配模式)到一個控制器,使用額外的方法層註解縮小主要映射的範圍。
下面是一個例子:java

package com.techmap.examples.controllers;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;


@Controller
@RequestMapping("/contex")
public class ContexController
{
    
    /**
     * 不指定 path 參數
     */
    @RequestMapping(method = RequestMethod.GET)
    public String get1()
    {
        return "/examples/targets/test1";
    }
    
    /**
     * 帶有 path 參數
     */
    @RequestMapping(path = "/new", method = RequestMethod.GET)
    public String get2()
    {
        return "/examples/targets/test2";
    }
    
    /**
     * 帶有 URI 模板
     */
    @RequestMapping(path = "/{day}", method = RequestMethod.GET)
    public String getForDay(@PathVariable @DateTimeFormat(iso = ISO.DATE) Date day, Model model)
    {
        System.out.println("--> " + new SimpleDateFormat("yyyy-MM-dd").format(day));
        
        return "/examples/targets/test3";
    }
}

3)測試例子

    爲使得例子可用,在上一篇的項目中添加下面三個 jsp 文件:test1.jsp、test3.jsp、test3.jsp。內容以下:web

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%
    String basepath = request.getScheme() + "://" + request.getServerName() + ":" + request
            .getServerPort() + request.getContextPath() + "/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basepath%>">
</head>
<body>
    <h2>Test 1</h2>
</body>
</html>

代碼中只有 test1.jsp,其餘兩個內容相同,只有<h2>中的內容不一樣,test2.jsp 中是<h2>Test 2</h2>,test3.jsp中是<h2>Test 3</h2>。它們所在的目錄是:
圖片描述spring

4)改造一下 helloWorld.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%
    String basepath = request.getScheme() + "://" + request.getServerName() + ":" + request
            .getServerPort() + request.getContextPath() + "/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basepath%>">
</head>
<body>
    <h2>Hello World!</h2>
    <h2>Test Controller</h2>
    <a href="contex">Test1</a><br>
    <a href="contex/new">Test2</a><br>
    <a href="contex/2016-09-05">Test3</a><br>
</body>
</html>

5)開始測試

    用上一篇中給出的路徑進入 helloWorld.jsp,看到以下頁面:
圖片描述
    分別點擊超連接 Test一、Test二、Test3,將會跳到上面定義的三個 test*.jsp 頁面。值得注意的是,點擊 Test3 時,控制檯會打印出以下的信息:spring-mvc

...
DEBUG 2016-09-05 08:15:23,152 Last-Modified value for [/spring5mvc/contex/2016-09-05] is: -1  (DispatcherServlet.java:951) 
--> 2016-09-05
DEBUG 2016-09-05 08:15:23,219 Invoking afterPropertiesSet() on bean with name '/examples/targets/test3'
...

這說明<a href="contex/2016-09-05">Test3</a>中的日期字符串將做爲參數傳遞到參數 day 上。mvc

6)說明

    在上面的例子中,註解 @RequestMapping 被用在了多處。第一處是類級別的,它指出這個控制器中的全部方法都與路徑 /contex 相關。方法get1()上有一個 @RequestMapping 來進一步細化:它只接受 GET 請求,這意味着 HTTP GET 請求 /contex 將調用這個方法。方法 get2() 有一個類似的細化;方法 get2() 把 HTTP 方法定義和路徑合併到了一塊兒,這樣 GET 請求 /contex/new 就能夠被這個方法處理了。
    方法 getForDay() 展現了另外一種使用 @RequestMapping 的方式:URI 模板(後面介紹)。
    像第1、二篇給出的 Hello World 例子那樣,類級別的 @RequestMapping 不是必須的。沒有它,全部的路徑都是簡單的絕對路徑,而不是相對的。若是不指定 GET、PUT、POST 等,@RequestMapping 默認映射全部的HTTP方法。app

相關文章
相關標籤/搜索