日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java EE——SpringMVC框架学习

發(fā)布時間:2024/9/30 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java EE——SpringMVC框架学习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • 一、SpringMVC的基本概念:
          • 1、三層架構和MVC:
          • 2、SpringMVC的概述:
          • 3、SpringMVC在三層架構的位置:
        • 二、SpringMVC 的入門:
        • 三、入門案例的執(zhí)行過程分析:
        • 四、RequestMapping 注解:
          • 1、使用說明:
          • 2、使用示例:
        • 五、請求參數的綁定:
          • 1、什么是參數綁定?
          • 2、 綁定說明:
          • 3、使用示例:
          • 4、自定義類型轉換器:
          • 5、在控制器中使用原生的ServletAPI對象
        • 六、常用注解:
        • 七、響應數據和結果視圖 :
          • 1、返回值分類:
          • 2. SpringMVC框架提供的轉發(fā)和重定向:
        • 八、SpringMVC 實現文件上傳 :
          • 1. 文件上傳的回顧:
          • 2、SpringMVC傳統(tǒng)方式文件上傳:
          • 3、SpringMVC跨服務器方式文件上傳:
        • 九、SpringMVC 中的異常處理:
        • 十、SpringMVC框架中的攔截器

一、SpringMVC的基本概念:

1、三層架構和MVC:

1.1、三層架構

開發(fā)Web程序一般都是基于兩種形式,一種C/S架構程序,一種B/S架構程序。在 JavaEE 開發(fā)中,幾乎全都是基于 B/S 架構的開發(fā)。在 B/S 架構中,系統(tǒng)標準的三層架構包括:表現層業(yè)務層持久層

三層架構中,每一層各司其職,接下來我們就說說每層都負責哪些方面:

  • 表現層:
    也就是我們常說的web層。它負責接收客戶端請求,向客戶端響應結果,通常客戶端使用http協(xié)議請求web 層,web 需要接收 http 請求,完成 http 響應。表現層包括展示層和控制層:控制層負責接收請求,展示層負責結果的展示。表現層依賴業(yè)務層,接收到客戶端請求一般會調用業(yè)務層進行業(yè)務處理,并將處理結果響應給客戶端。表現層的設計一般都使用 MVC 模型。(MVC 是表現層的設計模型,和其他層沒有關系)

  • 業(yè)務層:
    也就是我們常說的 service 層。它負責業(yè)務邏輯處理,和我們開發(fā)項目的需求息息相關。web 層依賴業(yè)務層,但是業(yè)務層不依賴 web 層。業(yè)務層在業(yè)務處理時可能會依賴持久層,如果要對數據持久化需要保證事務一致性。(也就是我們說的,事務應該放到業(yè)務層來控制)

  • 持久層:
    也就是我們是常說的 dao 層。負責數據持久化,包括數據層即數據庫和數據訪問層,數據庫是對數據進行持久化的載體,數據訪問層是業(yè)務層和持久層交互的接口,業(yè)務層需要通過數據訪問層將數據持久化到數據庫中。通俗的講,持久層就是和數據庫交互,對數據庫表進行曾刪改查的。

1.2、 MVC

MVC 全名是 Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,是一種用于設計創(chuàng)建 Web 應用程序 表現層的模式。MVC 中每個部分各司其職:

  • Model(模型):
    通常指的就是我們的數據模型。JavaBean的類,用來進行數據封裝。

  • View(視圖):
    通常指的就是我們的 jsp 或者 html。作用一般就是展示數據的。

  • Controller(控制器):
    是應用程序中處理用戶交互的部分。作用一般就是處理程序邏輯的。
    舉個例子:
    我們要保存一個用戶的信息,該用戶信息中包含了姓名,性別,年齡等等。
    這時候表單輸入要求年齡必須是 1~100 之間的整數。姓名和性別不能為空。并且把數據填充到模型之中。此時除了 js 的校驗之外,服務器端也應該有數據準確性的校驗,那么校驗就是控制器的該做的。
    當校驗失敗后,由控制器負責把錯誤頁面展示給使用者。
    如果校驗成功,也是控制器負責把數據填充到模型,并且調用業(yè)務層實現完整的業(yè)務需求。

2、SpringMVC的概述:

SpringMVC 是一種基于 Java 的實現 MVC 設計模型的輕量級 Web 框架,是 Spring 框架為表現層提供的的后續(xù)產品,是目前最主流的 MVC框架之一。

2.1、SpringMVC 的優(yōu)勢

1、清晰的角色劃分:

  • 前端控制器(DispatcherServlet)
  • 請求到處理器映射(HandlerMapping)
  • 處理器適配器(HandlerAdapter)
  • 視圖解析器(ViewResolver)
  • 處理器或頁面控制器(Controller)
  • 驗證器( Validator)
  • 命令對象(Command 請求參數綁定到的對象就叫命令對象)
  • 表單對象(Form Object 提供給表單展示和提交到的對象就叫表單對象)。
  • 2、分工明確,而且擴展點相當靈活,可以很容易擴展,雖然幾乎不需要。

    3、由于命令對象就是一個 POJO,無需繼承框架特定 API,可以使用命令對象直接作為業(yè)務對象。

    4、和 Spring 其他框架無縫集成,是其它 Web 框架所不具備的。

    5、可適配,通過 HandlerAdapter 可以支持任意的類作為處理器。

    6、可定制性,HandlerMapping、ViewResolver 等能夠非常簡單的定制。

    7、功能強大的數據驗證、格式化、綁定機制。

    8、利用 Spring 提供的 Mock 對象能夠非常簡單的進行 Web 層單元測試。

    9、本地化、主題的解析的支持,使我們更容易進行國際化和主題的切換。

    10、強大的 JSP 標簽庫,使 JSP 編寫更容易。

    3、SpringMVC在三層架構的位置:

    二、SpringMVC 的入門:

    1、使用Maven創(chuàng)建web工程,引入開發(fā)的jar包:

    需要用的坐標如下:

    <properties><!-- 版本鎖定 --><spring.version>5.0.2.RELEASE</spring.version></properties><dependencies><!-- 單元測試--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency></dependencies>

    2、配置核心的控制器(配置DispatcherServlet)

    在web.xml配置文件中核心控制器DispatcherServlet

    <!-- SpringMVC的核心控制器 --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 配置Servlet的初始化參數,讀取springmvc的配置文件,創(chuàng)建spring容器 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!-- 配置servlet的對象的創(chuàng)建時間點,取值只能是非 0 正整數,表示啟動順序。“1” 表示應用加載時創(chuàng)建。--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping>

    3、 編寫springmvc.xml的配置文件

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 配置spring創(chuàng)建容器時要掃描的包 --><context:component-scan base-package="com.smk"></context:component-scan><!-- 配置視圖解析器 --><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"></property><property name="suffix" value=".jsp"></property></bean><!-- 配置spring開啟注解mvc的支持--><mvc:annotation-driven/> </beans>

    4、 編寫index.jsp和HelloController控制器類

    index.jsp:

    <body> <h3>入門案例</h3> <a href="hello">入門案例</a> </body>

    HelloController:

    @Controller public class HelloController {@RequestMapping("/hello")public String sayHello() {System.out.println("Hello SpringMVC");return "success";} }

    5、 在WEB-INF目錄下創(chuàng)建pages文件夾,編寫success.jsp的成功頁面

    <body> <h3>入門成功!!</h3> </body>

    6、 啟動Tomcat服務器,進行測試

    因為之前一直用的Eclipse,所以這里細說一下IDEA下添加tomcat并發(fā)布項目的過程。

    1、首先點擊箭頭所指處添加服務器:

    2、點左上角的加號,找到并選擇Tomcat Server下的 Local


    3、在Deployment下點 “+” 號,選擇第一個添加項目:


    選擇第一個


    箭頭處為項目的訪問路徑,完整路徑要加上 localhost:8080

    注:一定要點 Apply,不然無法完成添加。

    4、添加完成后會出現Application Server 。


    5、右鍵運行,IDEA會自動跳轉到游覽器打開:



    測試成功!( ̄︶ ̄)↗ 

    三、入門案例的執(zhí)行過程分析:

    1、入門案例的執(zhí)行流程

  • 當啟動Tomcat服務器的時候,因為配置了load-on-startup標簽,所以會創(chuàng)建DispatcherServlet對象,就會加載springmvc.xml配置文件。
  • 開啟了注解掃描,那么HelloController對象就會被創(chuàng)建。
  • 從index.jsp發(fā)送請求,請求會先到達DispatcherServlet核心控制器,根據配置@RequestMapping注解找到執(zhí)行的具體方法。
  • 根據執(zhí)行方法的返回值,再根據配置的視圖解析器,去指定的目錄下查找指定名稱的JSP文件。
  • Tomcat服務器渲染頁面,做出響應。
  • 圖解:


    2、入門案例中的組件分析

    1、前端控制器(DispatcherServlet)

    • 用戶請求到達前端控制器,它就相當于 mvc 模式中的 c,dispatcherServlet 是整個流程控制的中心,由它調用其它組件處理用戶的請求,dispatcherServlet 的存在降低了組件之間的耦合性。

    2、處理器映射器(HandlerMapping)

    • HandlerMapping 負責根據用戶請求找到 Handler 即處理器,SpringMVC 提供了不同的映射器實現不同的映射方式,例如:配置文件方式,實現接口方式,注解方式等。

    3、處理器適配器(HandlAdapter)

    • 通過 HandlerAdapter 對處理器進行執(zhí)行,這是適配器模式的應用,通過擴展適配器可以對更多類型的處理器進行執(zhí)行。

    4、處理器(Handler)

    • 它就是我們開發(fā)中要編寫的具體業(yè)務控制器。由 DispatcherServlet 把用戶請求轉發(fā)到 Handler。由Handler 對具體的用戶請求進行處理。

    5、視圖解析器(View Resolver)

    • View Resolver 負責將處理結果生成 View 視圖,View Resolver 首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成 View 視圖對象,最后對 View 進行渲染將處理結果通過頁面展示給用戶。

    6、視圖(View)

    • SpringMVC 框架提供了很多的 View 視圖類型的支持,包括:jstlView、freemarkerView、pdfView等。我們最常用的視圖就是 jsp。

    • 一般情況下需要通過頁面標簽或頁面模版技術將模型數據通過頁面展示給用戶,需要由程序員根據業(yè)務需求開發(fā)具體的頁面。

    3、<mvc:annotation-driven/>說明

    • 在 SpringMVC 的各個組件中,處理器映射器、處理器適配器、視圖解析器稱為 SpringMVC 的三大組件。
    • 使 用 <mvc:annotation-driven> 自動加載 RequestMappingHandlerMapping(處理映射器)和RequestMappingHandlerAdapter(處理適配器),可用在SpringMVC.xml 配置文件中使用<mvc:annotation-driven/>替代注解處理器和適配器的配置。
    • 一般開發(fā)中,我們都需要寫上此標簽(雖然從入門案例中看,我們不寫也行,隨著課程的深入,該標簽還有具體的使用場景)。

    四、RequestMapping 注解:

    1、使用說明:

    作用

    • 用于建立請求 URL 和處理請求方法之間的對應關系。

    出現位置

    類上:

    • 請求 URL 的第一級訪問目錄。此處不寫的話,就相當于應用的根目錄。寫的話需要以/開頭。

    它出現的目的是為了使我們的 URL 可以按照模塊化管理:

    例如:

    • 賬戶模塊:
      /account/add
      /account/update
      /account/delete

    • 訂單模塊:
      /order/add
      /order/update
      /order/delete

    /accound,/order 就是把 RequsetMappding 寫在類上,使我們的 URL 更加精細。

    方法上:

    • 請求 URL 的第二級訪問目錄。

    屬性

    value:用于指定請求的 URL。它和 path 屬性的作用是一樣的。

    method:用于指定請求的方式。

    params:用于指定限制請求參數的條件。它支持簡單的表達式。要求請求參數的 key 和 value 必須和配置的一模一樣。

    • 例如:
      params = {“accountName”},表示請求參數必須有 accountName
      params = {“moeny!100”},表示請求參數中 money 不能是 100。

    headers:用于指定限制請求消息頭的條件。

    注意:以上四個屬性只要出現 2 個或以上時,他們的關系是與的關系。

    2、使用示例:

    1、出現位置的示例

    控制器代碼:

    @Controller("accountController") @RequestMapping("/account") public class AccountController {@RequestMapping("/findAccount")public String findAccount() {System.out.println("查詢了賬戶。。。。");return "success";} }

    jsp代碼:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>requestmapping 的使用</title> </head> <body> <!-- 第一種訪問方式 --> <a href="${pageContext.request.contextPath}/account/findAccount">查詢賬戶 </a> <br/> <!-- 第二種訪問方式 --> <a href="account/findAccount">查詢賬戶</a> </body> </html>

    注意:當使用此種方式配置時,在 jsp 中第二種寫法時,不要在訪問 URL 前面加/,否則無法找到資源。

    2、method 屬性的示例

    控制器代碼:

    @RequestMapping(value="/saveAccount",method=RequestMethod.POST) public String saveAccount() {System.out.println("保存了賬戶");return "success"; }

    jsp 代碼:

    <!-- 請求方式的示例 --> <a href="account/saveAccount">保存賬戶,get 請求</a> <br/><form action="account/saveAccount" method="post"><input type="submit" value="保存賬戶,post 請求"> </form>

    當使用 get 請求時,提示錯誤信息是 405,信息是方法不支持 get 方式請求


    3、params 屬性的示例

    控制器的代碼:

    @RequestMapping(value="/removeAccount",params= {"accountName","money>100"})public String removeAccount() {System.out.println("刪除了賬戶");return "success";}

    jsp 中的代碼:

    <!-- 請求參數的示例 --> <a href="account/removeAccount?accountName=aaa&money>100">刪除賬戶,金額 100</a> <br/> <a href="account/removeAccount?accountName=aaa&money>150">刪除賬戶,金額 150</a>

    當點擊第一個超鏈接時,可以訪問成功。
    當點擊第二個超鏈接時,無法訪問。如下圖:




    五、請求參數的綁定:

    1、什么是參數綁定?
    • 就是將請求參數串中的value值獲取到之后,在進行類型轉換,然后將轉換后的值賦值給Controller類中方法的形參,這個過程就是參數綁定。
    2、 綁定說明:

    2.1、綁定的機制

    我們都知道,表單中請求參數都是基于 key=value 的。
    SpringMVC 綁定請求參數的過程是通過把表單提交請求參數,作為控制器中方法參數進行綁定的。

    例:

    jsp 代碼:

    <a href="account/findAccount?accountId=10">查詢賬戶</a>

    jsp中請求參數是:accountId=10

    @RequestMapping("/findAccount") public String findAccount(Integer accountId) {System.out.println("查詢了賬戶。。。。"+accountId);return "success"; }

    點擊鏈接,會在控制臺輸出:

    2.2、支持的數據類型:

  • 基本數據類型和 String 類型
  • POJO 類型參數:包括實體類,以及關聯(lián)的實體類
  • 集合類型和數組:包括 List 結構和 Map 結構的集合(包括數組)
  • 3、使用示例:

    3.1、基本類型和 String 類型作為參數

    jsp 代碼:

    <!-- 基本類型示例 --> <a href="account/findAccount?accountId=10&accountName=zhangsan">查詢賬戶</a>

    控制器代碼:

    @RequestMapping("/findAccount") public String findAccount(Integer accountId,String accountName) {System.out.println("查詢了賬戶。。。。"+accountId+","+accountName);return "success"; }

    運行結果:


    3.2、POJO 類型作為參數

    實體類代碼:

    /** * 賬戶信息 */ public class Account implements Serializable{private Integer id;private String name;private Float money;private Address address;//省略getters and setters 和 tostring方法} /** * 地址的實體類 */ public class Address implements Serializable {private String provinceName;private String cityName;//省略getters and setters 和 tostring方法 }

    jsp 代碼:

    <form action="account/saveAccount" method="post"> 賬戶名稱:<input type="text" name="name" ><br/> 賬戶金額:<input type="text" name="money" ><br/> 賬戶省份:<input type="text" name="address.provinceName" ><br/> 賬戶城市:<input type="text" name="address.cityName" ><br/> <input type="submit" value="保存"> </form>

    控制器代碼:

    @RequestMapping("/saveAccount") public String saveAccount(Account account) {System.out.println("保存了賬戶。。。。"+account);return "success"; }

    運行結果:


    3.3、 POJO 類中包含集合類型參數

    實體類代碼:

    public class User implements Serializable {private String username;private String password;private Integer age;private List<Account> accounts;private Map<String, Account> accountMap;//省略getters and setters 和 tostring方法

    jsp代碼:

    <form action="account/updateAccount" method="post">用戶名稱:<input type="text" name="username"><br/>用戶密碼:<input type="password" name="password"><br/>用戶年齡:<input type="text" name="age"><br/>賬戶 1 名稱:<input type="text" name="accounts[0].name"><br/>賬戶 1 金額:<input type="text" name="accounts[0].money"><br/>賬戶 2 名稱:<input type="text" name="accounts[1].name"><br/>賬戶 2 金額:<input type="text" name="accounts[1].money"><br/>賬戶 3 名稱:<input type="text" name="accountMap['one'].name"><br/>賬戶 3 金額:<input type="text" name="accountMap['one'].money"><br/>賬戶 4 名稱:<input type="text" name="accountMap['two'].name"><br/>賬戶 4 金額:<input type="text" name="accountMap['two'].money"><br/><input type="submit" value="保存"> </form>

    控制器代碼:

    @RequestMapping("/updateAccount") public String updateAccount(User user) {System.out.println("更新了賬戶。。。。"+user);return "success"; }

    運行結果:


    3.4、請求參數亂碼問題

    在web請求中當出現中文時會有亂碼。get請求是不會亂碼的

    當是post 請求方式時,可以在 web.xml 中配置一個過濾器。

    例:

    <!-- 配置過濾器,解決中文亂碼的問題 --><filter><filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
    4、自定義類型轉換器:

    jsp表單提交的任何數據類型全部都是字符串類型,但是后臺定義Integer類型,數據也可以封裝上,說明Spring框架內部會默認進行數據類型轉換。

    但當我們把控制器中方法參數的類型改為 Date 時:

    • jsp 代碼:
    <a href="account/deleteAccount?date=2018-01-01">根據日期刪除賬戶</a>
    • 控制器代碼:
    @RequestMapping("/deleteAccount") public String deleteAccount(Date date) {System.out.println("刪除了賬戶。。。。"+date);return "success"; }

    運行結果:

    會出現類型轉化異常。

    解決辦法:自定義類型轉換器

    使用步驟

    1、定義一個類,實現 Converter 接口,該接口有兩個泛型。

    public class StringToDateConverter implements Converter<String, Date> {@Overridepublic Date convert(String source) {DateFormat format = null;try {if (source == null) {throw new NullPointerException("請輸入要轉換的日期");}format = new SimpleDateFormat("yyyy-MM-dd");Date date = format.parse(source);return date;} catch (Exception e) {throw new RuntimeException("輸入日期有誤");}} }

    2、第二步:在 spring 配置文件中配置類型轉換器。

    <!-- 配置類型轉換器工廠 --><bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean"><!-- 給工廠注入一個新的類型轉換器 --><property name="converters"><array><!-- 配置自定義類型轉換器 --><bean class="com.smk.util.StringToDateConverter"/></array></property></bean>

    3、第三步:在 annotation-driven 標簽中引用配置的類型轉換服務 。

    <!-- 引用自定義類型轉換器 --> <mvc:annotation-driven conversion-service="converterService"/>

    運行結果:

    5、在控制器中使用原生的ServletAPI對象

    SpringMVC 還支持使用原始 ServletAPI 對象作為控制器方法的參數。支持原始 ServletAPI 對象有:

    • HttpServletRequest、HttpServlet、ResponseHttpSession 等…

    使用方法

    只需要在控制器的方法參數定義HttpServletRequest和HttpServletResponse對象

    例:

    @RequestMapping("/testServletAPI") public String testServletAPI(HttpServletRequest request,HttpServletResponse response,HttpSession session) {System.out.println(request);System.out.println(response);System.out.println(session);return "success"; }

    六、常用注解:

    1、RequestParam注解

    作用:把請求中指定名稱的參數給控制器中的形參賦值。

    屬性:

  • value:請求參數中的名稱
  • required:請求參數中是否必須提供此參數,默認值是true,表示必須提供,如果不提供將報錯。
  • 例:

    jsp 中的代碼:

    <!-- requestParams 注解的使用 --> <a href="springmvc/useRequestParam?name=test">requestParam 注解</a>

    控制器中的代碼:

    @RequestMapping("/useRequestParam") public String useRequestParam(@RequestParam("name")String username,@RequestParam(value="age",required=false)Integer age){System.out.println(username+","+age);return "success"; }

    運行結果:

    2、RequestBody注解

    作用:

    • 用于獲取請求體內容。直接使用得到是 key=value&key=value…結構的數據。
    • get 請求方式不適用。(因為get沒有請求體)

    屬性:

    • required:是否必須有請求體,默認值是true。當取值為 true 時,get 請求方式會報錯。如果取值為 false,get 請求得到是 null。

    例:

    post 請求 jsp 代碼:

    <form action="useRequestBody" method="post"> 用戶名稱:<input type="text" name="username" ><br/> 用戶密碼:<input type="password" name="password" ><br/> 用戶年齡:<input type="text" name="age" ><br/> <input type="submit" value="保存"> </form>

    get 請求 jsp 代碼:

    <a href="springmvc/useRequestBody?body=test">requestBody 注解 get 請求</a>

    控制器代碼:

    @RequestMapping("/useRequestBody") public String useRequestBody(@RequestBody(required=false) String body){System.out.println(body);return "success"; }

    post 請求運行結果:

    get 請求運行結果:


    3、PathVariable注解

    作用:

    • 用于綁定 url 中的占位符賦值給形參。例如:請求 url 中 /delete/{id},這個 {id} 就是 url 占位符。
    • url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 風格 URL 的一個重要標志。

    屬性:

    • value:用于指定 url 中占位符名稱。
    • required:是否必須提供占位符。

    使用示例:

    jsp 代碼:

    <a href="usePathVariable/100">pathVariable 注解</a>

    控制器代碼:

    @RequestMapping("/usePathVariable/{id}") public String usePathVariable(@PathVariable("id") Integer id){System.out.println(id);return "success"; }

    運行結果:

    Restful風格的URL

    • 請求路徑一樣,可以根據不同的請求方式去執(zhí)行后臺的不同方法。

    restful風格的URL優(yōu)點:

  • 結構清晰
  • 符合標準
  • 易于理解
  • 擴展方便
  • 4、RequestHeader注解

    作用:

    • 用于獲取請求消息頭。

    屬性:

    • value:提供消息頭名稱
    • required:是否必須有此消息頭

    注:在實際開發(fā)中一般不怎么用。

    jsp 中代碼:

    <a href="useRequestHeader">獲取請求消息頭</a>

    控制器中代碼:

    @RequestMapping("/useRequestHeader")public String useRequestHeader(@RequestHeader(value = "Accept-Language",required = false) String requestHeader) {System.out.println(requestHeader);return "success";}

    運行結果:

    6、ModelAttribute注解

    作用:

  • 出現在方法上:表示當前方法會在控制器方法執(zhí)行前線執(zhí)行。
  • 出現在參數上:獲取指定的數據給參數賦值。
  • 屬性:

    • value:用于獲取數據的 key。key 可以是 POJO 的屬性名稱,也可以是 map 結構的 key。

    應用場景:

    • 當提交表單數據不是完整的實體數據時,保證沒有提交的字段使用數據庫原來的數據。

    示例

    jps 代碼:

    <a href="testModelAttribute?username=test">測試 modelattribute</a>

    控制器代碼:

    //接收請求的方法 @RequestMapping("/testModelAttribute") public String testModelAttribute(User user) {System.out.println("執(zhí)行了控制器的方法"+user.getUsername());return "success"; }//被 ModelAttribute 修飾的方法 @ModelAttribute public void showModel(User user) {System.out.println("執(zhí)行了 showModel 方法"+user.getUsername()); }

    運行結果:


    ModelAttribute 修飾方法帶返回值:

    jsp 的代碼:

    <!-- 修改用戶信息 --> <form action="updateUser" method="post"> 用戶名稱:<input type="text" name="username" ><br/> 用戶年齡:<input type="text" name="age" ><br/> <input type="submit" value="保存"> </form>

    控制器中的代碼:

    @RequestMapping("/testModelAttribute2")//獲取 ModelAttribute修飾的方法中的 User對象public String testModelAttribute2(User user) {System.out.println(user);return "success";}@ModelAttributeprivate User showUser(String username) {//模擬數據庫查詢,把查詢到的數據傳入 user 中User user = new User();user.setUsername(username);user.setAge(19);user.setBirthday(new Date());return user;}

    運行結果:


    先執(zhí)行ModelAttribute修飾的方法,然后在把jsp中的數據覆蓋user 的值,所以這里的 年齡和設置的不一樣。

    ModelAttribute 修飾方法不帶返回值:

    jsp 的代碼:同上

    控制器中的代碼:

    @RequestMapping("/testModelAttribute2")//把 ModelAttribute修飾的方法里的 map里 key的值賦給 userpublic String testModelAttribute2(@ModelAttribute("abc") User user) {System.out.println(user);return "success";}@ModelAttributeprivate void showUser(String username, Map<String, User> map) {//模擬數據庫查詢,把查詢到的數據傳入 user 中User user = new User();user.setUsername(username);user.setAge(19);user.setBirthday(new Date());map.put("abc", user);}

    運行結果:

    7、SessionAttribute

    作用:

    • 用于多次執(zhí)行控制器方法間的參數共享。

    屬性:

    • value:用于指定存入的屬性名稱
    • type:用于指定存入的數據類型

    使用示例

    jsp 中的代碼:

    <a href="testPut">存入 SessionAttribute</a> <hr/> <a href="testGet">取出 SessionAttribute</a> <hr/> <a href="testDel">清除 SessionAttribute</a>

    控制器中的代碼:

    @Controller @SessionAttributes(value = {"msg"})//把 msg = 張三 存入到session域中 public class HelloController {@RequestMapping("/testPut")public String testPut(Model model) {System.out.println(" testPut...");//底層會存儲到request域對象中model.addAttribute("msg", "張三");return "success";}@RequestMapping("/testGet")public String testGet(ModelMap model) {System.out.println("testGet...");String msg = (String) model.get("msg");System.out.println(msg);return "success";}//完成會話,清除session域的值@RequestMapping("/testDel")public String testDel(SessionStatus status) {System.out.println("testDel...");status.setComplete();return "success";}

    在success.jsp 中獲取數據:


    三個方法依次執(zhí)行,結果如下:

    游覽器

    存入:

    刪除:

    控制臺

    七、響應數據和結果視圖 :

    1、返回值分類:

    1.1、返回字符串類

    Controller方法返回字符串可以指定邏輯視圖的名稱,根據視圖解析器為物理視圖的地址。

    @RequestMapping("/testReturnString") public String testReturnString() {System.out.println("AccountController 的 testReturnString 方法執(zhí)行了。。。。");return "success"; }

    1.2、返回void

    如果控制器的方法返回值編寫成void,執(zhí)行程序報404的異常,默認查找JSP頁面沒有找到。

    默認會跳轉到當前 RequestMapping注解 value值同名的 jsp 頁面。

    例:


    Controller頁面:

    @Controller @RequestMapping("/user") public class UserController {@RequestMapping("/testString")public void testString() {System.out.println("testString方法執(zhí)行了...");} }

    這時可以新建 /WEB-INF/pages/user/testString.jsp 文件解決問題,或者可以使用請求轉發(fā)或者重定向跳轉到指定的頁面。

    例:

    @RequestMapping("/testReturnVoid")public void testReturnVoid(HttpServletRequest request, HttpServletResponse response)throws Exception {// 1、使用 request 轉向頁面,如下:request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);//2、也可以通過 response 頁面重定向:response.sendRedirect( "index.jsp"); //3、也可以通過 response 指定響應結果:response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().write("json 串");}

    注意:

    如果是重定向到 jsp 頁面,則 jsp 頁面必須在根目錄下即 webapp目錄下 ,不能寫在 WEB-INF 目錄中,否則無法找到。

    1.3、返回值是ModelAndView對象

    ModelAndView 是 SpringMVC 為我們提供的一個對象,該對象也可以用作控制器方法的返回值。

    示例代碼:

    @RequestMapping("/testReturnModelAndView")public ModelAndView testReturnModelAndView() {ModelAndView mv = new ModelAndView();mv.addObject("username", "張三");mv.setViewName("success");// 設置要跳轉到的jsp的頁面,是經過視圖解析器的。return mv;}

    運行結果:

    2. SpringMVC框架提供的轉發(fā)和重定向:

    2.1、forward 轉發(fā)

    controller 方法在提供了 String 類型的返回值之后,默認就是請求轉發(fā)。也可以寫成:

    @RequestMapping("/testForward") public String testForward() {System.out.println("AccountController 的 testForward 方法執(zhí)行了。。。。");return "forward:/WEB-INF/pages/success.jsp"; }

    它相當于 request.getRequestDispatcher("url").forward(request,response) 。使用請求轉發(fā),既可以轉發(fā)到 jsp,也可以轉發(fā)到其他的控制器方法。

    2.2、Redirect 重定向

    contrller 方法提供了一個 String 類型返回值之后,它需要在返回值里使用:redirect

    @RequestMapping("/testRedirect") public String testRedirect() {System.out.println("AccountController 的 testRedirect 方法執(zhí)行了。。。。");return "redirect:testReturnModelAndView"; }

    它相當于 response.sendRedirect(url),同樣的:如果是重定向到 jsp 頁面,則 jsp 頁面必須在根目錄下即 webapp目錄下 ,不能寫在 WEB-INF 目錄中,否則無法找到。

    八、SpringMVC 實現文件上傳 :

    1. 文件上傳的回顧:

    1.1、文件上傳的必要前提

    • form 表單的 enctype 取值必須是:multipart/form-data(默認值是:application/x-www-form-urlencoded)
    • enctype 是表單請求正文的類型
    • method 屬性取值必須是 Post

    1.2、文件上傳的原理分析

    當 form 表單的 enctype 取值不是默認值后,request.getParameter() 將失效。

    當 enctype = “application/x-www-form-urlencoded” 時,form 表單的正文內容是:key=value&key=value&key=value

    當 form 表單的 enctype 取值為 Mutilpart/form-data 時,請求正文內容就變成:

    每一部分都是 MIME 類型描述的正文

    -----------------------------7de1a433602ac 分界符 Content-Disposition: form-data; name="userName" 協(xié)議頭 aaa 協(xié)議的正文(文件內容) -----------------------------7de1a433602ac Content-Disposition: form-data; name=“file”; filename=“C:\Users\zhy\Desktop\fileupload_demofile\b.txt” Content-Type: text/plain 協(xié)議的類型(MIME 類型) bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -----------------------------7de1a433602ac--

    1.3、實現步驟:

  • 導入文件上傳需要的jar包:
  • <dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version> </dependency> <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version> </dependency>
  • 編寫文件上傳的JSP頁面:
  • <form action="user/fileupload1" method="post" enctype="multipart/form-data">選擇文件:<input type="file" name="upload"/><br/><input type="submit" value="上傳文件"/> </form>
  • 編寫文件上傳的Controller控制器:
  • @RequestMapping(value = "/fileupload1")public String fileupload(HttpServletRequest request) throws Exception {// 先獲取到要上傳的文件目錄String path = request.getSession().getServletContext().getRealPath("/uploads");System.out.println(path);// 創(chuàng)建File對象,一會向該路徑下上傳文件File file = new File(path);// 判斷路徑是否存在,如果不存在,創(chuàng)建該路徑if (!file.exists()) {file.mkdirs();}// 創(chuàng)建磁盤文件項工廠DiskFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload fileUpload = new ServletFileUpload(factory);// 解析request對象List<FileItem> list = fileUpload.parseRequest(request);// 遍歷for (FileItem fileItem : list) {// 判斷文件項是普通字段,還是上傳的文件if (fileItem.isFormField()) {} else {// 上傳文件項// 獲取到上傳文件的名稱String filename = fileItem.getName();//生成唯一id,防止文件覆蓋String uuid = UUID.randomUUID().toString().replace("-", "");//把uuid里的"-"替換成""filename = uuid + filename;// 上傳文件fileItem.write(new File(file, filename));// 刪除臨時文件fileItem.delete();}}return "success";}
    2、SpringMVC傳統(tǒng)方式文件上傳:

    SpringMVC框架提供了MultipartFile對象,該對象表示上傳的文件,要求變量名稱必須和表單file標簽的name屬性名稱相同

    即:


  • jsp頁面:
  • <h3>SpringMVC文件上傳</h3><form action="fileupload2" method="post" enctype="multipart/form-data">選擇文件:<input type="file" name="upload"/><br/><input type="submit" value="上傳文件"/> </form>
  • 控制器代碼:
  • @RequestMapping(value = "/fileupload2")public String fileupload2(HttpServletRequest request, MultipartFile upload) throws Exception {System.out.println("SpringMVC方式的文件上傳...");// 先獲取到要上傳的文件目錄String path = request.getSession().getServletContext().getRealPath("/uploads");// 創(chuàng)建File對象,一會向該路徑下上傳文件File file = new File(path);// 判斷路徑是否存在,如果不存在,創(chuàng)建該路徑if (!file.exists()) {file.mkdirs();}// 獲取到上傳文件的名稱String filename = upload.getOriginalFilename();String uuid = UUID.randomUUID().toString().replace("-", "");// 把文件的名稱唯一化filename = uuid + "_" + filename;// 上傳文件upload.transferTo(new File(file, filename));return "success";}

    3、配置文件解析器對象:

    <!-- 配置文件解析器對象,要求id名稱必須是multipartResolver --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="maxUploadSize" value="10485760"/></bean>

    注意

    一但采用 MultipartResolver 進行文件上傳,MultipartResolver 根據請求頭部的的 content-type 判斷是否含有 ”multipart/form-data”。如果有,則把請求封裝成 MultipartFile。

    這時傳統(tǒng)的上傳方式就不能用了。

    3、SpringMVC跨服務器方式文件上傳:

    1、分服務器的目的

    在實際開發(fā)中,會有很多處理不同功能的服務器。例如:

    • 應用服務器:負責部署我們的應用
    • 數據庫服務器:運行我們的數據庫
    • 緩存和消息服務器:負責處理大并發(fā)訪問的緩存和消息
    • 文件服務器:負責存儲用戶上傳文件的服務器。

    分服務器處理的目的是讓服務器各司其職,從而提高項目的運行效率。


    實現步驟:

    1、創(chuàng)建兩個web項目,其中一個作為上傳服務器使用,并都在tomcat 進行發(fā)布。

    2、實現SpringMVC跨服務器方式文件上傳:

  • 導入開發(fā)需要的jar包:
  • <dependency><groupId>com.sun.jersey</groupId><artifactId>jersey-core</artifactId><version>1.18.1</version> </dependency> <dependency><groupId>com.sun.jersey</groupId><artifactId>jersey-client</artifactId><version>1.18.1</version> </dependency>
  • 編寫文件上傳的JSP頁面:
  • <h3>跨服務器文件上傳</h3> <form action="fileupload3" method="post" enctype="multipart/form-data">選擇文件:<input type="file" name="upload"/><br/><input type="submit" value="上傳文件"/> </form>
  • 編寫控制器:
  • @RequestMapping(value = "/fileupload3")public String fileupload3(MultipartFile upload) throws Exception {System.out.println("SpringMVC跨服務器方式的文件上傳...");// 定義圖片服務器的請求路徑String path = "http://localhost:9090/fileupload/uploads /";// 獲取到上傳文件的名稱String filename = upload.getOriginalFilename();String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();// 把文件的名稱唯一化filename = uuid + "_" + filename;// 向圖片服務器上傳文件// 創(chuàng)建客戶端對象Client client = Client.create();// 連接圖片服務器WebResource webResource = client.resource(path + filename);// 上傳文件webResource.put(upload.getBytes());return "success";}

    需要注意的是:圖片服務器里的 uploads 文件需要自己創(chuàng)建,在Tomcat 服務器的 webapps的根目錄下創(chuàng)建。



    上傳成功。

    九、SpringMVC 中的異常處理:

    若遇到錯誤或者異常,返回給用戶一個良好的錯誤信息比直接返回報錯的游覽器頁面要好的多。

    當系統(tǒng)的 dao、service、controller 出現異常時都是向上拋出的,最后由 springmvc 前端控制器交由異常處理器進行異常處理,如下圖:

    1、SpringMVC的異常處理

    • 模擬異常信息:
    @Controller @RequestMapping("/user") public class UserController {@RequestMapping("/testException")public String testException() throws SysException {System.out.println("testException執(zhí)行了...");try {//模擬異常int a = 10 / 0;} catch (Exception e) {//控制臺打印異常信息e.printStackTrace();//拋出自定義異常類信息throw new SysException("查詢所有用戶出現了錯誤!");}return "success";} }
  • 自定義異常類:
  • public class SysException extends Exception {private String message;public String getMessage() {return message;}public SysException(String message) {this.message = message;} }
  • 自定義異常處理器:
  • public class SysExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {SysException e = null;// 獲取到異常對象//如果拋出的是系統(tǒng)自定義異常則直接轉換if (ex instanceof SysException) {e = (SysException) ex;} else {e = new SysException("請聯(lián)系管理員");}ModelAndView mv = new ModelAndView();// 存入錯誤的提示信息mv.addObject("message", e.getMessage());// 跳轉的Jsp頁面mv.setViewName("error");return mv;} }
  • 配置異常處理器
  • <!-- 配置異常處理器 --> <bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>

    運行結果:

    十、SpringMVC框架中的攔截器

    1、攔截器的作用

    1、Spring MVC 的處理器攔截器類似于 Servlet 開發(fā)中的過濾器 Filter,用于對處理器進行預處理和后處理。用戶可以自己定義一些攔截器來實現特定的功能。

    2、 可以定義攔截器鏈,連接器鏈就是將攔截器按著一定的順序結成一條鏈,在訪問被攔截的方法時,攔截器鏈中的攔截器會按著定義的順序執(zhí)行。

    3、攔截器和過濾器的功能比較類似,區(qū)別是:

    • 過濾器是 servlet 規(guī)范中的一部分,任何 java web 工程都可以使用。
    • 攔截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
    • 過濾器在 url-pattern 中配置了/*之后,可以對所有要訪問的資源攔截。
    • 攔截器它是只會攔截訪問的控制器方法,如果訪問的是 jsp,html,css,image 或者 js 是不會進行攔截的。

    想要自定義攔截器, 要求必須實現:HandlerInterceptor 接口。

    2、自定義攔截器的步驟

    2.1、 創(chuàng)建類,實現HandlerInterceptor接口:

    public class MyInterceptor1 implements HandlerInterceptor {/*** controller方法執(zhí)行前,進行攔截的方法* return true放行* return false攔截* 可以使用轉發(fā)或者重定向直接跳轉到指定的頁面。*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle 方法執(zhí)行了...");return true;}/*** controller方法執(zhí)行后,進行攔截的方法* 可以使用轉發(fā)或者重定向直接跳轉到指定的頁面。*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle 方法執(zhí)行了");}/*** JSP執(zhí)行后執(zhí)行* 不可以使用轉發(fā)或者重定向直接跳轉到指定的頁面。*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion 方法執(zhí)行了");}}

    2.2、 在springmvc.xml中配置攔截器類:

    <!-- 配置攔截器 --><mvc:interceptors><mvc:interceptor><!-- 哪些方法進行攔截 --><mvc:mapping path="/*"/><!-- 注冊攔截器對象 --><bean class="com.smk.interceptor.MyInterceptor1"/></mvc:interceptor></mvc:interceptors>

    2.3、controller 類代碼:

    @Controller public class UserController {@RequestMapping("/testInterceptor")public String testInterceptor() {System.out.println("testInterceptor執(zhí)行了...");return "success";} }

    運行結果:


    3、HandlerInterceptor接口中的方法

    1、preHandle方法是controller方法執(zhí)行前攔截的方法

  • 可以使用request或者response跳轉到指定的頁面
  • return true放行,執(zhí)行下一個攔截器,如果沒有攔截器,執(zhí)行controller中的方法。
  • return false不放行,不會執(zhí)行controller中的方法。
  • 2、 postHandle是controller方法執(zhí)行后執(zhí)行的方法,在JSP視圖執(zhí)行前。

  • 可以使用request或者response跳轉到指定的頁面
  • 如果指定了跳轉的頁面,那么controller方法跳轉的頁面將不會顯示。
  • 如果controller 被攔截了則不會執(zhí)行。
  • 3、afterCompletion方法是在DispatcherServlet進行視圖的渲染之后執(zhí)行

  • request或者response不能再跳轉頁面了
  • 如果controller方法被攔截了,也會執(zhí)行!
  • 4、 配置多個攔截器

    配置第2個攔截器

    <!-- 配置攔截器 --><mvc:interceptors><mvc:interceptor><!-- 哪些方法進行攔截 --><mvc:mapping path="/user/*"/><!-- 注冊攔截器對象 --><bean class="com.smk.interceptor.MyInterceptor1"/></mvc:interceptor><mvc:interceptor><!-- 哪些方法進行攔截 --><mvc:mapping path="/**"/><!-- 注冊攔截器對象 --><bean class="com.smk.interceptor.MyInterceptor2"/></mvc:interceptor></mvc:interceptors>

    運行結果:

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的Java EE——SpringMVC框架学习的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。