1. 程式人生 > 實用技巧 >3 Controller(控制器)和RestFul風格

3 Controller(控制器)和RestFul風格

3 Controller(控制器)和RestFul風格

控制器Controller

  • 控制器負責提供訪問應用程式的行為,通常通過介面定義或註解定義兩種方法實現。
  • 控制器負責解析使用者的請求並將其轉換為一個模型。
  • 在Spring MVC中一個控制器類可以包含多個方法。
  • 在Spring MVC中,對於Controller的配置方式有很多種。

module:springmvc-04-controller

環境搭建

新增web框架支援,以及Artifacts中的lib配置!

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--1 配置DispatcherServlet-->
    <servlet>
         <servlet-name>DispatcherServlet</servlet-name>
         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
         <init-param>
             <param-name>contextConfigLocation</param-name>
             <param-value>classpath:springmvc-servlet.xml</param-value>
         </init-param>
         <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

springmvc-servlet.xml

<?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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--自動掃描包,讓指定包下的註解生效,由IOC容器統一管理-->
    <context:component-scan base-package="com.zzb.controller"/>
    <!--讓Spring MVC不處理靜態資源,例如.mp3 .css .jpg等不走檢視解析器-->
    <mvc:default-servlet-handler/>
    <!--
       支援mvc註解驅動
       在spring中一般採用@RequestMapping註解來完成對映關係
       要想使@RequestMapping註解生效
       必須向上下文中註冊DefaultAnnotationHandlerMapping
       和一個AnnotationMethodHandlerAdapter例項
       這兩個例項分別在類級別和方法級別處理。
       而annotation-driven配置幫助我們自動完成上述兩個例項的注入
    -->
    <mvc:annotation-driven/>

    <!--檢視解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <!--字首-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--字尾-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

程式碼實現

實現Controller介面

Controller是一個介面,在org.springframework.web.servlet.mvc包下,介面中只有一個方法;

@FunctionalInterface
public interface Controller {
    @Nullable
    ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}

1、編寫一個ControllerTest1類,實現Contoller介面

package com.zzb.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ControllerTest1 implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

        // 建立模型檢視
        ModelAndView modelAndView = new ModelAndView();
        // 呼叫業務層
        String msg = "ControllerTest1";
        modelAndView.addObject("msg", msg);
        // 設定跳轉檢視
        modelAndView.setViewName("test");

        return modelAndView;
    }
}

2、去Spring配置檔案中註冊請求的bean,name或id對應請求路徑,class對應處理請求的類

    <bean id="/t1" class="com.zzb.controller.ControllerTest1"/>

3、編寫前端展示頁面test.jsp,注意在WEB-INF/jsp目錄

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>

4、配置Tomcat,啟動測試!

測試結果:

說明:

  • 實現Controller介面定義控制器的方法比較老了,一般不推薦使用!
  • 缺點是一個控制器只有一個方法,如果要多個方法則需要定義多個Controller。

使用註解@Controller

  • @Controller註解型別用於宣告Spring類的例項是一個控制器(在講IOC時還提到了另外3個註解);

  • Spring可以使用掃描機制來找到應用程式中所有基於註解的控制器類,為了保證Spring能找到你的控制器,需要在配置檔案中宣告元件掃描。

    <!--自動掃描包,讓指定包下的註解生效,由IOC容器統一管理-->
    <context:component-scan base-package="com.zzb.controller"/>
  • 增加一個ControllerTest2類,使用註解!
package com.zzb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ControllerTest2 {

    @RequestMapping("/t2")
    public String test2(Model model){

        model.addAttribute("msg", "ControllerTest2");
        // 返回檢視位置
        return "test";
    }
}
  • 啟動Tomcat測試

可以發現,我們的兩個請求都可以指向一個檢視,但是頁面結果的結果是不一樣的,從這裡可以看出檢視是被複用的,而控制器與檢視之間是弱偶合關係。

註解方式是平時使用的最多的方式!

RequestMapping

@RequestMapping

@RequestMapping註解用於對映url到控制器類或一個特定的處理程式方法。可用於類或方法上。用於類上,表示類中的所有響應請求的方法都是以該地址作為父路徑。

package com.zzb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/myweb")
public class ControllerTest2 {

    @RequestMapping("/t2")
    public String test2(Model model){

        model.addAttribute("msg", "ControllerTest2");
        // 返回檢視位置
        return "test";
    }
}

注意觀察url

RestFul 風格

概念

Restful就是一個資源定位及資源操作的風格。不是標準也不是協議,只是一種風格。基於這個風格設計的軟體可以更簡潔,更有層次,更易於實現快取等機制。

功能

資源:網際網路所有的事物都可以被抽象為資源

資源操作:使用POST、DELETE、PUT、GET,使用不同方法對資源進行操作。

分別對應 新增、 刪除、修改、查詢。

傳統方式操作資源 :通過不同的引數來實現不同的效果!方法單一,post 和 get

http://127.0.0.1/item/queryItem.action?id=1 查詢,GET

http://127.0.0.1/item/saveItem.action 新增,POST

http://127.0.0.1/item/updateItem.action 更新,POST

http://127.0.0.1/item/deleteItem.action?id=1 刪除,GET或POST

使用RESTful操作資源 :可以通過不同的請求方式來實現不同的效果!如下:請求地址一樣,但是功能可以不同!

http://127.0.0.1/item/1 查詢,GET

http://127.0.0.1/item 新增,POST

http://127.0.0.1/item 更新,PUT

http://127.0.0.1/item/1 刪除,DELETE

程式碼實現

1、新建一個RestFulController

package com.zzb.controller;

import org.springframework.stereotype.Controller;

@Controller
public class RestFulController {
}

2、在Spring MVC中可以使用 @PathVariable 註解,讓方法引數的值對應繫結到一個URI模板變數上。

package com.zzb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class RestFulController {

    @RequestMapping("/t3/{p1}/{p2}")
    public String test3(@PathVariable int p1,@PathVariable int p2, Model model){

        int result = p1 + p2;

        model.addAttribute("msg", result);

        return "test";
    }
}

3、測試

使用路徑變數的好處?

  • 使路徑變得更加簡潔;

  • 獲得引數更加方便,框架會自動進行型別轉換;

  • 通過路徑變數的型別可以約束訪問引數,如果型別不一樣,則訪問不到對應的請求方法,如這裡訪問是的路徑是/t3/1/a,則路徑與方法不匹配,而不會是引數轉換失敗。

4、修改引數型別,再次測試

package com.zzb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class RestFulController {

    @RequestMapping("/t3/{p1}/{p2}")
    public String test3(@PathVariable int p1,@PathVariable String p2, Model model){

        String result = p1 + p2;

        model.addAttribute("msg", result);

        return "test";
    }
}

測試結果:

使用method屬性指定請求型別

用於約束請求的型別,可以收窄請求範圍。指定請求謂詞的型別如GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等

測試:

1、增加一個方法

    // 對映訪問路徑,必須是post請求
    @RequestMapping(value = "/t4", method = {RequestMethod.POST})
    public String test4(Model model){

        model.addAttribute("msg", "Hello");
        return "test";
    }

2、使用瀏覽器位址列進行訪問預設是Get請求,會報錯405

3、將指定方法從POST改為GET

    @RequestMapping(value = "/t4", method = {RequestMethod.GET})

總結:

Spring MVC 的 @RequestMapping 註解能夠處理 HTTP 請求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH。

所有的位址列請求預設都會是 HTTP GET 型別的。

方法級別的註解變體有如下幾個:組合註解

@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

@GetMapping 是一個組合註解,平時使用的會比較多!

它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一個快捷方式。