1. 程式人生 > >Spring MVC 深入及對註解的詳細講解

Spring MVC 深入及對註解的詳細講解



核心原理

1.       使用者傳送請求給伺服器。urluser.do

2.       伺服器收到請求。發現Dispatchservlet可以處理。於是呼叫DispatchServlet

3.       DispatchServlet內部,通過HandleMapping檢查這個url有沒有對應的Controller。如果有,則呼叫Controller

4、    Control開始執行

5.       Controller執行完畢後,如果返回字串,則ViewResolver將字串轉化成相應的檢視物件;如果返回ModelAndView物件,該物件本身就包含了檢視物件資訊。

6.       DispatchServlet

將執檢視物件中的資料,輸出給伺服器。

7.       伺服器將資料輸出給客戶端。

spring3.0中相關jar包的含義

org.springframework.aop-3.0.3.RELEASE.jar

aop面向切面程式設計

org.springframework.asm-3.0.3.RELEASE.jar

spring獨立的asm位元組碼生成程式

org.springframework.beans-3.0.3.RELEASE.jar

IOC的基礎實現

org.springframework.context-3.0.3.RELEASE.jar

IOC基礎上的擴充套件服務

org.springframework.core-3.0.3.RELEASE.jar

spring的核心包

org.springframework.expression-3.0.3.RELEASE.jar

spring的表示式語言

org.springframework.web-3.0.3.RELEASE.jar

web工具包

org.springframework.web.servlet-3.0.3.RELEASE.jar

mvc工具包

@Controller控制器定義

Struts1一樣,SpringControllerSingleton的。這就意味著會被多個請求執行緒共享。因此,我們將控制器設計成無狀態類。

spring 3.0中,通過@controller標註即可將class定義為一個controller類。為使spring能找到定義為controllerbean,需要在spring-context配置檔案中增加如下定義:

<context:component-scan base-package="com.sxt.web"/>

注:實際上,使用@component,也可以起到@Controller同樣的作用。

@RequestMapping

在類前面定義,則將url和類繫結。

在方法前面定義,則將url和類的方法繫結

@RequestParam

一般用於將指定的請求引數付給方法中形參。示例程式碼如下:

@RequestMapping(params="method=reg5")

public String reg5(@RequestParam("name")String uname,ModelMap map) {

System.out.println("HelloController.handleRequest()");

System.out.println(uname);

return"index";

}

這樣,就會將name引數的值付給uname。當然,如果請求引數名稱和形參名稱保持一致,則不需要這種寫法。

@SessionAttributes

ModelMap中指定的屬性放到session中。示例程式碼如下:

@Controller

@RequestMapping("/user.do")

@SessionAttributes({"u","a"})   //ModelMap中屬性名字為ua的再放入session中。這樣,requestsession中都有了。

publicclass UserController  {

@RequestMapping(params="method=reg4")

public String reg4(ModelMap map) {         System.out.println("HelloController.handleRequest()");

map.addAttribute("u","uuuu");  //u放入request作用域中,這樣轉發頁面也可以取到這個資料。

return"index";

}

}

<body>

<h1>**********${requestScope.u.uname}</h1>

<h1>**********${sessionScope.u.uname}</h1>

</body>

注:名字為”user”的屬性再結合使用註解@SessionAttributes可能會報錯。

@ModelAttribute

    示例程式碼如下:

package com.sxt.web;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.ModelAttribute;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.SessionAttributes;

@Controller

@RequestMapping("/user.do")

@SessionAttributes({"u","a"}) 

publicclass UserController  {

@RequestMapping(params="method=reg4")

public String reg4(ModelMap map) {

System.out.println("HelloController.handleRequest()");

map.addAttribute("u","尚學堂高淇");

return"index";

}

@RequestMapping(params="method=reg5")

public String reg5(@ModelAttribute("u")String uname,ModelMap map) {

System.out.println("HelloController.handleRequest()");

System.out.println(uname);

return"index";

}

}

先呼叫reg4方法,再呼叫reg5方法。 

Controller類中方法引數的處理

Controller類中方法返回值的處理

1.       返回string(建議)

a)         根據返回值找對應的顯示頁面。路徑規則為:prefix字首+返回值+suffix字尾組成

b)         程式碼如下:

@RequestMapping(params="method=reg4")

public String reg4(ModelMap map) {

System.out.println("HelloController.handleRequest()");

return"index";

}

字首為:/WEB-INF/jsp/    字尾是:.jsp

在轉發到:/WEB-INF/jsp/index.jsp

2.       也可以返回ModelMapModelAndViewmapListSetObject、無返回值。一般建議返回字串!

請求轉發和重定向

程式碼示例:

package com.sxt.web;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.ModelAttribute;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.SessionAttributes;

@Controller

@RequestMapping("/user.do")

publicclass UserController  {

@RequestMapping(params="method=reg4")

public String reg4(ModelMap map) {

System.out.println("HelloController.handleRequest()");

//     return "forward:index.jsp";

//     return "forward:user.do?method=reg5"; //轉發

//     return "redirect:user.do?method=reg5";  //重定向

return"redirect:http://www.baidu.com"//重定向

}

@RequestMapping(params="method=reg5")

public String reg5(String uname,ModelMap map) {

System.out.println("HelloController.handleRequest()");

System.out.println(uname);

return"index";

}

}

訪問reg4方法,既可以看到效果。

獲得request物件、session物件

普通的Controller類,示例程式碼如下:

@Controller

@RequestMapping("/user.do")

publicclass UserController  {

@RequestMapping(params="method=reg2")

public String reg2(String uname,HttpServletRequest req,ModelMap map){

req.setAttribute("a", "aa");

req.getSession().setAttribute("b", "bb");

return"index";

}

}

ModelMap

map的實現,可以在其中存放屬性,作用域同request。下面這個示例,我們可以在modelMap中放入資料,然後在forward的頁面上顯示這些資料。通過el表示式、JSTLJava程式碼均可。程式碼如下:

package com.sxt.web;

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

@Controller

@RequestMapping("/user.do")

publicclass UserController extends MultiActionController  {

@RequestMapping(params="method=reg")

public String reg(String uname,ModelMap map){

map.put("a", "aaa");

return"index";

}

}

<%@ page language="java" import="java.util.*" pageEncoding="gbk"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head></head>

<body>

   < h1>${requestScope.a}</h1>

   < c:out value="${requestScope.a}"></c:out>

</body>

</html>

將屬性u的值賦給形參uname

ModelAndView模型檢視類

見名知意,從名字上我們可以知道ModelAndView中的Model代表模型,View代表檢視。即,這個類把要顯示的資料儲存到了Model屬性中,要跳轉的檢視資訊儲存到了view屬性。我們看一下ModelAndView的部分原始碼,即可知其中關係:

[java] view plain copy print?
  1. publicclass ModelAndView {  
  2.     /** View instance or view name String */
  3.     private Object view;  
  4.     /** Model Map */
  5.     private ModelMap model;  
  6.     /** 
  7.      * Indicates whether or not this instance has been cleared with a call to {@link #clear()}. 
  8.      */
  9.     privateboolean cleared = false;  
  10.     /** 
  11.      * Default constructor for bean-style usage: populating bean 
  12.      * properties instead of passing in constructor arguments. 
  13.      * @see #setView(View) 
  14.      * @see #setViewName(String) 
  15.      */
  16.     public ModelAndView() {  
  17.     }  
  18.     /** 
  19.      * Convenient constructor when there is no model data to expose. 
  20.      * Can also be used in conjunction with <code>addObject</code>. 
  21.      * @param viewName name of the View to render, to be resolved 
  22.      * by the DispatcherServlet's ViewResolver 
  23.      * @see #addObject 
  24.      */
  25.     public ModelAndView(String viewName) {  
  26.         this.view = viewName;  
  27.     }  
  28.     /** 
  29.      * Convenient constructor when there is no model data to expose. 
  30.      * Can also be used in conjunction with <code>addObject</code>. 
  31.      * @param view View object to render 
  32.      * @see #addObject 
  33.      */
  34.     public ModelAndView(View view) {  
  35.         this.view = view;  
  36.     }  
  37.     /** 
  38.      * Creates new ModelAndView given a view name and a model. 
  39.      * @param viewName name of the View to render, to be resolved 
  40.      * by the DispatcherServlet's ViewResolver 
  41.      * @param model Map of model names (Strings) to model objects 
  42.      * (Objects). Model entries may not be <code>null</code>, but the 
  43.      * model Map may be <code>null</code> if there is no model data. 
  44.      */
  45.     public ModelAndView(String viewName, Map<String, ?> model) {  
  46.         this.view = viewName;  
  47.         if (model != null) {  
  48.             getModelMap().addAllAttributes(model);  
  49.         }  
  50.     }  
  51.     /** 
  52.      * Creates new ModelAndView given a View object and a model. 
  53.      * <emphasis>Note: the supplied model data is copied into the internal 
  54.      * storage of this class. You should not consider to modify the supplied 
  55.      * Map after supplying it to this class</emphasis> 
  56.      * @param view View object to render 
  57.      * @param model Map of model names (Strings) to model objects 
  58.      * (Objects). Model entries may not be <code>null</code>, but the 
  59.      * model Map may be <code>null</code> if there is no model data. 
  60.      */
  61.     public ModelAndView(View view, Map<String, ?> model) {  
  62.         this.view = view;  
  63.         if (model != null) {  
  64.             getModelMap().addAllAttributes(model);  
  65.         }  
  66.     }  
  67.     /** 
  68.      * Convenient constructor to take a single model object. 
  69.      * @param viewName name of the View to render, to be resolved 
  70.      * by the DispatcherServlet's ViewResolver 
  71.      * @param modelName name of the single entry in the model 
  72.      * @param modelObject the single model object 
  73.      */
  74.     public ModelAndView(String viewName, String modelName, Object modelObject) {  
  75.         this.view = viewName;  
  76.         addObject(modelName, modelObject);  
  77.     }  
  78.     /** 
  79.      * Convenient constructor to take a single model object. 
  80.      * @param view View object to render 
  81.      * @param modelName name of the single entry in the model 
  82.      * @param modelObject the single model object 
  83.      */
  84.     public ModelAndView(View view, String modelName, Object modelObject) {  
  85.         this.view = view;  
  86.         addObject(modelName, modelObject);  
  87.     }  
  88.     /** 
  89.      * Set a view name for this ModelAndView, to be resolved by the 
  90.      * DispatcherServlet via a ViewResolver. Will override any 
  91.      * pre-existing view name or View. 
  92.      */
  93.     publicvoid setViewName(String viewName) {  
  94.         this.view = viewName;  
  95.     }  
  96.     /** 
  97.      * Return the view name to be resolved by the DispatcherServlet 
  98.      * via a ViewResolver, or <code>null</code> if we are using a View object. 
  99.      */
  100.     public String getViewName() {  
  101.         return (this.view instanceof String ? (String) this.view : null);  
  102.     }  
  103.     /** 
  104.      * Set a View object for this ModelAndView. Will override any 
  105.      * pre-existing view name or View. 
  106.      */
  107.     publicvoid setView(View view) {  
  108.         this.view = view;  
  109.     }  
  110.     /** 
  111.      * Return the View object, or <code>null</code> if we are using a view name 
  112.      * to be resolved by the DispatcherServlet via a ViewResolver. 
  113.      */
  114.     public View getView() {  
  115.         return (this.view instanceof View ? (View) this.view : null);  
  116.     }  
  117.     /** 
  118.      * Indicate whether or not this <code>ModelAndView</code> has a view, either 
  119.      * as a view name or as a direct {@link View} instance. 
  120.      */
  121.     publicboolean hasView() {  
  122.         return (this.view != null);  
  123.     }  
  124.     /** 
  125.      * Return whether we use a view reference, i.e. <code>true</code> 
  126.      * if the view has been specified via a name to be resolved by the 
  127.      * DispatcherServlet via a ViewResolver. 
  128.      */
  129.     publicboolean isReference() {  
  130.         return (this.view instanceof String);  
  131.     }  
  132.     /** 
  133.      * Return the model map. May return <code>null</code>. 
  134.      * Called by DispatcherServlet for evaluation of the model. 
  135.      */
  136.     protected Map<String, Object> getModelInternal() {  
  137.         returnthis.model;  
  138.     }  
  139.     /** 
  140.      * Return the underlying <code>ModelMap</code> instance (never <code>null</code>). 
  141.      */
  142.     public ModelMap getModelMap() {  
  143.         if (this.model == null) {  
  144.             this.model = new ModelMap();  
  145.         }  
  146.         returnthis.model;  
  147.     }  
  148.     /** 
  149.      * Return the model map. Never returns <code>null</code>. 
  150.      * To be called by application code for modifying the model. 
  151.      */
  152.     public Map<String, Object> getModel() {  
  153.         return getModelMap();  
  154.     }  
  155.     /** 
  156.      * Add an attribute to the model. 
  157.      * @param attributeName name of the object to add to the model 
  158.      * @param attributeValue object to add to the model (never <code>null</code>) 
  159.      * @see ModelMap#addAttribute(String, Object) 
  160.      * @see #getModelMap() 
  161.      */
  162.     public ModelAndView addObject(String attributeName, Object attributeValue) {  
  163.         getModelMap().addAttribute(attributeName, attributeValue);  
  164.         returnthis;  
  165.     }  
  166.     /** 
  167.      * Add an attribute to the model using parameter name generation. 
  168.      * @param attributeValue the object to add to the model (never <code>null</code>) 
  169.      * @see ModelMap#addAttribute(Object) 
  170.      * @see #getModelMap() 
  171.      */
  172.     public ModelAndView addObject(Object attributeValue) {  
  173.         getModelMap().addAttribute(attributeValue);  
  174.         returnthis;  
  175.     }  
  176.     /** 
  177.      * Add all attributes contained in the provided Map to the model. 
  178.      * @param modelMap a Map of attributeName -> attributeValue pairs 
  179.      * @see ModelMap#addAllAttributes(Map) 
  180.      * @see #getModelMap() 
  181.      */
  182.     public ModelAndView addAllObjects(Map<String, ?> modelMap) {  
  183.         getModelMap().addAllAttributes(modelMap);  
  184.         returnthis;  
  185.     }  
  186.     /** 
  187.      * Clear the state of this ModelAndView object. 
  188.      * The object will be empty afterwards. 
  189.      * <p>Can be used to suppress rendering of a given ModelAndView object 
  190.      * in the <code>postHandle</code> method of a HandlerInterceptor. 
  191.      * @see #isEmpty() 
  192.      * @see HandlerInterceptor#postHandle 
  193.      */
  194.     publicvoid clear() {  
  195.         this.view = null;  
  196.         this.model = null;  
  197.         this.cleared = true;  
  198.     }  
  199.     /** 
  200.      * Return whether this ModelAndView object is empty, 
  201.      * i.e. whether it does not hold any view and does not contain a model. 
  202.      */
  203.     publicboolean isEmpty() {  
  204.         return (this.view == null && CollectionUtils.isEmpty(this.model));  
  205.     }  
  206.     /** 
  207.      * Return whether this ModelAndView object is empty as a result of a call to {@link #clear} 
  208.      * i.e. whether it does not hold any view and does not contain a model. 
  209.      * <p>Returns <code>false</code> if any additional state was added to the instance 
  210.      * <strong>after</strong> the call to {@link #clear}. 
  211.      * @see #clear() 
  212.      */
  213.     publicboolean wasCleared() {  
  214.         return (this.cleared && isEmpty());  
  215.     }  
  216.     /** 
  217.      * Return diagnostic information about this model and view. 
  218.      */
  219.     @Override
  220.     public String toString() {  
  221.         StringBuilder sb = new StringBuilder("ModelAndView: ");  
  222.         if (isReference()) {  
  223.             sb.append("reference to view with name '").append(this.view).append("'");  
  224.         }  
  225.         else {  
  226.             sb.append("materialized View is [").append(this.view).append(']');  
  227.         }  
  228.         sb.append("; model is ").append(this.model);  
  229.         return sb.toString();  
  230.     }  
  231. }  
public class ModelAndView {

	/** View instance or view name String */
	private Object view;

	/** Model Map */
	private ModelMap model;

	/**
	 * Indicates whether or not this instance has been cleared with a call to {@link #clear()}.
	 */
	private boolean cleared = false;


	/**
	 * Default constructor for bean-style usage: populating bean
	 * properties instead of passing in constructor arguments.
	 * @see #setView(View)
	 * @see #setViewName(String)
	 */
	public ModelAndView() {
	}

	/**
	 * Convenient constructor when there is no model data to expose.
	 * Can also be used in conjunction with <code>addObject</code>.
	 * @param viewName name of the View to render, to be resolved
	 * by the DispatcherServlet's ViewResolver
	 * @see #addObject
	 */
	public ModelAndView(String viewName) {
		this.view = viewName;
	}

	/**
	 * Convenient constructor when there is no model data to expose.
	 * Can also be used in conjunction with <code>addObject</code>.
	 * @param view View object to render
	 * @see #addObject
	 */
	public ModelAndView(View view) {
		this.view = view;
	}

	/**
	 * Creates new ModelAndView given a view name and a model.
	 * @param viewName name of the View to render, to be resolved
	 * by the DispatcherServlet's ViewResolver
	 * @param model Map of model names (Strings) to model objects
	 * (Objects). Model entries may not be <code>null</code>, but the
	 * model Map may be <code>null</code> if there is no model data.
	 */
	public ModelAndView(String viewName, Map<String, ?> model) {
		this.view = viewName;
		if (model != null) {
			getModelMap().addAllAttributes(model);
		}
	}

	/**
	 * Creates new ModelAndView given a View object and a model.
	 * <emphasis>Note: the supplied model data is copied into the internal
	 * storage of this class. You should not consider to modify the supplied
	 * Map after supplying it to this class</emphasis>
	 * @param view View object to render
	 * @param model Map of model names (Strings) to model objects
	 * (Objects). Model entries may not be <code>null</code>, but the
	 * model Map may be <code>null</code> if there is no model data.
	 */
	public ModelAndView(View view, Map<String, ?> model) {
		this.view = view;
		if (model != null) {
			getModelMap().addAllAttributes(model);
		}
	}

	/**
	 * Convenient constructor to take a single model object.
	 * @param viewName name of the View to render, to be resolved
	 * by the DispatcherServlet's ViewResolver
	 * @param modelName name of the single entry in the model
	 * @param modelObject the single model object
	 */
	public ModelAndView(String viewName, String modelName, Object modelObject) {
		this.view = viewName;
		addObject(modelName, modelObject);
	}

	/**
	 * Convenient constructor to take a single model object.
	 * @param view View object to render
	 * @param modelName name of the single entry in the model
	 * @param modelObject the single model object
	 */
	public ModelAndView(View view, String modelName, Object modelObject) {
		this.view = view;
		addObject(modelName, modelObject);
	}


	/**
	 * Set a view name for this ModelAndView, to be resolved by the
	 * DispatcherServlet via a ViewResolver. Will override any
	 * pre-existing view name or View.
	 */
	public void setViewName(String viewName) {
		this.view = viewName;
	}

	/**
	 * Return the view name to be resolved by the DispatcherServlet
	 * via a ViewResolver, or <code>null</code> if we are using a View object.
	 */
	public String getViewName() {
		return (this.view instanceof String ? (String) this.view : null);
	}

	/**
	 * Set a View object for this ModelAndView. Will override any
	 * pre-existing view name or View.
	 */
	public void setView(View view) {
		this.view = view;
	}

	/**
	 * Return the View object, or <code>null</code> if we are using a view name
	 * to be resolved by the DispatcherServlet via a ViewResolver.
	 */
	public View getView() {
		return (this.view instanceof View ? (View) this.view : null);
	}

	/**
	 * Indicate whether or not this <code>ModelAndView</code> has a view, either
	 * as a view name or as a direct {@link View} instance.
	 */
	public boolean hasView() {
		return (this.view != null);
	}

	/**
	 * Return whether we use a view reference, i.e. <code>true</code>
	 * if the view has been specified via a name to be resolved by the
	 * Dispatc