spring MVC 之controller (一)

在spring MVC 中,每個請求到DispatcherServlet後根據需求,將會分配到相對應的控制器controller去處理,因此controller在 spring MVC中的作用是非常重要的。本文先介紹兩類controller。

一、頁面直接跳轉

當我們請求一個頁面時,由於文件都隱藏在了文件下,無法直接訪問,因此需要有一個控制器來實現簡單的頁面跳轉,跳轉到對應的頁面。這類控制器不需要對請求做太多的處理地,只需實現頁面跳轉即可。這時,我們可以不需要自己去設計自己的controller,而是直接配置現有的controller類。與頁面直接跳轉的現有controller主要有以下兩個:

1、ParameterizableViewController

我們在“/WEB-INF/jsp/”目錄下創建了一個welcome.html文檔,爲了實現在瀏覽器中輸入welcome.test就直接跳轉到welcome.html,spring-servlet.xml文件配置主要如下:

這裏寫圖片描述

不需要自己寫控制器,而是直接調用現有的ParameterizableViewController類來實現。只需要指定對應的視圖名就可以。然後就能根據視圖解析器去查找需要跳轉的頁面,視圖解析器設置如下:

<!-- 視圖解析器 -->
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <!-- 前綴 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 後綴 -->
        <property name="suffix" value=".html" />
    </bean>

2、UrlFilenameViewController

這個控制器相對於ParameterizableViewController更爲簡潔,可以不用指明視圖名,而直接通過請求的url去查找文件,直接以請求 的URL來確定視圖名,然後直接跳轉過去。例如請求的url是“welcome.test”,那麼從中提取出視圖名爲“welcome”,而不需要另外指定視圖名。這種方法適用於請求的url跟視圖名一致。

這裏寫圖片描述

這兩種方法都是直接配置現有的controller類來實現頁面的直接跳轉,區別在於ParameterizableViewController類可以根據需要指定視圖名,較爲靈活,而UrlFilenameViewController類只能跳轉到跟url對應的視圖名,而不能自行指定視圖名。

welcome.html文檔如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>welcome page</title>
</head>
<body>
    <h1>this is the welcome page</h1>
</body>
</html>

啓動服務器後,在外部瀏覽器中輸入:http://localhost:8080/springMVC/welcome.test,即可正常跳轉到welcome.htm頁面。

這裏寫圖片描述

二、封裝表單參數的控制器

一般我們在進行表單登記或者註冊時,會要求填較多的信息,這些信息如果按照之前介紹的繼承Controller來實現參數的注入,當表單參數較多時,代碼就會顯得冗餘。因此我們希望controller能實現數據的自動封裝。這裏,我將介紹兩種方法來實現表單參數的自動封裝。

1、AbstractCommandController

首先需要注意的一個問題是由於AbstractCommandController在spring 3之後就不建議使用了,因此在一些比較新的spring MVC框架中並不包含這個類,這裏本着學習的態度,還是瞭解一下。所以在導入jar包是需要注意版本問題。通過查看各版本的jar包,注意到3.2.2這個版本中包含有AbstractCommandController,讀者們可以到 http://repo.spring.io/libs-release-local/org/springframework/spring/3.2.2.RELEASE/ 中下載。在測試中,我導入的jar包如下:

這裏寫圖片描述

接下來使配置文件,首先配置info.javainfoController.java文檔

這裏寫圖片描述

infoController.java文檔

package test.springMVC;

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

import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;

@SuppressWarnings("deprecation")
public class infoController extends AbstractCommandController {

    @Override
    protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException exception)
            throws Exception {
        info inf = (info)command;
        System.out.println(inf);
        return new ModelAndView("addsucc");
    }

}

info.java文檔

package test.springMVC;

public class info {

    private String name;

    private int num;

    private String phone;

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

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

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String toString() {
        return name + ";" + num + ";" + phone;
    }


}

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

    <!-- 設置映射方式 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="addInfo.html">addInfoController</prop>
                <prop key="add.test">addSuccController</prop>
            </props>
        </property>
    </bean>

    <bean id="addInfoController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController">
    </bean>
    <bean id="addSuccController" class="test.springMVC.infoController">
        <property name="commandClass" value="test.springMVC.info"></property>
    </bean>

    <!-- scan the package and the sub package -->
    <context:component-scan base-package="test.SpringMVC" />

    <!-- don't handle the static resource -->
    <mvc:default-servlet-handler />

    <!-- if you use annotation you must configure following setting -->
    <mvc:annotation-driven />

    <!-- 視圖解析器 -->
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <!-- 前綴 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 後綴 -->
        <property name="suffix" value=".html" />
    </bean>
</beans>

視圖文檔 addInfo.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>添加信息</title>
</head>
<body>
    <form action="add.test" method="post">
        name : <input type="text" name="name" /><br />
        number : <input type="text" name="num" /><br />
        phone:<input type="text" name="phone" /><br />
        <input type="submit" value="提交" /> 
    </form>
</body>
</html>

啓動服務器後,在外部瀏覽器中輸入http://localhost:8080/springMVC/addInfo.html,跳轉到addInfo.html的頁面

這裏寫圖片描述

填入信息後點提交,提交成功後會跳轉到成功頁面

這裏寫圖片描述

另外查看eclipse控制能打印出所填信息

這裏寫圖片描述

當輸入的表單參數爲“int”和“String”類型,並且輸入格式正確的話,是能正確顯示的,但是如果我們在視圖addInfo.html文檔中加入一個日期格式,就會報“空指針異常”的錯誤。這是因爲當表單提交參數時,會有一個數據綁定DateBind的過程,根據“name”的值把參數註冊到對象中。當輸入的爲“int”和“String”類型時,通過屬性編輯器能將其轉成正確的數據類型,但是缺少Date類型的屬性編輯器,因此要將Date類型正確的註冊到對象中,在數據綁定中手動註冊一個Date類型屬性編輯器。

infoController.java文檔

package test.springMVC;

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

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

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;

@SuppressWarnings("deprecation")
public class infoController extends AbstractCommandController {

    @Override
    protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException exception)
            throws Exception {
        info inf = (info)command;
        System.out.println(inf);
        return new ModelAndView("addsucc");
    }

    @Override
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
        // TODO Auto-generated method stub
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }

}

info.java文檔

package test.springMVC;

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

public class info {

    private String name;

    private int num;

    private String phone;

    private Date schoolDate;

    public Date getSchoolDate() {
        return schoolDate;
    }

    public void setSchoolDate(Date schoolDate) {
        this.schoolDate = schoolDate;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

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

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String toString() {
        return name + ";" + num + ";" + phone + ";" + new SimpleDateFormat("yyyy-mm-dd").format(schoolDate);
    }
}

對應的 addInfo.html也增加一個日期選擇框

date : <input type="date" name="schoolDate" />

這樣運行之後,控制檯就能打印出正確的表單提交的參數

這裏寫圖片描述

2、SimpleFormController

SimpleFormController也是用自動封裝表單參數。SimpleFormController有如下一些特點:

1、表單提交方式必須採用“post”方法;

2、相對於AbstractCommandController信息登記和封裝成功需要兩個控制器來處理,SimpleFormController只需要一個控制器就行,兩次請求的地址都是同一個,根據提交方式不同來區分轉到的頁面,因此在控制器中需要設置formViewsuccessView屬性。第一個網址中提交是使用的“GET”方式,因此轉到formView對應的頁面,第二次表單提交時採用的“post”方式,因此轉到successView對應的頁面。

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

    <!-- 設置映射方式 -->
    <bean  class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="addInfo.html">addInfoController</prop>
            </props>
        </property>
    </bean>

    <bean id="addInfoController" class="test.springMVC.infoFormController">
        <property name="commandClass" value="test.springMVC.info"></property>
        <property name="formView" value="addInfo"></property>
        <property name="successView" value="addsucc"></property>
    </bean>

    <!-- 視圖解析器 -->
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <!-- 前綴 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 後綴 -->
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

infoFormController.java

package test.springMVC;

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

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

public class infoFormController extends SimpleFormController {



    @Override
    protected Map referenceData(HttpServletRequest request) throws Exception {
        Map<String, Object> model = new HashMap<String, Object>();
        model.put("groupList", new String[]{"group1", "group2"});
        return model;
    }

    @Override
    protected ModelAndView onSubmit(Object command) throws Exception {
        info inf = (info)command;
        System.out.println(inf);
        return new ModelAndView("addsucc");
    }


    @Override
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
        // TODO Auto-generated method stub
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }
}

addInfo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>信息添加</title>
</head>
<body>
    <form action="" method="post"> <!-- 必須指定爲post -->
        name : <input type="text" name="name" /><br />
        number : <input type="text" name="num" /><br />
        phone:<input type="text" name="phone" /><br />
        group:<select name="group">
                    <c:forEach items="${groupList}" var="group">
                    <option value="${group}">${group}</option>
                    </c:forEach>
                </select>
        date : <input type="date" name="schoolDate" />
        <input type="submit" value="提交" /> 
    </form>
</body>
</html>

info.java

package test.springMVC;

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

public class info {

    private String name;

    private int num;

    private String phone;

    private String group;

    private Date schoolDate;

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public Date getSchoolDate() {
        return schoolDate;
    }

    public void setSchoolDate(Date schoolDate) {
        this.schoolDate = schoolDate;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

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

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String toString() {
        return name + ";" + num + ";" + phone + ";" + group + ";" + new SimpleDateFormat("yyyy-mm-dd").format(schoolDate);
    }
}

針對上面給出的代碼,對SimpleFormController實現表單數據自動封裝的過程總結如下:

  1. 瀏覽器中輸入url:“http://localhost:8080/springMVC/addInfo.html”,通過查找spring-servlet.xml文檔,由於是get請求,因此轉到formView對應的addInfo.jsp頁面。
  2. addInfo.html頁面中的<select>標籤中的數據來自infoFormController中的“referenceData”方法,因此轉到addInfo.html頁面之前先獲取“referenceData”中的數據,然後在addInfo.html頁面頁面中顯示出來。
  3. 填寫信息之後,提交表單,提交的url還是 “http://localhost:8080/springMVC/addInfo.html”。由於表單的提交方式爲“post”,因此調用controller中的“onSubmit”方法。
  4. 數據封裝成功後,轉到successView對應的addsucc.jsp頁面。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章