個人筆記,如有錯誤,懇請批評指正。
Spring Web MVC是一種基于java的實現了Web MVC設計模式的請求驅動類型的輕量級Web框架,即使用了MVC架構模式的思想,將web層進行職責解耦,基于請求驅動指的就是使用請求-響應模型,框架的目的就是幫助我們簡化開發,Spring Web MVC也是要簡化我們日常Web開發的。 另外還有一種基于組件的、事件驅動的Web框架在此就不介紹了,如Tapestry、JSF等。 Spring Web MVC也是服務到工作者模式的實現,但進行可優化。前端控制器是DispatcherServlet;應用控制器其實拆為處理器映射器(Handler Mapping)進行處理器管理和視圖解析器(ViewResolver)進行視圖管理;頁面控制器/動作/處理器為Controller接口(僅包含ModelAndView handleRequest(request, response) 方法)的實現(也可以是任何的POJO類);支持本地化(Locale)解析、主題(Theme)解析及文件上傳等;提供了非常靈活的數據驗證、格式化和數據綁定機制;提供了強大的約定大于配置(慣例優先原則)的契約式編程支持
mvc、aop、core相關包
新建spring-mvc.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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd "></beans>org.springframework.web.servlet.DispatcherServlet,繼承HttpServlet,需要在Web.xml文件中定義
<?xml version="1.0" encoding="UTF-8"?><web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 繼承servlet --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value><!-- 配置文件目錄 --> </init-param> <load-on-startup>1</load-on-startup><!-- 項目啟動就初始化servlet --> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping></web-app>創建控制器FirstAction.java,實現Controller接口
// action實現Controller接口,并實現handleRequest方法(類似service方法),與JSP內置對象偶合public class FirstAction implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { // TODO Auto-generated method stub System.out.println("傳入的數據為"); String userName=request.getParameter("userName"); String pwd=request.getParameter("pwd"); System.out.println("userName:"+userName); System.out.println("這里可以調用業務層處理業務。"); //封裝數據,可以直接使用request對象,也可以使用封裝等方式,真正使用時可以選擇一種 request.setAttribute("rUserName", userName); Map<String, String > map=new HashMap<String, String>(); map.put("mUserName",userName); //返回視圖層,如果使用map封裝數據,需要作為(第二個)參數傳遞,也是request作用域。 return new ModelAndView("/jsp/first.jsp",map); //返回視圖層,不傳遞map。 //return new ModelAndView("/jsp/first.jsp"); //也可以使用如下方式傳遞,不使用Map,數據一樣是request作用域 //return new ModelAndView("/jsp/first.jsp","mUserName",userName); }}修改spring-mvc.xm.文件
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd "> <!-- 1。配置action,實現controler接口 2。配置映射處理器,用來處理請求與action的映射,可以不用寫id, 3。配置視圖解析器:完成ModelAndView的解析 缺點: 1。與JSP偶合 2。只支持屬性的注入,不支持封閉后對象注入 --> <!-- 聲明bean的name,因為使用了BeanNameUrlHandlerMapping,所以不是定義id,用戶調用的URL將通過bean的name匹配 --> <bean name="/first.action" class="cn.ustb.action.FirstAction" /> <!-- 聲明 BeanNameUrlHandlerMapping,使用名稱映射--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> <!-- 支持servlet與jsp視圖解析,可進行進一步處理,此步可省略, --> <!-- InternalResourceViewResolver支持servlet與jsp視圖解析,沒有配置時,默認使用它,此步可省略, --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 可以加前綴或后綴 --> <!-- <property name="prefix" value="/jsp/"/> <property name="suffix" value=".jsp"/> --> </bean>新建目錄jsp及目錄下新建first.jsp,用來展現訪問結果。
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> 這是/jsp/first.jsp頁面.<br/> <!-- 獲取并展現控制層傳遞過來的值 --> 直接通過request傳遞的值:${requestScope.rUserName}<br/>通過Map傳遞的值:${requestScope.mUserName} </body></html>編寫index.jsp用來訪問控制器
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> <a href="first.action?userName=mike&pwd=admin">firstMVC</a> </body></html>
strong text BeanNameUrlHandlerMapping:它將收到的HTTP請求映射到bean的名稱(這些bean需要在web應用上下文中定義)
<!-- 聲明bean的name,因為使用了BeanNameUrlHandlerMapping,所以不是定義id,用戶調用的URL將通過bean的name匹配 --> <bean name="/first.action" class="cn.ustb.action.FirstAction" /> <!-- 聲明 BeanNameUrlHandlerMapping,使用名稱映射 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />SimpleUrlHandlerMapping:它將收到的HTTP請求映射到bean的ID(這些bean需要在web應用上下文中定義)
<!-- 配置URL與ACTION對象ID進行映射 ,<prop key="second.action">second</prop>,其中key匹配url信息,value為action的ID --> <bean id="first" class="cn.ustb.action.FirstAction" /> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="first.action">first</prop> </props> </property> </bean>作為UrlBasedViewResolver的子類, 它支持頁面jstl處理.
<!-- 支持servlet與jsp視圖解析,可進行進一步處理,此步可省略, --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 可以加前綴或后綴 --> <property name="prefix" value="/jsp/"/> <property name="suffix" value=".jsp"/> </bean>forward使用轉發方式:
return new ModelAndView("forward:/jsp/first.jsp",map); //控制器采用注解,方法在返回字符串時,可以使用: return "forward:/jsp/first.jsp";redirect重定向方式
return new ModelAndView("redirect:/jsp/first.jsp",map);//控制器采用注解,方法在返回字符串時,可以使用return "redirect:/jsp/first.jsp";在spring mvc中控制對象要實現controller接口,并且必須實現handRequest方法。此控制器在接收到DispatcherServlet分配置的請求時,執行handRequest方法,并返回ModelAndView實例,此實例中封裝了Model與View。
public class FirstAction implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ... ...}可以將請求參數值自動設置到command對象中,便于后繼的使用。
/jsp/main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><html> <head> <title>My JSP 'main.jsp' starting page</title> </head> <body> 這是/jsp/main.jsp頁面.<br/> <!-- 獲取并展現控制層傳遞過來的值 --> 直接通過request傳遞的值:${requestScope.rStudent}<br/>通過Map傳遞的值:${requestScope.mStudent} </body></html>index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><html> <head> <title>My JSP 'index.jsp' starting page</title> </head> <body> <a href="student.action?stuName=mike&stuPwd=admin">test student</a> </body></html>除action類以外,其它繼續使用上一節代碼
繼承MultiActionController
public class StudentMultiAction extends MultiActionController { //定義方法時,參數規則:(HttpServletRequest request, HttpServletResponse response, [,Httpsession session] [,MyObject]); public ModelAndView add(HttpServletRequest request,HttpServletResponse response,Student student){ System.out.println("add.student:"+student); student.setStuName("rename"); return new ModelAndView("jsp/main","student",student); } //定義方法時,參數規則:(HttpServletRequest request, HttpServletResponse response, [,HttpSession session] [,MyObject]); public ModelAndView update(HttpServletRequest request,HttpServletResponse response,Student student){ System.out.println("update.student:"+student); student.setStuName("rename"); return new ModelAndView("jsp/main","student",student); } //定義方法時,參數規則:(HttpServletRequest request, HttpServletResponse response, [,HttpSession session] [,MyObject]); public ModelAndView list(HttpServletRequest request,HttpServletResponse response,Student student){ System.out.println("list.student:"+student); student.setStuName("updateName"); return new ModelAndView("jsp/main"); }}index.jsp關鍵代碼
<body> <form action="studentMulti.action?do=add" method="post"> <input type="text" name="stuName"><br> <input type="passWord" name="stuPwd"><br> <input type="submit" value="student_add"> </form> <a href="studentMulti.action?do=update&stuPwd=testpwd&stuName=testName">調用修改方法</a> <a href="studentMulti.action?&stuPwd=testpwd&stuName=testName">調用默認方法</a></body>繼續使用上一章節的代碼(注意新建項目記得重新配置web.xml文件)
添加DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter等相關信息。其中 DefaultAnnotationHandlerMapping:支持通過url找到相關的action AnnotationMethodHandlerAdapter:支持通過url匹配action定義方法 base-package:定 義掃描的范圍,spring可以自動去掃描base-pack下面或者子包下面的java文件,如果掃描到有@Component @Controller@Service等這些注解的類,則把這些類注冊為bean
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd "> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean> <context:component-scan base-package="*"></context:component-scan></beans>加入@Controller,@RequestMapping注解信息
@Controller //用來聲明控制器@RequestMapping("/student")public class StudentAction { public StudentAction(){ System.out.println("---StudentAction構造方法被調用---"); }//訪問可用student/save.action,save后邊的action是根據web.xml配置來的//如果要添加其它的數據到最后跳轉過去的頁面,可以在方法中添加ModelMap的參數,例如 : public String save(Student student,ModelMap map){//...,通過map再存放其它的數據 @RequestMapping(value="/save") public ModelAndView save(Student student){ System.out.println("save方法注入的student對象:"+student); System.out.println("---調用業務邏輯進行業務處理---"); //修改學生名字,跳轉到下一頁面時看能否顯示修改后的名字 student.setStuName("rename"); //直接使用字符串,返回視圖,進行結果展現等 return new ModelAndView("forward:/jsp/main.jsp"); } //同一個action中可以定義多個方法,方法的返回類型也可以用String @RequestMapping("/update") public String update(Student student,ModelMap paramMap){ System.out.println("update方法已注入student對象:"+student); System.out.println("---調用業務邏輯進行業務處理---"); paramMap.put("other","testOtherValue"); //直接使用字符串,返回視圖,進行結果展現等 return "forward:/jsp/main.jsp"; }}基于上面的示例,在spring3中可以進一步簡化配置,取代上面的注解方式. 步驟如下 1. 使用上面的action類,仍然給類及方法添加@Controller(類)、@RequestMapping(類及方法)注解 2. 本文件頂部添加spring mvc 命名空間的信息(可以參考org.springframework.web.servlet.config包) 3. 添加下面注解驅動mvc:annotation-driven,取代了上面的DefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter,并啟動了json的注解。
修改內容如下:
修改spring-mvc.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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd "><!-- <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean> <context:component-scan base-package="*"></context:component-scan> --> <!-- mvc:annotation-driven,取代了上面的DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter兩個Bean的配置 --> <mvc:annotation-driven></mvc:annotation-driven> <context:component-scan base-package="*"/></beans>Spring 2.0 定義了一個 org.springframework.ui.ModelMap 類,它作為通用的模型數據承載對象,傳遞數據供視圖所用。我們可以在請求處理方法中聲明一個 ModelMap 類型的入參,Spring 會將本次請求模型對象引用通過該入參傳遞進來,這樣就可以在請求處理方法內部訪問模型對象了在默認情況下,ModelMap 中的屬性作用域是 request 級別是,也就是說,當本次請求結束后,ModelMap 中的屬性將銷毀,但實際上有時候需要把ModelMap值存放于session中或有時候也可以從Session中獲取對象的值注入到ModelMap中。
繼續使用上一節代碼
如果希望在多個請求中共享 ModelMap 中的屬性,必須將其屬性轉存到 session 中,這樣 ModelMap 的屬性才可以被跨請求訪問; 可以在定義 類時使用@SessionAttributes(“屬性名”)或@SessionAttributes({“attr1”,”attr2”})等方式將嘗試從modelMap中尋找相同屬性名相應的value. 修改StudentAction.java類,
@Controller@RequestMapping("/student")//下邊如有多個屬性可以用 @SessionAttributes({“attr1”,”attr2”})。@SessionAttributes("user") public class StudentAction { public StudentAction(){ System.out.println("---StudentAction構造方法被調用---"); } @RequestMapping(value="/save") public String save(Student student,ModelMap map){ System.out.println("---調用業務邏輯進行業務處理---"); Student s2=new Student(); s2.setStuAge(11); s2.setStuId(11111); map.addAttribute("user", s2);//屬性名必須與session一致 //map.addAttribute("stu", student); //直接使用字符串,返回視圖,進行結果展現等 return "forward:/jsp/main.jsp"; } //同一個action中可以定義多個方法 @RequestMapping(value="/update") public String update(Student student){ System.out.println("update方法已注入student對象:"+student); System.out.println("---調用業務邏輯進行業務處理---"); paramMap.put("student",student); //直接使用字符串,返回視圖,進行結果展現等 return "forward:/jsp/main.jsp"; }}修改/jsp/main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><html> <head> <title>My JSP 'main.jsp' starting page</title> </head> <body> 這是/jsp/main.jsp頁面.<br/> <!-- 獲取并展現控制層傳遞過來的值 --> 默認直接通過request傳遞的值:${requestScope.student}<br/> <!-- 默認直接通過session傳遞的值stu:${sessionScope.stu}<br/> --> 默認直接通過session傳遞user值:${sessionScope.user}<br/><!--下邊的代碼給下一示例使用:調用update方法測試把session的值注入到map中,此時session已經有user相關信息--> <a href="../student/update.action">session的值注入到map中</a> </body></html>在參數中使用@ModelAttribute(“user”),可以獲取@SessionAttributes(“user”)值
繼續使用上節代碼 修改StudentAction.java類, 定義類時繼續使用@SessionAttributes(“user”),并修改update方法,在參數中添加@ModelAttribute(“user”):參數中的student的對象將由session中獲取。
@Controller@RequestMapping("/student")//下邊如有多個屬性可以用 @SessionAttributes({“attr1”,”attr2”})。@SessionAttributes("user") public class StudentAction { public StudentAction(){ System.out.println("---StudentAction構造方法被調用---"); } //同一個action中可以定義多個方法 @RequestMapping(value="/update") public String update(@ModelAttribute("user")Student student){ System.out.println("update方法已注入student對象:"+student); System.out.println("---調用業務邏輯進行業務處理---"); //直接使用字符串,返回視圖,進行結果展現等 return "forward:/jsp/main.jsp"; }}新聞熱點
疑難解答