Spring MVC框架

1 Spring MVC簡介javascript

1.1. Spring3 MVC VS Struts2

l  官方的下載網址是:http://www.springsource.org/downloadhtml

l  咱們用Struts2時採用的傳統的配置文件的方式,並無使用傳說中的0配置Spring3 mvc能夠認爲已經100%零配置了前端

l  Spring會比Struts快,在Struts中默認配置了不少缺省的攔截器,在給開發者提供便利的同時,失去了靈活性和效率.java

l  Spring mvc是基於方法的設計, 而Sturts是基於類,每次發一次請求都會實例一個action,每一個action都會被注入屬性,而spring基於方法,粒度更細,可控制更強jquery

l  設計思想上:Struts更加符合oop的編程思想,Spring是在在Servlet上擴展,使用AOP實現。web

l  Intercepter的實現機制:Struts有以本身的interceptor機制,Spring mvc用的是獨立的AOP方式. 須要的本身配置,比較麻煩當性能較優,靈活性高ajax

2 環境與入門案例

2.1使用示例

2.1.1建立項目並導入相關jar包

mvc/aop/core相關包。spring

2.1.2建立配置文件

新建spring-mvc.xml文件apache

<?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>

2.1.3 配置前端過濾器

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>

      <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-mapping>

      <servlet-name>mvc</servlet-name>

      <url-pattern>*.action</url-pattern>

   </servlet-mapping>

</web-app>

2.1.4建立控制器

建立控制器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);

   }

}

2.1.5修改配置文件,添加控制器信息

修改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.it.action.FirstAction" />

   <!-- 聲明 BeanNameUrlHandlerMapping,使用名稱映射-->

   <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

   <!-- 支持servlet與jsp視圖解析,可進行進一步處理,此步可省略, -->

   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

   <!-- 能夠加前綴或後綴 -->

      <!--

      <property name="prefix" value="/jsp/"/>

      <property name="suffix" value=".jsp"/> 

       -->

   </bean>

2.1.6建立結果展示頁面

新建目錄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>

2.1.7編寫測試(訪問)頁面

編寫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=zcf&pwd=admin">firstMVC</a>

  </body>

</html>

2.2流程分析

3 URL處理器

3.1 BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping:它將收到的HTTP請求映射到bean的名稱(這些bean須要在web應用上下文中定義)

<!-- 聲明bean的name,由於使用了BeanNameUrlHandlerMapping,因此不是定義id,用戶調用的URL將經過bean的name匹配 -->
   <bean name="/first.action" class="cn.it.action.FirstAction" />
   <!--
      聲明 BeanNameUrlHandlerMapping,使用名稱映射
    -->
   <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"   />

3.2 SimpleUrlHandlerMapping

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.it.action.FirstAction" />  

   <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

      <property name="mappings">

         <props>

            <prop key="first.action">first</prop>

         </props>

      </property>

   </bean>

4 視圖解析器

4.1 UrlBasedViewResolver

<!-- 支持servletjsp視圖解析1,可進行進一步處理,此步可省略, -->

   <!-- viewClass不一樣的配置,能夠解析不一樣的資源-->

   <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">

      <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>

      <!--
      <property name="prefix" value="/jsp/"/>

      <property name="suffix" value=".jsp"/> 
      -->
</bean> 

4.2 InternalResourceViewResolver

做爲UrlBasedViewResolver的子類, 它支持頁面jstl處理.

<!-- 支持servlet與jsp視圖解析,可進行進一步處理,此步可省略, -->

   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

      <!-- 能夠加前綴或後綴 -->    

      <property name="prefix" value="/jsp/"/>

      <property name="suffix" value=".jsp"/>     

   </bean>

4.3 forward:前綴

forward使用轉發方式:   

  return  new ModelAndView("forward:/jsp/first.jsp",map);

  //控制器採用註解,方法在返回字符串時,能夠使用:

 return "forward:/jsp/first.jsp";

4.4 Redirect:前綴

redirect重定向方式  

 return  new ModelAndView("redirect:/jsp/first.jsp",map);

//控制器採用註解,方法在返回字符串時,能夠使用

return "redirect:/jsp/first.jsp";

5 控制器

5.1 controller接口

在spring mvc中控制對象要實現此接口,而且必須實現handRequest方法。此控制器在接收到DispatcherServlet分配置 的請求時,執行handRequest方法,並 返回ModelAndView實例。

public class FirstAction implements Controller {

   @Override

   public ModelAndView handleRequest(HttpServletRequest request,

         HttpServletResponse response) throws Exception {
...

}

5.2 AbstractCommandController

能夠將請求參數值自動設置到command對象中,便於後繼的使用。

5.2.1添加student實體類

public class Student implements Serializable {

   @Override

   public String toString() {

      return "Student [stuId=" + stuId + ", stuName=" + stuName + ", stuPwd="

            + stuPwd + ", stuAge=" + stuAge + "]";
   }

   /**

    *

    */

   private static final long serialVersionUID = 1785249781500211272L;


   private Integer stuId;

  
   private String stuName;

  
   private String stuPwd;
 

   private Integer stuAge;
  

   public Integer getStuId() {

      return stuId;

   }

   public void setStuId(Integer stuId) {

      this.stuId = stuId;

   }

   public String getStuName() {

      return stuName;

   }

   public void setStuName(String stuName) {

      this.stuName = stuName;

   }

   public String getStuPwd() {

      return stuPwd;

   }

   public void setStuPwd(String stuPwd) {

      this.stuPwd = stuPwd;

   }

   public Integer getStuAge() {

      return stuAge;

   }

   public void setStuAge(Integer stuAge) {

      this.stuAge = stuAge;

   }

}

5.2.2建立或修改控制器類

public class StudentAction extends AbstractCommandController {

   public StudentAction(){    

      //配置student對象能夠注入

      setCommandClass(Student.class);

   }

   @Override

   protected ModelAndView handle(HttpServletRequest arg0,

         HttpServletResponse arg1, Object arg2, BindException arg3)

         throws Exception {

      // TODO Auto-generated method stub

      System.out.println("---接收數據---");

      //方式1接收數據,只能每一個屬性都分開接書

      String stuName=arg0.getParameter("stuName");

      String stuPwd=arg0.getParameter("stuPwd");

      System.out.println("方式1接收的數據爲:"+stuName+","+stuPwd);     

      //方式2接收數據,實現對象屬性注入

      Student student = (Student)arg2;

      System.out.println("方式2接收的數據爲:"+student);    

      System.out.println("---調用業務層,進行業務處理,略---");
     
      //封裝視圖數據,有多種方式 ,這裏列表方式 一和方式 二,能夠任選一種:

      //方式一,直接採用request對象封裝

      arg0.setAttribute("rStudent", student);

      //封裝視圖數據,方式二,直接採用Map封裝,默認做用域是request,須要在return的時候做爲參數傳遞。

      Map<String ,Student > map=new HashMap<String, Student>();

      map.put("mStudent", student);

      //默認爲forward方式

      return  new ModelAndView("/jsp/main.jsp",map);

   }

}

5.2.3添加或修改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

   ">  

   <bean id="student" class="cn.it.action.StudentAction"></bean>

   <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

      <property name="mappings">

         <props>

            <prop key="student.action">student</prop>

         </props>

      </property>

   </bean>    

</beans>

5.2.4添加跳轉頁面

/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=zcf&stuPwd=admin">test student</a>

  </body>

</html>

5.3 MultiActionController

5.3.1準備工做

除action類之外,其它繼續使用上面的代碼

5.3.2添加StudentMultiAction.java類

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");

   }

}

5.3.3修改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

   ">

   <!-- 配置控制器,並指定經過methodNameResolver方法名調用相關方法處理相關邏輯-->

   <bean id="studentMultiAction" class="cn.it.action.StudentMultiAction">

      <property name="methodNameResolver" ref="parameterMethodNameResolver"></property>

   </bean>

   <!-- 定義經過方法名調用控制器相關方法的規則 -->

   <bean id="parameterMethodNameResolver"

   class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">

      <!-- 在url中使用do=方法名方式識別相關方法,例如:studentMulti.action?do=add,將調用add方法;這裏的do不是固定的,能夠改成其它 -->

      <property name="paramName" value="do" />

      <!-- 若是沒有指定方法名時,默認 調用控制器的list方法 -->

      <property name="defaultMethodName" value="list" />

   </bean>

   <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

      <property name="mappings">

         <props>

            <prop key="/studentMulti.action">studentMultiAction</prop>

         </props>

      </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/" />

      <property name="suffix" value=".jsp" />

   </bean>

</beans>

5.3.4測試頁面

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>

5.3.5結果顯示頁面

/WEB-INF/jsp/main.jsp關鍵代碼

<body>

  this is WEB-INF/JSP main jsp<br>

  studentName:${requestScope.student.stuName}<br> 

  </body>

6 基於註解的MVC實現

6.1示例1

繼續使用上面的代碼(注意新建項目記得從新配置web.xml文件)

6.1.1修改spring-mvc.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

   ">

   <!--

   DefaultAnnotationHandlerMapping:支持經過url找到相關的action

   AnnotationMethodHandlerAdapter:支持經過url匹配action定義方法

   base-package:定 義掃描的範圍,spring能夠自動去掃描base-pack下面或者子包下面的java文件,若是掃描到有@Component @Controller@Service等這些註解的類,則把這些類註冊爲bean

   -->  

   <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>

6.1.2添加或修改控制類

加入@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(value="/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";

   }

}

6.1.3添加或修改跳轉頁面

<%@ 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/>

  </body>

</html>

6.1.4添加或修改測試頁面

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<html>

  <head>

    <title>My JSP 'index.jsp' starting page</title>

  </head>

 

  <body>

 <a href="student/save.action?stuName=zcf&stuPwd=admin">調用save方法</a>

  <a href="student/update.action?stuName=zcf&stuPwd=admin">調用update方法</a>

  </body>

</html>

6.2示例2(基於annotation-driven的註解)

基於上面的示例,在spring3中能夠進一步簡化配置,取代上面的註解方式.

   步驟以下

   1.使用上面的action類,仍然給類及方法添加@Controller(類)、@RequestMapping(類及方法)註解

   2.本文件頂部添加spring mvc 命名空間的信息(能夠參考org.springframework.web.servlet.config包)

   3.添加下面註解驅動<mvc:annotation-driven>,取代了上面的DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter,並啓動了json的註解

    -->

   修改內容以下:

6.2.1修改配置文件

修改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>

6.3 @SessionAttributes與model.addAttribute使用

Spring 2.0 定義了一個 org.springframework.ui.ModelMap 類,它做爲通用的模型數據承載對象,傳遞數據供視圖所用。咱們能夠在請求處理方法中聲明一個 ModelMap 類型的入參,Spring 會將本次請求模型對象引用經過該入參傳遞進來,這樣就能夠在請求處理方法內部訪問模型對象了在默認狀況下,ModelMap 中的屬性做用域是 request 級別是,也就是說,當本次請求結束後,ModelMap 中的屬性將銷燬,但實際上有時候須要把ModelMap值存放於session中或有時候也能夠從Session中獲取對象的值注入到ModelMap中。

繼續使用上面的代碼

6.3.1 modelMap屬性注入到Session

若是但願在多個請求中共享 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>

6.3.2 session屬性注入到ModelMap

在參數中使用@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構造方法被調用---");

   }

 

   @RequestMapping(value="/save")

   public String save(Student student,ModelMap map){

      System.out.println("---調用業務邏輯進行業務處理---");

     

      Student s2=new Student();

      s2.setStuAge(11);

      s2.setStuId(11111);

      s2.setStuName("testname");

      map.addAttribute("user", s2);

      //map.addAttribute("stu", student); 

     

      //直接使用字符串,返回視圖,進行結果展示等

      return "forward:/jsp/main.jsp";

   }

  

   //同一個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";

   }

}

7 攔截器示例

在綜合示例1上繼續。

7.1攔截器使用

7.1.1編寫攔截器類, 實現HandlerInterceptor接口

LoginInterceptor.java,須要實現HandlerInterceptor接口

public class LoginInterceptor implements HandlerInterceptor {

 

   @Override

   public void afterCompletion(HttpServletRequest arg0,

         HttpServletResponse arg1, Object arg2, Exception arg3)

         throws Exception {

      // TODO Auto-generated method stub

      System.out.println("---訪問請求資源後無論理有沒有異常都必定執行此方法---");

 

   }

 

   @Override

   public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,

         Object arg2, ModelAndView arg3) throws Exception {

      // TODO Auto-generated method stub

      System.out.println("---訪問請求資源後,若是沒有異常,將執行此方法---");

 

   }

 

   @Override

   public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,

         Object arg2) throws Exception {

      // TODO Auto-generated method stub

      System.out.println("---訪問請求資源前執行,若是此方法返回false,將不能訪問請求資源---");

      return true;

   }

}

7.1.2配置文件中添加攔截器

<!-- 配置spring mvc攔截器 -->

   <mvc:interceptors>

   <!-- 默認攔截DispatcherServlet指定的後綴(這裏是.action) -->

      <bean class="cn.it.interceptor.LoginInterceptor"/>

   </mvc:interceptors>

7.3登錄示例

7.3.1編寫及配置攔截器

添加攔截器類及攔截器配置信息,如上面。

7.3.2修改攔截器類preHandle方法

@Override

   public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,

         Object arg2) throws Exception {

      // TODO Auto-generated method stub

      System.out.println("---訪問請求資源前執行,若是此方法返回false,將不能訪問請求資源---");

      if(arg0.getSession().getAttribute("user")==null){

         arg1.sendRedirect(arg0.getContextPath()+"/login.jsp");

         return false;

      }

      return true;

   }

7.3.3編寫登錄頁面 

login.jsp,本頁面已模仿了登錄

<%@page import="cn.it.entity.Student"%>

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<html>

  <head>

    <title>My JSP 'index.jsp' starting page</title>

  </head>

 

  <body> 

   <%

      session.setAttribute("user", new  Student(1001,"zcf","admin",20));

    %> 

    <!-- 這裏正常應該跳到action再到頁面 ,爲了演示,這裏簡略-->

    <a href="index.jsp">已登錄,返回首頁</a>

    

  </body>

</html>

7.4多個攔截器使用

編寫兩個攔截器

HandlerInterceptor1代碼以下,HandlerInterceptor2代碼略

public class HandlerInterceptor1 implements HandlerInterceptor {

 

   @Override

   public void afterCompletion(HttpServletRequest arg0,

         HttpServletResponse arg1, Object arg2, Exception arg3)

         throws Exception {

      System.out.println("HandlerInterceptor1.afterCompletion");

 

   }

 

   @Override

   public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,

         Object arg2, ModelAndView arg3) throws Exception {

      System.out.println("HandlerInterceptor1.postHandle");

 

   }

 

   @Override

   public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,

         Object arg2) throws Exception {

      System.out.println("HandlerInterceptor1.preHandle");

      return false;

   } 
}

配置兩個攔截器

<mvc:interceptors>

   <!-- 默認攔截DispatcherServlet指定的後綴(這裏是.action) -->

   <!-- 配置多個攔截器,將按配置順序執行 -->

      <mvc:interceptor>

         <!-- 若是須要攔截全部,能夠發下配置「/**」表示攔截全部url -->

         <mvc:mapping path="/**"/>

         <bean class="cn.it.interceptors.HandlerInterceptor1"></bean>

      </mvc:interceptor>

      <mvc:interceptor>

         <!-- 若是須要攔截全部,能夠發下配置「/**」表示攔截全部url -->

         <mvc:mapping path="/**"/>

         <bean class="cn.it.interceptors.HandlerInterceptor2"></bean>

      </mvc:interceptor>

   </mvc:interceptors>

訪問資源,查看執行狀況

兩個攔截器的preHandle方法都返回false

只輸出:

Interceptor1.preHandle

第一個返回true,第二個返回false

輸出

Interceptor1.preHandle

Interceptor2.preHandle

Interceptor1.afterCompletion

第一個返回false,第二個返回true

輸出

Interceptor1.preHandle

兩個都返回true

輸出:

Interceptor1.preHandle

Interceptor2.preHandle

save方法注入的student對象:Student [stuId=null, stuName=zcf, stuPwd=admin, stuAge=null]

Interceptor2.postHandle

Interceptor1.postHandle

Interceptor2.afterCompletion

Interceptor1.afterCompletion

8文件上傳示例

8.1 multipartResolver使用

spring-mvc.xml文件添加以下內容:

<!--文件上傳使用, 配置multipartResolver,id名爲約定好的 -->

   <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!-- 配置文件(每次上傳的全部文件總大小)大小,單位爲b, 1024000表示1000kb  -->

      <property name="maxUploadSize" value="1024000" />   

   </bean>

8.2中文亂碼處理

web.xml文件添加以下內容:

<filter>

      <filter-name>encodingFilter</filter-name>

<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

      <init-param>

         <param-name>encoding</param-name>

         <param-value>UTF-8</param-value>

      </init-param>

   </filter>

   <filter-mapping>

      <filter-name>encodingFilter</filter-name>

      <url-pattern>/*</url-pattern>

   </filter-mapping>

若是上邊的方式設置後,仍然有亂碼,請嘗試修改tomcat安裝目錄下的

apache-tomcat安裝目錄\conf\server.xml文件,修改Connector元素內容,添加URIEncoding="UTF-8" ,修改後內容 以下:

<Connector port="8080" protocol="HTTP/1.1"

               connectionTimeout="20000"

               redirectPort="8443" URIEncoding="UTF-8"/>

8.3 properties文件信息注入

PropertiesFactoryBean:用來注入properties類型的配置文件信息

<!--PropertiesFactoryBean對properties文件可用 ,能夠用來注入properties配置文件的信息 -->

   <bean id="uploadProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">

      <property name="location" value="classpath:xxxxx.properties"></property>

   </bean>

8.4文件上傳示例

8.4.1導入包

繼續使用上一章節代碼,並導入文件上傳須要的jar包:commons-fileupload-1.2.2.jar, commons-io-2.0.1.jar

8.4.2修改student實體類,添加文件類型屬性

public class Student implements Serializable {

 

   private static final long serialVersionUID = -5304386891883937131L;

 

   private Integer stuId;

 

   private String stuName;

 

   private String stuPwd;

 

   private Integer stuAge;

 

   private MultipartFile[] files;

 

   public MultipartFile[] getFiles() {

      return files;

   }

 

   public void setFiles(MultipartFile[] files) {

      this.files = files;

   }

 

   public Integer getStuId() {

      return stuId;

   }

 

   public void setStuId(Integer stuId) {

      this.stuId = stuId;

   }

 

   public String getStuName() {

      return stuName;

   }

 

   public void setStuName(String stuName) {

      this.stuName = stuName;

   }

 

   public String getStuPwd() {

      return stuPwd;

   }

 

   public void setStuPwd(String stuPwd) {

      this.stuPwd = stuPwd;

   }

 

   public Integer getStuAge() {

      return stuAge;

   }

 

   public void setStuAge(Integer stuAge) {

      this.stuAge = stuAge;

   }

 

   @Override

   public String toString() {

      return "Student [stuId=" + stuId + ", stuName=" + stuName + ", stuPwd="

            + stuPwd + ", stuAge=" + stuAge + "]";

   }

}

8.4.3編寫上傳頁面

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<html>

  <head>

    <title>My JSP 'index.jsp' starting page</title>

  </head>

 

  <body>    

     <form action="student/save.action" method="post" enctype="multipart/form-data">

       姓名:<input type="text" name="stuName"><br/>

       密碼<input type="password" name="stuPwd"><br>

       請選擇文件:<br/><input type="file" name="files"><br/>

       <input type="file" name="files"><br/>

       <input type="submit" value="文件上傳測試">   

     </form>   

  </body>

</html>

8.4.4編寫控制器

StudentAction.java

@Controller

@RequestMapping("/student")

public class StudentAction {

  

   public StudentAction(){

      System.out.println("---StudentAction構造方法被調用---");

   }

 

   @RequestMapping("/save")

   public String save(Student student) {

      System.out.println("save方法已注入student對象:"+student);

      MultipartFile[] files=student.getFiles();

      for(MultipartFile file:files){

         if(file.isEmpty()){

            System.out.println("文件爲空");

         }else{

            System.out.println("文件不爲空!");

            System.out.println("格式:" + file.getContentType());

            System.out.println("原名:" + file.getOriginalFilename());

            System.out.println("大小:" + file.getSize());

            System.out.println("表單控件的名稱" + file.getName());

            try {

                FileUtils.copyInputStreamToFile(file.getInputStream(), new File("e:/testupload/"+file.getOriginalFilename()));

            } catch (IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }          

         }

      } 

      System.out.println("---調用業務邏輯進行業務處理---");     

      //直接使用字符串,返回視圖,進行結果展示等

      return "forward:/jsp/main.jsp";

   }

}

8.4.5修改配置文件

添加文件處理器CommonsMultipartResolver配置

<?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

   ">

  

   <mvc:annotation-driven></mvc:annotation-driven>

   <context:component-scan base-package="*"/>

  

   <!--文件上傳使用, 配置multipartResolver,id名稱爲約定好的 -->

   <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

      <!-- 配置文件(每次上傳的全部文件總大小)大小,單位爲b, 1024000表示1000kb  -->

      <property name="maxUploadSize" value="1024000" />   

   </bean>

 

</beans>

 

 

8.4.6編寫處理完後跳轉的頁面

main.jsp

 

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<html>

  <head>

      <title>main.jsp</title>  

  </head>

 

  <body>

    /jsp/main.jsp頁面

          student: ${requestScope.student}

  </body>

</html>

 

 

8.4.7文件存放於tomcat目錄下處理方式

l  在項目目錄下新建upload文件夾

l  修改StudentAction.java。

@Controller

@RequestMapping("/student")

public class StudentAction {

  

   public StudentAction(){

      System.out.println("---StudentAction構造方法被調用---");

   }

  

   @Resource

   ServletContext application;

 

   @RequestMapping("/save")

   public String save(Student student) {

      System.out.println("save方法已注入student對象:"+student);

      MultipartFile[] files=student.getFiles();

      System.out.println("真實路徑:"+application.getRealPath("/"));

      for(MultipartFile file:files){

         if(file.isEmpty()){

            System.out.println("文件爲空");

         }else{

            System.out.println("文件不爲空!");

            System.out.println("格式:" + file.getContentType());

            System.out.println("原名:" + file.getOriginalFilename());

            System.out.println("大小:" + file.getSize());

            System.out.println("表單控件的名稱" + file.getName());

           

            try {

                FileUtils.copyInputStreamToFile(file.getInputStream(), new File(application.getRealPath("/")+"upload/"+file.getOriginalFilename()));

            } catch (IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }          

         }

      } 

      System.out.println("---調用業務邏輯進行業務處理---");     

      //直接使用字符串,返回視圖,進行結果展示等

      return "forward:/jsp/main.jsp";

   }

}

其它代碼同上一章節,能夠在application.getRealPath("/")+"upload/"目錄下查看到文件,例如 :

E:\Users\chufeng\Workspaces\MyEclipse10\it\.metadata\.me_tcat\webapps\fileuploadspring\upload查看到上傳的文件。

8.5 文件上傳優化

8.5.1編寫文件上傳工具類

FileUploadUtil.java

@Component(value="fileUploadUtils")  //普通的bean注入

public class FileUploadUtils {

   /*

    * 注入字符串,#{}爲spel語言,其中uploadProperties,是xml配置文件中注入properties文件的bean id,

    *  path爲properties文件的其中一個key ,也能夠經過下邊的set方法注入

    */

  

   @Value("#{uploadProperties.path}")

   private String path;

   //private String path="e:/testupload";

  

   //path也能夠經過set方法注入

// @Value("#{uploadProperties.path}")

// public void setPath(String path) {

//    this.path = path;

// } 

  

   private String getExtName(MultipartFile file){

      return FilenameUtils.getExtension(file.getOriginalFilename());

   }

 

   private String createNewName(MultipartFile file){

      return UUID.randomUUID().toString()+"."+getExtName(file);

   }

  

   public String uploadFile(MultipartFile file){

      try {

         String newName=createNewName(file);

         FileUtils.copyInputStreamToFile(file.getInputStream(), new File(path,newName ));

         return newName;

      } catch (IOException e) {

         // TODO Auto-generated catch block

         e.printStackTrace();

         throw new RuntimeException(e);      

      }    

   }

}

8.5.2修改StudentAction.java

主要修改save方法,使用自已的文件上傳工具類進行文件上傳。

@Controller

@RequestMapping(value="/student")

public class StudentAction {

 

   @Resource

   private ServletContext application;

  

   @Resource

   private FileUploadUtils fileUploadUtils;

  

   public StudentAction(){

      System.out.println("---StudentAction構造方法被調用---");

   }

 

   @RequestMapping(value="/save")

   public String save(Student student,Map<String, Student> paramMap) {

      System.out.println("save方法已注入student對象:"+student);

      MultipartFile[] files=student.getFiles();

      for(MultipartFile file:files){

         if(file.isEmpty()){

            System.out.println("文件爲空");

         }else{

            System.out.println("文件不爲空!");

        

            fileUploadUtils.uploadFile(file);

         }

      } 

      System.out.println("---調用業務邏輯進行業務處理---");     

      paramMap.put("student",student);    

      //直接使用字符串,返回視圖,進行結果展示等

      return "forward:/jsp/main.jsp";

   }

}

 

8.5.3添加upload.properties文件

配置文件上傳後的存放目錄

path=e\:\\testdir\\upload\\

8.5.4修改spring-mvc.xml配置文件

注入配置文件的信息

<!--PropertiesFactoryBean對properties文件可用 ,能夠用來注入properties配置文件的信息 -->

   <bean id="uploadProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">

      <property name="location" value="classpath:upload.properties"></property>

   </bean>

9異常處理

系統異常處理:通常系統各層能夠向上拋出異常,最後再作統一的異常處理

dao-->service-->controler-->統一異常處理

spring mvc提供全局異常處理器進行統一異常處理

9.1自定義異常

自定義異常,對預期的異常進行處理

public class CustomException extends Exception {   

 

   public CustomException()  {}               

    public CustomException(String message) {      

        super(message);             

    }

}

9.2全局異常處理器

須要實現spring mvc 提供的HandlerExceptionResolver接口

public class CustomExceptionResolver implements HandlerExceptionResolver {

 

   @Override

   public ModelAndView resolveException(HttpServletRequest arg0,

         HttpServletResponse arg1, Object arg2, Exception arg3) {

      CustomException customException = null;

      if(arg3 instanceof CustomException){

         customException = (CustomException)arg3;

      }else{

         customException = new CustomException("末知錯誤,請聯繫管理員!");//能夠配置

      }

      return new ModelAndView("forward:/error.jsp","errMsg",customException.getMessage());

   }

 

}

9.3錯誤頁面

error.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

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

<html>

  <head>

   <title>錯誤頁面</title>

  </head> 

  <body>

${requestScope.errMsg}

  </body>

</html>

9.4處理器配置

   <!-- 只要實現了HandlerExceptionResolver接口就是全局異常處理器 -->

<bean class="cn.it.resolver.CustomExceptionResolver"></bean>

9.5訪問頁面

<form action="student/add.action" method="post">

姓名:<input type="text" name="stuName"><br>

密碼:<input type="text" name="stuPass"><br>

<input type="submit" value="add">

</form>

9.6控制器關鍵代碼

@RequestMapping("/add")

   public String add(Student student,ModelMap map) throws Exception{

       throw new CustomException("ddddd");

      /*Integer.parseInt("dd");

      System.out.println("add:"+student);

  

      map.addAttribute("user",student);

     

      return "forward:/jsp/main.jsp";*/

   }

10 json交互

使用上面的源碼,暫時去掉攔截器的登錄權限處理

10.1導入json jar包及jquery的js文件

10.2修改action文件

@Controller

@RequestMapping(value="/student")

public class StudentAction {

 

   public StudentAction(){

      System.out.println("---StudentAction構造方法被調用---");

   }

 

   @RequestMapping("/doAjax")

   @ResponseBody //若是返回json格式,須要這個註解

   public Object doAjax(Student student){

      System.out.println("---doAjax.student:"+student);

      student.setStuName("1001name");

      return student;

   }

} 

10.3修改訪問頁面

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<html>

  <head>

    <title>My JSP 'index.jsp' starting page</title>

    <script type="text/javascript" src="${pageContext.request.contextPath}/jquery-1.3.js"></script>

  <script type="text/javascript">

      $(

         function(){

             $("#bt1").click(

                function(){

                   $.post(

                      "student/doAjax.action",

                      {stuId:1001,stuName:"name1001",stuPwd:"pwd1001",stuAge:20},

                      function(json){alert(json.stuName+"||"+json.stuPwd);},

                      "json"

                   );

                }

             );          

         }

      );

  </script>

  </head>

  <body>

   <button id="bt1" >testajax</button>

  </body>

</html
相關文章
相關標籤/搜索