Sping MVC不使用任何註解處理(jQuery)Ajax請求(基於XML配置)

1. Springjavascript

    Spring框架是一個輕量級的解決方案,是一個潛在的一站式商店,用於構建企業就緒的應用程序。Spring框架是一個Java平臺,爲開發Java應用程序提供全面的基礎架構支持。Spring處理基礎結構,所以您能夠專一於應用程序。Spring使您可以從「普通的Java對象」(POJO)構建應用程序,並將企業服務非侵入性地應用於POJO。此功能適用於Java SE編程模型以及所有和部分Java EE。可是,Spring是模塊化的,容許您僅使用所需的那些部分,而沒必要引入其他部分。您能夠將IoC容器與頂部的任何Web框架一塊兒使用,但也能夠僅使用 Hibernate集成代碼或JDBC抽象層。Spring框架支持聲明式事務管理,經過RMI或Web服務對邏輯的遠程訪問以及用於持久化數據的各類選項。它提供了功能全面的MVC框架,並使您可以將AOP透明地集成到軟件中。Spring被設計爲非侵入式的,這意味着您的域邏輯代碼一般不依賴於框架自己。在您的集成層(例如數據訪問層)中,將存在對數據訪問技術和Spring庫的某些依賴關係。可是,將這些依賴項與其他代碼庫隔離起來應該很容易。Spring的兩大核心特徵:IoC(控制反轉),AOP(面向切面編程)。IoC做用:把對象的控制權交給容器管理。AOP做用:面向切面編程(好比日誌打印),底層使用動態代理實現。Spring框架包含組織爲約20個模塊的功能。這些模塊分爲核心容器,數據訪問/集成,Web,AOP(面向方面​​的編程),檢測,消息傳遞和測試。Spring的整個完整框 架來講,其設計原則則是"對擴展開放,對修改閉合"(OOP設計原則)。固然Spring還有不少強大的功能,這裏先簡單介紹一下,點到爲止。css

2. Spring MVChtml

    Spring MVC是基於Servlet API構建的原始web框架,從一開始就已經包含在就包含在Spring框架中,與Spring框架無縫對接。全稱應該爲Spring Web MVC,其來源於模塊spring-webmvc。可是,一般咱們叫它Spring MVC(習慣)。Spring MVC框架是圍繞一個 DispatcherServlet (核心控制器)來設計的,這個 Servlet會把請求分發給各個處理器,並支持可配置的處理器映射、視圖渲染、本地化、時區 與主題渲染等,甚至還能支持文件上傳。"對擴展開放"是Spring Web MVC框架一個重要的設計原則。Spring Web MVC核心類庫中的一些方法被定義爲 final 方法。Sp'ring MVC的數據綁定很是靈活方便,視圖解析也設計的很是靈活與方便,而且提供了好多功能強大的註解機制。固然,Spring MVC的強大之處不是一兩句話能夠搞定的,咱們應該參考其文檔,而且深刻學習鑽研,最好研究研究源碼。這裏話很少說,點到爲止。前端

3. Spring MVC處理(jQuery)Ajax請求(前臺不發送數據,後臺返回普通字符串)java

   開發環境:Eclipse+Tomcat+Spring MVC+Jackson+JSP+jQuery+Ajaxjquery

   本篇博客比較長,本來是一個小的demo,寫這麼長不值,不,我認爲值,由於我感受本身寫的還能夠(哈哈!裝一波),這些都是筆者一字一句寫的,固然有參考一些東西(本人最討厭複製粘貼),加上本身的理解,涉及到代碼徹底認真實踐過,本身從頭至尾寫一遍,也是對本身知識的積累以及經驗的提高,Spring MVC文檔和Spring文檔等,請你們認真看下去,看完這篇,你不只掌握了Ajax,認識了Spring的好處,還會熟知Spring MVC的執行流程,還會接觸到有趣的日誌打印。固然也能夠免費獲取jar包(有源碼連接),百度都有(基本都免費)。因此普通的一些jar包都是免費的,沒有必要花一些代價去活得開發包。本質來講,框架只是個模板,咱們聽從框架的規範來開發就好了,畢竟使用一些框架是咱們的開發變得簡單高效,筆者認爲仍是應該瞭解一下底層核心的原理比較好,這樣便於在咱們開發的時候遇到bug的時候能夠迅速作出決策和解決。寫博客,我是認真的。c++

(1)搭建環境web

   Eclipse中新建Java Web項目,並把項目部署到Tomcat容器中。下面是項目的結構:ajax

 

項目基本結構很簡單,沒啥可說的。這裏說一下lib裏面的jar包。既然咱們想使用Spring MVC進行開發,必須導入其開發包。上面說了,Spring MVC實際上是集成在Spring中的,因此也是導入Spring開發包。本次使用spring-framework-4.0.0.RELEASE開發包。spring

Spring開發包:spring-aop面向切面編程所用到的包。spring-aspects提供對AspectJ(面向切面的一個框架)的支持,spring-beans包含訪問配置文件,建立和管理Bean以及進行控制反轉和依賴注入操做相關的全部類。spring-core是Spring的核心包(核心工具類)。spring-expression是Spring的表達式語言,spring-jdbc它包含了spring 與 JDBC 數據訪問時進行封裝的全部類,提供使用springjdbc的最佳實現(利用jdbc template)。spring-orm是Spring對DAO特性進行擴展,支持一些ORM(對象關係映射)框架(好比MyBatis和Hibernate等)。spring-test提供了對Junit等測試框架的簡單封裝,這讓咱們在對Spring的代碼進行測試時更加方便和快捷。spring-tx包爲JDBC、Hibernate、JDO、JPA等提供了一致的聲明式的編程式事物管理。spring-web包含web應用研發時用到Spring框架時所須要的的核心類。spring-webmvc包含了Spring webmvc框架相關的全部類。

log4j日誌信息包。不導這個包的話會報錯。

Jasckson三個包(前幾篇博客說過好多遍)。這裏導入Jackson包的緣由說一下。1. Spring MVC內置的json與對象轉換器依賴於Jackson類庫。(底層經過對Jackson的一些方法進行封裝實現)。2. 簡單好用我感受,效率也還能夠。固然也能夠實現本身的json與對象的轉換器(題外話)。

com.springsource三個jar包,主要是爲了提供Spring對Apache的一些服務的支持。Tomcat就是Apache的,不導這3個包的話會報錯。固然,這裏只是導入了spring的一部分經常使用的包,還有其餘的(本身百度下spring開發包,在裏面找找),本次開發也沒把這些spring包所有用到,主要是爲了着重介紹一下。好了,jar包說完了。下面進行開發。這裏不使用任何註解的目的說一下,只是基於XML配置實現。其實咱們使用註解會簡單方便不少(後面會有更新的),此篇文章主要是爲了便於你們熟悉Spring MVC的執行流程,並使用它最最原始的一些配置以及方法。方便你們瞭解更深層次的東西,以及深刻了解Spring MVC一些核心的東西。由於咱們每天使用註解,可是估計咱們都沒了解過註解的機制以及原理,註解有什麼用。以及註解代替了那些咱們以前開發比較繁雜的操做以及方法。有時候咱們研究一些東西,不能只停留在表面會使用就好了,咱們深刻到底層的話會有意想不到的收穫及理解。

(2)編寫jsp文件

   

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

<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>">
<title>I LOVE YOU</title>
<link rel="stylesheet" type="text/css" href="">
<script type="text/javascript" src="index.js"></script>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>


</head>
<body>


<button id="mybutton1" value="springmvc處理ajax請求" onclick="fun1()" >(jquery)ajax請求(不發送數據)</button>
<spand id="show1" />

<br/>
<hr/>

</body>

很簡單,定義了一個按鈕。並調用js文件相關的函數進行處理,<span>標籤是爲了顯示內容。頁面引入自定義的js文件和jQeury的js文件(注意名稱和路徑)。

(3)編寫js文件

/**
 * 
 */
//使用jquery提交ajax請求(不攜帶數據)
function fun1(){
    
    $.ajax({
        
        type:"POST",                    //發送方式
        url:"UserController1",                //請求地址
        data:"",                           //數據爲空
        success:function(data){             //成功後的回調函數
            
            $("#show1").html(data);            //頁面展現內容
            
        }            
    });
}

很簡單,就寫了一個fun1()函數。用來響應按鈕。雖說,討論客戶端不發送數據沒多大意義,這裏咱們仍是討論一下吧。在學習java基礎的時候,咱們還常常討論"空"呢。不是嗎?這裏主要是爲了熟悉一下代碼執行的流程,畢竟咱們學習的過程是由淺入深的。閒話少敘。

(4)編寫controller類

package com.controller;

import java.io.IOException;

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

import org.springframework.web.HttpRequestHandler;

public class UserController1 implements HttpRequestHandler{


    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setCharacterEncoding("UTF-8");    
        String str = "我是一個 springmvc";        
        try {
            response.getWriter().print(str);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    
    }    
}

這裏定義了一個controller類,而且實現了HttpRequestHandler接口,並實現接口中的抽象方法。方法中定義了一個字符串,利用response獲取打印流進行輸出便可。Spring MVC中。通常在咱們編寫controller(也就是一個handler,用來處理客戶端的請求),要能被Sping MVC識別它是一個controller類,由於這裏沒有用到註解。因此咱們有2種方法。

第一種:編寫controller類,實現org.springframework.web.servlet.mvc.Controller接口,而後交給核心控制器調用相對應的處理器適配器進行處理。不過,實現了Controller,就必須實現其中的抽象方法public abstract ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)。這個方法必須返回一個ModelAndView對象,而咱們所做的是對字符串數據和json數據的處理。因此在這裏咱們並無選擇實現Controller接口。
第二種:編寫controller類,實現org.springframework.web.HttpRequestHandler接口,而後交給核心控制器調用相應的處理器適配器進行處理,並實現其中的抽象方法。本身能夠百度一下Spring MVC的執行流程,這裏很少說。

public abstract void handleRequest(HttpServletRequest request, HttpServletResponse response) 咱們注意到,這個方法是沒有返回值的,因此就方便了咱們對字符串數據和json數據的處理。注意到有2個參數request和response(這是Servlet的東西)。Spring MVC支持的支持的參數類型:

HttpServletRequest 對象,HttpServletResponse 對象,HttpSession 對象,Model/ModelMap 對象。這裏咱們用到了其中的2個。

(5)配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>MySpringMVCAjax</display-name>
  <welcome-file-list> 
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  
  
  <!-- 配置springmvc核心控制器 -->
  
  <servlet>
      <servlet-name>springmvc</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:springmvc.xml</param-value>
      </init-param>    
        
  </servlet>
  
  <servlet-mapping>
      <servlet-name>springmvc</servlet-name>
      <url-pattern>/</url-pattern>
      
  </servlet-mapping>
  
  
  <!-- 對靜態資源進行放行 -->
  <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/static/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.css</url-pattern>
    </servlet-mapping>
  
  
  
  
  <!-- 配置編碼過濾器 -->
  
 <filter>
      <filter-name>SpringCharacterEncodingFilter</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> 
       
       <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  
  <filter-mapping>         
      <filter-name>SpringCharacterEncodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>  
  
</web-app>

這裏咱們配置了三個東西。

第一個,配置Spring核心控制器。Sping MVC核心控制器(前端控制器或中央處理器)org.springframework.web.servlet.DispatcherServlet,DispatcherServlet 其實就是個 Servlet (它繼承自 HttpServlet 基類),一樣也須要在你 web應用的 web.xml 配置文件下聲明。你須要在 web.xml 文件中把你但願 DispatcherServlet 處理的請求映射到對應的URL上去。這就是標準的Java EE Servlet配 置。DispatcherServlet就是一個Sping MVC處理請求的一箇中央處理器,負責調度處理器映射器,處理器適配器以及視圖解析器。配置初始化參數來加載Sping MVC的主配置文件springmvc.xml,這裏咱們把它放在src目錄下。

第二個,給靜態資源放行。這裏注意一下。咱們在覈心控制器<url-pattern>標籤下配置的是 / ,表示全部訪問的url都交給核心控制器去處理,這樣致使有可能加載不到靜態資源文件(js,css,img)。解決辦法:

第一種:在springmvc.xml文件中配置<mvc:default-servlet-handler /><!-- 表示對全部靜態資源進行放行 -->(比較高級的方法)

 

 

第二種:對靜態資源進行放行,如咱們web.xml所示。固然,也能夠在spring.xml文件進行放行,語法爲:

<resources location="/js/" mapping="/js/**" />
<resources location="/css/" mapping="/css/**" />
<resources location="/images/" mapping="/images/**" />

這裏使用web.xml對靜態資源進行放行,主要是由於這個方法簡單易懂。後面我會對博客內容進行更新升級,再採起比較高級的方法。

第三種:配置核心控制器時,把<url-pattern>標籤設置爲 *.do 或者 .action就行了。表示以.do結尾的或者以.action結尾的URL都由前端控制器DispatcherServlet來解析。這種方法也能夠,可是到時訪問路徑的時候要加上這個後綴,看起來不太舒服(有一點強迫症的人應該懂)。固然筆者估計沒有吧。筆者只是採起一些簡單說不上高效的方法。

第三個,就是配置spring提供編碼過濾器。web.xml配置的編碼過濾器爲了防止前端傳入的中文數據出現亂碼問題,使用Spring提供的編碼過濾器來統一編碼。配置爲UTF-8。固然也可使用GBK等其餘編碼。GBK編碼方式的編碼是以中國國情而創造的,在國際上的兼容性很差,這也是爲何大多數的網頁是使用UTF-8編碼而不是GBK。UTF-8好處:兼容ASCII,存儲英文文件都是單字節,文件小。在eclipse中把項目的編碼也設置爲UTF-8,JSP頁面中字符編碼也設置爲UTF-8。瀏覽器網頁字符編碼也設置爲UTF-8。反正就是通通UTF-8的樣子。作這麼多主要是統一編碼,解決中文亂碼亂碼問題。由於之前使用servlet和struts2的時候,常常出現中文亂碼問題,讓人摸不着什麼頭腦。因此。Spring提供的這個編碼過濾器就比較方便好用了。因此說Spring是一個神奇的東西。咱們研讀一下Spring源碼,看看Spring開發的文檔,就能夠汲取一些精華(精髓)。Spring提供的編碼過濾器,org.springframework.web.filter.CharacterEncodingFilter類,注意把路徑寫正確。初始化參數(也就是編碼)encoding爲UTF-8。Spring裏的字符過濾器CharacterEncodingFilter是針對請求的,forceEncoding=true是意思是指不管客戶端請求是否包含了編碼,都用過濾器裏的編碼來解析請求。forceEncoding默認爲false。forceEncoding爲true效果: request.setCharacterEncoding("UTF-8");forceEncoding爲false的效果:

 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8")。 <url-pattern>標籤配置的/*表明過濾全部請求,從而將編碼設置爲UTF-8。好了。web.xml到此結束。其實有時候咱們只是開發一個簡單的小例子demo,看起來很簡單。可是咱們要了解底層究竟是怎麼實現的。好比Java的底層,JVM(Java虛擬機)用c/c++編寫,Java類庫用Java語言編寫。還有好比native本地方法,其底層本質也是c/c++編寫的,Java只是調用了它的接口。這也就解釋了爲何native方法效率通常比較高。那麼問題來了,c語言用什麼編寫的 ? 這個能夠自行谷歌或百度,這裏很少說。固然,一個項目或者工做的執行流程咱們也必須熟知。此次開發看起來很簡單,可是咱們把涉及到的知識內容都會爲你們詳細講解,而且都是本人一字一句通過推敲實踐進行編寫的。固然,本人也是菜鳥一枚。知識有限。可是咱們能夠通過學習來獲取更多的知識,提高本身的能力,從而達到人生的巔峯。很少說了(跑題了,哈哈!)。

(6)配置springmvc.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"  
      xsi:schemaLocation="  
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/mvc 
      http://www.springframework.org/schema/mvc/spring-mvc.xsd  
      http://www.springframework.org/schema/context 
      http://www.springframework.org/schema/context/spring-context.xsd">
      
    
    
    <!-- 配置user實體類 -->
    
    <bean id="user" class="com.pojo.User" />
    
    
    <!-- 配置handler-->
    <bean name="/UserController1" class="com.controller.UserController1" /> 
    <bean name="/UserController2" class="com.controller.UserController2" /> 
    <bean name="/UserController3" class="com.controller.UserController3" />  
    
    <!-- 配置處理器映射器 -->
    
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
        
     <!-- 配置處理器適配器 -->   
     <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/> 
         
     
     <!-- 配置json與對象的轉換器 -->
     
     <bean id="myconverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
              
     <!-- 配置視圖解析器 -->   
     
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          
         <property name="prefix" value="/"></property>
      
        <property name="suffix" value=".jsp"></property>
          
      </bean>

</beans>

springmvc.xml是本次開發的主配置文件。經過觀察得知,頂層標籤<beans>包含了許多bean模塊。Spring Bean其實就是是被實例的,組裝的及被Spring 容器管理的Java對象。一個bean至關於一個實體類對象,經過IoC(控制反轉,也叫依賴注入)咱們能夠把bean注入到容器當中,交給Spring容器管理(好比bean的實例化)。這樣作的目的其實解耦合。由於軟件設計的原則就是高內聚,低耦合。Spring默認的bean實例是單例的,咱們能夠用scope屬性來設置bean的做用域。scope能夠接受Singleton(單例模式,每次獲取bean只有一個實例)、prototype(原型模式,每次獲取bean都會產生新的實例)、request(每次HTTP request請求都會產生不一樣的Bean實例)、session(每次HTTP session請求都會產生不一樣的Bean實例)、global session (每一個全局的HTTPSession對應一個Bean實例。僅在portlet Context的時候纔有效。)5個值。咱們經常使用單例模式,由於建立對象自己代價比較高,耗費資源,單例的自己也知足咱們的需求了。固然咱們也能夠根據不一樣的需求設置不一樣的scope,這本無可厚非。還有,注意一下引入的xsd文件,Spring文件中的引用的xsd文件是用於校驗xml文件的格式用的。Spring默認在啓動時是要加載XSD文件來驗證xml文件的。至關因而約束文件。這裏咱們引入了三個xsd文件,spring-beans-xsd包含對bean的解釋。sprng-mvc.xsd包含了對<mvc>等標籤的解釋,spring-context.xsd包含對context的解釋,這裏咱們其實只用到了spring-beans.xsd約束文件。

咱們具體看一下配置了什麼東西。

1. 把User實體類注入到容器(下面會貼User類的代碼,這裏暫時還沒用到)。至關因而經過<bean>標籤來裝配一個User類,咱們就能夠經過獲取bean來達到獲取User實體對象的目的。設置bean的id(一個bean的惟一標識)和class(類的全包路徑 包.類)。

2. 配置controller(也就是handler,處理客戶端請求)。這裏咱們配置了好三個controller。咱們看UserController1(對應上面的方法UserController1)的配置,配置了一個name和class。Spring MVC要識別請求的url,就是經過調用處理器映射器獲取到這個name的名稱,找到controller類,而後交給處理器設配器去處理controller。至關於就是映射路徑。注意名稱前要加上/  否則沒法識別。這裏咱們設置name=」/UserController1「和類名保持一致(爲了方便),固然也能夠起其餘名字,別忘了/,前臺提交的url和此處name的名稱要保持一致。class爲UserController1的全包類路徑。

3. 配置處理器映射器BeanNameUrlHandlerMapping。不須要指定id,只配置全類路徑便可,即class。這個處理器映射器,將bean的name做爲url進行查找,須要在配置Handler時指定bean的 name(url)。

    查看spring-webmvc包下面的DispatcherServlet.properties 資源文件:

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
    org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
 org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
Spring MVC的處理器映射器,經常使用的有2個,一個是org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,繼承了
AbstractDetectingUrlHandlerMapping抽象類,它又向上繼承了AbstractUrlHandlerMapping抽象類,它又向上繼承了AbstractHandlerMapping,
AbstractHandlerMapping抽象類實現了HandlerMapping接口。

另外一個是org.springframework.web.servlet.handler.SimpleUrlHandlerMapping,繼承了AbstractUrlHandlerMapping抽象類,
AbstractUrlHandlerMapping繼承了AbstractHandlerMapping抽象類,AbstractHandlerMapping實現了org.springframework.web.servlet.HandlerMapping
接口。觀察資源文件發現,BeanNameUrlHandlerMapping是Spring MVC的默認處理器映射器,這裏咱們就使用這個。若要使用SimpleUrlHandlerMapping,
咱們根據它的語法來就好了。能夠這樣配置:
bean id="UserController1" class="com.controller.UserController1" />

<!-- 簡單URL配置處理器映射器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="/UserController1">UserController1</prop>
        </props>
    </property>
</bean>

固然這兩種處理器映射器配置能夠並存,核心控制器會正確的去判斷 url 用哪一個 Handler 去處理。

注意這個上面資源文件的處理器映射器DefaultAnnotationHandlerMapping,經過查看源碼,它已經被廢棄了。被拋棄的感受很差受啊。

(估計DefaultAnnotationHandlerMapping的心裏是崩潰的)。

4. 配置處理器適配器。不須要指定id,class爲全類路徑。核心控制器調用處理器映射器找到了Controller類,那麼誰來處理這個Controller呢。那麼此時處理器適配器就閃亮登場了。什麼是處理器適配器呢。且聽下回分解,本章完。。。(皮一下)。經過觀察以上資源文件。咱們發現。Spring MVC的處理器適配器,經常使用的有2個。

一個是org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,一個是org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter

這2個類都實現了HandlerAdapter接口。SimpleControllerHandlerAdapter處理的Handler必須實現Conreoller接口,通常返回一個ModelAndView對象。

HttpRequestHandlerAdapter處理的Handler必須實現HttpRequestHandler接口,通常用來處理字符串或者json數據。由於其抽象方法沒有返回值。AnnotationMethodHandlerAdapter已經廢棄了,很少說。固然兩種適配器能夠共存,配置不一樣的映射器找到不一樣的controller。

Spring MVC默認的處理器適配器是HttpRequestHandlerAdapter  。

5. 配置視圖解析器。不須要指定id,class爲全類路徑。咱們這裏用的是InternalResourceViewResolver,配置它的class路徑,注意有2個屬性。prefix表示返回視圖頁面的前綴,suffix表示返回視圖頁面的後綴。好比通常咱們要視圖解析完成後返回一個頁面index.jsp時,prefix至關於配置的是其根目錄(在哪兒),suffix就是.jsp,這樣在咱們使用註解進行開發的時候,只須要返回一個字符串"index"就好了。上面那樣配置,表示在 Handler 中只須要返回在 WebContent根目錄下的jsp 文件名就ok了(爲了簡單方便,開發比較高效)。視圖解析器做用它負責將一個表明邏輯視圖名的字符串 (String)映射到實際的視圖類型 View 上。經過以上資源文件發現。注意HandlerExceptionResolver處理器異常解析器。它負責將捕獲的異常映射到不一樣的視 圖上去,此外還支持更復雜的異常處理代碼。Spring MVC的視圖解析器這裏介紹3種:

第一種:使用ViewResolver接口解析視圖

org.springframework.web.servlet.view.InternalResourceViewResolver類,經過連續向上繼承,實現org.springframework.web.servlet.ViewResolver接口。在實際應用中InternalResourceViewResolver也是使用的最普遍的一個視圖解析器。本次開發就用的是這個視圖解析器。這個比較經常使用。InternalResourceViewResolver解析器能夠解釋爲內部資源視圖解析器。InternalResourceViewResolver會把返回的視圖名稱都解析爲InternalResourceView對象,InternalResourceView會把Controller處理器方法返回的模型屬性都存放到對應的request屬性中,而後經過RequestDispatcher在服務器端把請求forword重定向到目標URL。

 

接口中的方法:經過傳來的參數解析視圖,並返回一個View對象。注意Handler類實現Conteoller接口方法時,就返回了一個ModelAndView對象。ModelAndView 是SpringMVC 框架的一個底層對象,包括 Model 和 View。

 

public abstract interface ViewResolver
{
public abstract View resolveViewName(String paramString, Locale paramLocale)
throws Exception;
}

 

第二種:使用RequestToViewNameTranslator接口解析視圖。DefaultRequestToViewNameTranslator爲這個接口的實現子類。

這個接口定義了一個抽象方法

public abstract interface RequestToViewNameTranslator
{
public abstract String getViewName(HttpServletRequest paramHttpServletRequest)
throws Exception;
}

表示根據request請求返回一個視圖名稱的字符串。

第三種:使用FlashMapManager接口解析視圖。SessionFlashMapManager爲這個接口的實現子類。

 

FlashMap管理器。它可以存儲並取回兩次請求之間 的 FlashMap 對象。後者可用於在請求之間傳遞數據,一般 是在請求重定向的情境下使用。

這個接口定義的方法:本身看看就行了,在這裏不作過多介紹。

public abstract interface FlashMapManager
{
public abstract FlashMap retrieveAndUpdate(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse);

public abstract void saveOutputFlashMap(FlashMap paramFlashMap, HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse);
}

Map確定時用來保存數據的。RedirectView在頁面跳轉,數據的保存依賴於FlashMap和FlashMapManger,FlashMapManger在容器初始化時被填入,而FlashMap從Manger能夠獲取。

5. 配置json與對象的轉換器。這裏暫時用不到。下面會解釋。先跳過。其實Spring MVC內置的json與對象的轉換器底層仍是用Jasckson類庫實現。

(7)配置log4j.properties日誌文件

   

### set log levels ###
log4j.rootLogger = INFO , console , D
 
### console ###  
log4j.appender.console = org.apache.log4j.ConsoleAppender  
log4j.appender.console.Target = System.out  
log4j.appender.console.layout = org.apache.log4j.PatternLayout  
log4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH\:mm\:ss} [%p]-[%c] %m%n  
 
 
### log file ###  
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File =../logs/IvaDubboWeb-info.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = INFO 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n


### out zhiding log file ###
log4j.logger.haha = INFO, haha
log4j.additivity.haha = false
log4j.appender.haha = org.apache.log4j.DailyRollingFileAppender
log4j.appender.haha.File =D:/logs/mylog.log
log4j.appender.haha.Append = true
log4j.appender.haha.Threshold = INFO
log4j.appender.haha.layout = org.apache.log4j.PatternLayout
log4j.appender.haha.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n

Log4j簡單介紹:

Log4j是Apache的一個開源項目,經過使用Log4j,咱們能夠控制日誌信息輸送的目的地是控制檯、文件、GUI組件,甚至是套接口服務器、NT的事件記錄器、UNIX Syslog守護線程等;咱們也能夠控制每一條日誌的輸出格式;經過定義每一條日誌信息的級別,咱們可以更加細緻地控制日誌的生成過程。Log4j有三個主要的組件:Loggers(記錄器),Appenders (輸出源)和Layouts(佈局)。這裏可簡單理解爲日誌類別,日誌要輸出的地方和日誌以何種形式輸出。綜合使用這三個組件能夠輕鬆地記錄信息的類型和級別,並能夠在運行時控制日誌輸出的樣式和位置。

1.  配置根logger,日誌輸出級別爲INFO級別。log4j的輸出級別:TRACE < DEBUG < INFO < WARN < ERROR < FATAL。比INFO級別高的也會打印輸出,比INFO低的不會輸出。

2. 配置console,在eclipse的控制檯打印日誌信息。

3. 配置輸出到文件。一個是輸出到通常性文件中,另外一個是輸出到咱們指定的文件中。很簡單。(筆者對log4j還琢磨了半天,主要是瞭解日誌打印究竟是什麼玩意兒)。

對上面log4j簡單測試一下(注意要導入log4j開發包和單元測試JUinit包,並把log4j.properties文件放在src目錄下)。打印到控制檯:

package com.log4j;

import org.apache.log4j.Logger;
import org.junit.Test;

public class Log4jTest {

    @Test
    public void test() {

        // BasicConfigurator.configure(); //自動快速地使用缺省Log4j環境。

        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.info("log4j");
        logger.info("是");
        logger.error("什麼");
        logger.debug("呢");

    }

    
}

運行效果:debug級別比INFO低,無輸出。

打印日誌到指定文件:把方法放在一個類中就好了

@Test
    public void test1() {

        // BasicConfigurator.configure(); //自動快速地使用缺省Log4j環境。

        Logger logger = Logger.getLogger("haha");
        logger.info("我");
        logger.info("要");
        logger.info("學");
        logger.info("java");
        logger.info("哈");
        logger.info("哈");
    }

運行效果:

 

(8)運行程序

   啓動Tomcat服務器,在瀏覽器地址欄上輸入:localhost/MySpringAjax/  

   完美運行,不作過多解釋。

 

 4. Spring MVC處理(jQuery)Ajax請求(前臺發送key/value數據,後臺返回json數據)

(1)編寫jsp頁面

   重複步驟咱們一筆帶過就行了。好比jar包都已經導好了,還有log4j.properties文件,springmvc.xml主配置文件,這些都是項目公用的。這裏就很少說了。

 

<button id="mybutton2" value="springmvc處理ajax請求" onclick="fun2()" >發送數據格式爲key/value的(jquery)ajax請求</button>
<spand id="show2" />

 

(2)編寫js頁面

 

//使用jquery提交key/value數據(ajax請求)

function fun2(){
    
    $.ajax({
        
        type:"POST",
        url:"UserController2",
        data:"username=wly&password=1314520",        //key/value數據
        success:function(data){
            
            $("#show2").html(data.username+" "+data.password);
            
        }            
    });

}

 

(3)編寫User類

package com.pojo;

public class User {

    private String username;

    private String password;
    

    private Integer age;
    
    

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User [username=" + username + ", password=" + password + ", age=" + age + "]";
    }    
}

   這裏咱們給User類增長了一個age屬性,前臺發送的仍是username和password。(增長age屬性主要是爲了對User類進行從新的一些操做,就是方便咱們演示不一樣的效果)。

(4)配置web.xml文件

   上面已經配置好了,配置三個東西。1. Spring MVC核心控制器;2. 對靜態資源進行放行;3. 配置Spring MVC提供的編碼過濾器

(5)配置springmvc.xml文件

   上面已經配置好了,須要配置的bean有,User實體類,Controller類,處理器映射器,處理器適配器,視圖解析器,json與對象的轉換器(本次開發就調用Spring MVC內置的json與對象的轉換器進行進行json數據與對象的轉換)。配置json與對象轉換器的id(惟一識別這個bean)和class(全包類路徑)。

 

 <!-- 配置json與對象的轉換器 -->
     
     <bean id="myconverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>

 

 

 

這裏咱們看一下配置的Spring MVC內置的json與對象的轉換器,這裏咱們使用的是MappingJackson2HttpMessageConverter類。咱們先介紹一下Spring MVC的2個經常使用的消息轉換器。

1. org.springframework.http.converter.json.MappingJackson2HttpMessageConverter消息轉換器類,這個類繼承了AbstractHttpMessageConverter<T>抽象類,而這個抽象類實現了package org.springframework.http.converter.HttpMessageConverter<T>接口。咱們看一下這個接口的抽象方法。

 

package org.springframework.http.converter;

import java.io.IOException;
import java.util.List;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;

public abstract interface HttpMessageConverter<T>
{
  public abstract boolean canRead(Class<?> paramClass, MediaType paramMediaType);
  
  public abstract boolean canWrite(Class<?> paramClass, MediaType paramMediaType);
  
  public abstract List<MediaType> getSupportedMediaTypes();
  
  public abstract T read(Class<? extends T> paramClass, HttpInputMessage paramHttpInputMessage)
    throws IOException, HttpMessageNotReadableException;
  
  public abstract void write(T paramT, MediaType paramMediaType, HttpOutputMessage paramHttpOutputMessage)
    throws IOException, HttpMessageNotWritableException;
}

/* Location:           F:\eclipseWorkspace\myworkspace\MySpringMVCAjax\WebContent\WEB-INF\lib\spring-web-4.0.0.RELEASE.jar
 * Qualified Name:     org.springframework.http.converter.HttpMessageConverter
 * Java Class Version: 6 (50.0)
 * JD-Core Version:    0.7.0.1
 */

 

通常來講,咱們在Spring MVC實現自定義的json與對象的轉化器時,就應該實現HttpMessageConverter<T>這個接口。MediaType在網絡協議的消息頭裏面叫作Content-Type,使用兩部分的標識符來肯定一個類型,咱們用的時候其實就是爲了代表咱們傳的東西是什麼類型。MediaType類就是一個媒體類型,定義了好多靜態常量,定義的就是數據的格式。至關於ContentType。靜態常量值有application/json,text/html,image/png,application/xml等等。有好多呢。本身去看源碼好了。canRead()方法表示檢測能不能把json數據轉化爲java對象,canWrite表示檢測能不能把java對象轉化爲json數據。read()方法用來讀,表示把json數據轉化爲java對象,write方法表示寫,把java對象轉換爲json數據輸出。MappingJackson2HttpMessageConverter是HttpMessageConverter<T>的實現子類,先來看一下AbstractHttpMessageConverter<T>抽象類定義的2個重要的抽象方法。實現HttpMessageConverter<T>接口中的read()和write()抽象方法。可是調用的仍是本類定義的2個抽象方法。再交給起子類去實現這2個方法。

 

/*     */   public final T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
/*     */     throws IOException
/*     */   {
/* 158 */     return readInternal(clazz, inputMessage);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public final void write(final T t, MediaType contentType, HttpOutputMessage outputMessage)
/*     */     throws IOException, HttpMessageNotWritableException
/*     */   {
/* 170 */     final HttpHeaders headers = outputMessage.getHeaders();
/* 171 */     if (headers.getContentType() == null) {
/* 172 */       if ((contentType == null) || (contentType.isWildcardType()) || (contentType.isWildcardSubtype())) {
/* 173 */         contentType = getDefaultContentType(t);
/*     */       }
/* 175 */       if (contentType != null) {
/* 176 */         headers.setContentType(contentType);
/*     */       }
/*     */     }
/* 179 */     if (headers.getContentLength() == -1L) {
/* 180 */       Long contentLength = getContentLength(t, headers.getContentType());
/* 181 */       if (contentLength != null) {
/* 182 */         headers.setContentLength(contentLength.longValue());
/*     */       }
/*     */     }
/* 185 */     if ((outputMessage instanceof StreamingHttpOutputMessage)) {
/* 186 */       StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage)outputMessage;
/*     */       
/*     */ 
/* 189 */       streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body()
/*     */       {
/*     */         public void writeTo(final OutputStream outputStream) throws IOException {
/* 192 */           AbstractHttpMessageConverter.this.writeInternal(t, new HttpOutputMessage()
/*     */           {
/*     */             public OutputStream getBody() throws IOException {
/* 195 */               return outputStream;
/*     */             }
/*     */             
/*     */             public HttpHeaders getHeaders()
/*     */             {
/* 200 */               return AbstractHttpMessageConverter.1.this.val$headers;
/*     */             }
/*     */           });
/*     */         }
/*     */       });
/*     */     }
/*     */     else {
/* 207 */       writeInternal(t, outputMessage);
/* 208 */       outputMessage.getBody().flush();
/*     */     }
/*     */   }
/*     */   
/*     */ 

/*     */   protected abstract T readInternal(Class<? extends T> paramClass, HttpInputMessage paramHttpInputMessage)
/*     */     throws IOException, HttpMessageNotReadableException;
/*     */   
/*     */   protected abstract void writeInternal(T paramT, HttpOutputMessage paramHttpOutputMessage)
/*     */     throws IOException, HttpMessageNotWritableException;
/*     */ }

 

接下來,MappingJackson2HttpMessageConverter就出現了,其實現了抽象類定義的方法readInternal()和writeInternal,經過觀察發現。readInternal()方法其調用了ObjectMapper(Jackson核心操做類)的readValue()方法,表示將json字符串轉化爲java對象。read()方法實際上是本類擴展的一個方法,做用和readInternal同樣。writeInternal()方法其調用了ObjectMapper(Jackson核心操做類)的writeValue()方法,表示將java對象轉化爲json字符串。

公共接口HttpInputMessage,擴展HttpMessage,表示HTTP輸入消息,由表頭 和可讀主體組成。一般由服務器端的HTTP請求句柄或客戶端的HTTP響應句柄實現。其實現子類ServletServerHttpRequest封裝了請求頭header和請求體body。

公共接口HttpOutputMessage ,擴展HttpMessage表示HTTP輸出消息,由標頭 和可寫主體組成。一般由客戶端的HTTP請求句柄或服務器端的HTTP響應句柄實現。其實現子類ServletServerHttpResponse至關於封裝了響應頭和響應體。

 

/*     */   protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
/*     */     throws IOException, HttpMessageNotReadableException
/*     */   {
/* 168 */     JavaType javaType = getJavaType(clazz, null);
/* 169 */     return readJavaType(javaType, inputMessage);
/*     */   }
/*     */   
/*     */ 
/*     */   public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
/*     */     throws IOException, HttpMessageNotReadableException
/*     */   {
/* 176 */     JavaType javaType = getJavaType(type, contextClass);
/* 177 */     return readJavaType(javaType, inputMessage);
/*     */   }
/*     */   
/*     */   private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) {
/*     */     try {
/* 182 */       return this.objectMapper.readValue(inputMessage.getBody(), javaType);
/*     */     }
/*     */     catch (IOException ex) {
/* 185 */       throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   protected void writeInternal(Object object, HttpOutputMessage outputMessage)
/*     */     throws IOException, HttpMessageNotWritableException
/*     */   {
/* 193 */     JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 198 */     JsonGenerator jsonGenerator = this.objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
/*     */     
/*     */ 
/*     */ 
/* 202 */     if (this.objectMapper.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
/* 203 */       jsonGenerator.useDefaultPrettyPrinter();
/*     */     }
/*     */     try
/*     */     {
/* 207 */       if (this.jsonPrefix != null) {
/* 208 */         jsonGenerator.writeRaw(this.jsonPrefix);
/*     */       }
/* 210 */       this.objectMapper.writeValue(jsonGenerator, object);
/*     */     }
/*     */     catch (JsonProcessingException ex) {
/* 213 */       throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
/*     */     }
/*     */   }
/*     */   

2. org.springframework.http.converter.StringHttpMessageConverter消息轉換器類,繼承了AbstractHttpMessageConverter<String>抽象類,而這個抽象類實現了HttpMessageConverter<T>接口。主要用於以讀寫字符串。其實就是一個消息轉換器。默認狀況下,該轉換器支持全部介質類型(*/*),並用寫Content-Typetext/plain。能夠經過設置supportedMediaTypes該屬性來覆蓋。原理:經過輸入和輸出流的方式進行讀和寫操做。

設計哲學:StringHttpMessageConverter的哲學即是:你想要什麼類型的數據,我便發送給你該類型的數據。

其實很簡單的道理,好比我但願接受的數據類型是Accept: application/json;charset=UTF-8,發送的數據類型Content-Type: application/json;charset=UTF-8 固然也要保持一致。至關於以什麼格式輸入的字符串,就得以相應的格式進行轉換。這裏要深刻了解的話請看具體源碼。

 

 

 

(6)配置編寫Controller類

 

package com.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.HttpRequestHandler;

import com.pojo.User;


public class UserController2 implements HttpRequestHandler{

    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setCharacterEncoding("UTF-8");
        
        //加載spring.xml文件初始化ApplicationContext
        ApplicationContext ac = new ClassPathXmlApplicationContext("springmvc.xml");
        //獲得User類的實例(對象),能夠看出IoC(把對象交給容器管理)機制(工廠模式+Java反射機制)
        User user = (User) ac.getBean("user");
        //獲取username和password,進行手動封裝
        String username=request.getParameter("username");
        String password=request.getParameter("password");    
        user.setUsername(username);
        user.setPassword(password);    
        //獲取消息轉換器MappingJackson2HttpMessageConverter類對象,實現了HttpMessageConverter接口
        HttpMessageConverter converter= (HttpMessageConverter) ac.getBean("myconverter");        
        //獲取媒體類型,傳入的是"application/json;charset=UTF-8"這裏咱們直接new
        MediaType mediaType=new MediaType(MediaType.APPLICATION_JSON, null);        
        //實例化響應信息類。ServletServerHttpResponse是HttpOutputMessage的實現子類
        //這裏直接new,要是配置到springmvc裏面顯得配置文件冗餘。
        HttpOutputMessage out=new ServletServerHttpResponse(response);            
        converter.write(user, mediaType, out);
    }
}

 

首先要獲取2個bean,一個是配置的轉換器,一個是User類對象。經過加載spring.xml初始化Spring的一個應用上下文ApplicationContext對象,調用方法getBean("id")。咱們能夠得到bean對象,其實這是經過Java反射機制完成的。這個傳入的id是我咱們spring.xml中所配置的id,注意必定要對應,保持一致。關於獲取Spring Bean還有其餘方法,本身能夠百度。獲得user對象後,手動進行封裝。代碼都有註解,很容易理解。MediaType.APPLICATION_JSON是一個靜態常量。MediaType類中定義的這個靜態常量(還有好多,這裏只列舉一個)public static final MediaType APPLICATION_JSON = valueOf("application/json")。HttpOutputMessage封裝輸出的信息。最後經過消息轉換器的write()方法把對象轉化爲json數據進行輸出,響應客戶端。

ApplicationContext是一箇中央接口,爲應用程序提供配置。在應用程序運行時,它是隻讀的,可是若是實現支持,則能夠從新加載。

ApplicationContext提供:

1. 用於訪問應用程序組件的Bean工廠方法。繼承自ListableBeanFactory。

2.以通用方式加載文件資源的能力。從ResourceLoader接口繼承。

3.將事件發佈給註冊的偵聽器的能力。從ApplicationEventPublisher接口繼承。

4.解決消息的能力,支持國際化。從MessageSource接口繼承。

5.從父上下文繼承。在後代上下文中的定義將始終優先。例如,這意味着整個Web應用程序均可以使用單個父上下文,而每一個servlet都有其本身的子上下文,該子上下文獨立於任何其餘servlet的子上下文。

存在問題:這裏的User類對象其實最後仍是經過Spring容器new的實例(反射),徹底不用註解的話,怎麼自動完成User類對key/value類型數據的封裝呢,咱們怎麼獲得user類呢。有一種思路(深刻了解spring mvc的參數綁定機制,這就要又得研究研究源碼了)。不知道你們還有什麼好的辦法。歡迎交流哈。

 

(7)運行程序

 

5. Spring MVC處理(jQuery)Ajax請求(前臺發送json數據,後臺返回json數據)

(1)編寫jsp頁面

<button id="mybutton3" value="springmvc處理ajax請求" onclick="fun3()" >發送數據格式爲json的(jquery)ajax請求</button>
<spand id="show3" /><br/>

 

(2)編寫js文件

//使用jquery提交json數據(ajax請求)

function fun3(){
    
    var user={                        //符合json數據格式規範的javascript對象
            "username":"我是誰",
            "password":"1314520"    
    };    
$.ajax({
        
        type:"POST",
        url:"UserController3",
        contentType:"application/json;charset=UTF-8", //發送數據到服務器時所使用的內容類型
        data:JSON.stringify(user),    //將javascript對象轉化爲json字符串
        
        //預期的服務器響應的數據類型。服務器返回json字符串。jquery會自動把json轉化爲js對象
        dataType:"json",    //至關於調用JSON.parse(data)方法。此時咱們省去便可。      
        success:function(data){
            
            $("#show3").html(data.username+" "+data.password+" "+data.age);
            
        }            
    });
}

打印信息時,咱們加了一個age屬性注意一下。這裏username設置爲中文,主要爲了測試會不會出現亂碼(看web.xml配置的編碼過濾器生效沒)。

(3)編寫User類

   User實體類和上面同樣。有3個屬性,username,password,age。提供getters和setters方法,toString方法。

(4)配置web.xml

   同樣

(5)配置springmvc.xml文件

   同理

(6)編寫Controller類

package com.controller;

import java.io.IOException;

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

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.pojo.User;


public class UserController3 implements HttpRequestHandler{


    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setCharacterEncoding("UTF-8");
        ////加載spring.xml文件初始化ApplicationContext
        ApplicationContext ac = new ClassPathXmlApplicationContext("springmvc.xml");
        ////獲取消息轉換器MappingJackson2HttpMessageConverter類對象,實現了HttpMessageConverter接口
        HttpMessageConverter converter=(HttpMessageConverter) ac.getBean("myconverter");        
        ////獲取媒體類型,傳入的是"application/json;charset=UTF-8"這裏咱們直接new對象
        MediaType mediaType=new MediaType(MediaType.APPLICATION_JSON, null);        
        //請求信息類,封裝輸入信息
        HttpInputMessage in=new ServletServerHttpRequest(request);        
        //響應信息類,封裝輸出信息
        HttpOutputMessage out=new ServletServerHttpResponse(response);                            
        //把前臺傳來傳來json數據轉化爲User對象(read接受的參數:這裏能夠把json數據轉化爲User,得益於HttpInputMessage已經把請求的信息已經封裝好了,包括請求頭和請求體)
        User user= (User) converter.read(User.class, in);
        //設置年齡
        user.setAge(666);
        
        System.out.println(user);
        //把User對象轉化爲json數據輸出
        converter.write(user, mediaType, out);    
    }
}

代碼都有註解。很簡單。消息轉換器對象的write()方法讀客戶端發送的json數據,把json數據轉換爲User類對象,爲何要轉換?(方便咱們代碼進行操做和維護。好比咱們登錄時,要查數據庫看這個user存在不,設置其餘屬性什麼的,好比age。因此是有必定需求的。java語言是面向對象程序設計語言,確定操做java對象方便快捷)。

(7)跑一下程序

完美運行,沒有出現亂碼,好了,收工。打印出了username,password,age的內容。

6. 理解Spring MVC的執行流程

(1)用戶發送請求到Spring MVC核心控制器(DispatcherServlet)。

(2)前端控制器請求 HandlerMapping 查找 Controller,能夠根據 xml 配置、註解進行查找。

(3) 處理器映射器 HandlerMapping 查找完成後向核心控制器返回 Controller。

(4)前端控制器調用處理器適配器去執行 Controller。

(5)處理器適配器執行 Controller。

(6)Controller執行完成後給適配器返回 ModelAndView對象。

(7)處理器適配器向前端控制器返回 ModelAndView。ModelAndView 是SpringMVC 框架的一個底層對象,包括 Model 和 View。

(8)前端控制器請求試圖解析器去進行視圖解析根據邏輯視圖名來解析真正的視圖。

(9)視圖解析器向前端控制器返回 view。

(10)核心控制器進行視圖渲染。就是將模型數據(在 ModelAndView 對象中)填充到 request 域

(11)核心控制器向用戶響應結果。

 

7. 總結

(1)導包。不到log4j日誌包會出現錯誤,Spring框架支持log4j日誌輸出。支持Apache服務的包也要導入(com.springresource)。Jackson包導全。Spring開發基本包。

(2)加載不到靜態資源,要對靜態資源文件進行放行。

(3)Spring的IoC機制,能夠把對象交給容器管理。IoC核心:經過配置文件或者是Annonation的方式,將實現類注入到調用者那裏去。

   IoC實現原理:工廠模式+java反射機制。IOC好處:

   第一:資源集中管理,實現資源的可配置和易管理。

   第二:下降了使用資源雙方的依賴程度,也就是咱們說的耦合度。

   第三:經過配置文件,能夠作到改變實現類,而不改變任何一個調用者的代碼(IOC)。

(4)本次開發咱們使用到了Spring MVC內置的消息轉換器MappingJackson2HttpMessageConverter(用於java對象與json數據的轉換)。其內部實現原理仍是使用到了Jackson開發包,這就是爲何要導入Jackson包的緣由。固然,咱們也能夠直接使用Jackson類庫進行java對象與json數據的轉換(個人前幾篇博客)。這裏調用內置的消息轉換器,方便你們理解。Spring MVC的執行流程,以及底層究竟是怎麼進行java對象與json數據的。固然也能夠在Spring MVC自定義本身的消息轉換器類,讓其實現HttpMessageConverter<T>接口。

(5)本次開發的強大之處在於沒有使用任何Spring的任何註解,基於純XML配置,走原生模式。方便你們瞭解底層的實現原理。

(6)學習的時候能夠多參考Spring和Spring MVC的開發文檔。有不懂的類能夠參考Spring API文檔。

 (7)經過本次開發,發現Spring MVC的優勢:Spring MVC與Spring無縫對接,使用簡單,易擴展,靈活性比較強,可適配,非侵入,清晰的角色劃分,強大的配置方式,可定製的handler mapping和view resolver。固然我以爲Spring MVC最好的地方在於提供了很是靈活的參數綁定機制和強大的註解機制。

相關文章
相關標籤/搜索