Java框架之SpringMVC 04-視圖解析-Spring表單-JSON-上傳下載

来源:https://www.cnblogs.com/Open-ing/archive/2020/01/22/12228444.html
-Advertisement-
Play Games

SpringMVC 視圖解析 請求處理方法(controller方法)執行完成後,最終返回一個 ModelAndView 對象,即使出現異常也會返回一個 ModelAndView 對象。對於那些返回 String,View 或 ModeMap 等類型的處理方法,Spring MVC 也會在內部將它們 ...


SpringMVC

視圖解析

  請求處理方法(controller方法)執行完成後,最終返回一個 ModelAndView 對象,即使出現異常也會返回一個 ModelAndView 對象。對於那些返回 String,View 或 ModeMap 等類型的處理方法,Spring MVC 也會在內部將它們裝配成一個 ModelAndView 對象,它包含了邏輯名和模型對象的視圖,由視圖解析器解析視圖,然後,進行頁面的跳轉。

  Spring MVC 藉助視圖解析器ViewResolver)得到最終的視圖對象(View),最終的視圖可以是 JSP ,也可能是 Excel、JFreeChart等各種表現形式的視圖

視圖View

  視圖的作用是渲染模型數據,將模型里的數據以某種形式呈現給客戶

    1. 將數據存放到域中   request.setAttribute(name,value)

    2. 轉發|重定向       rd.forward(request,response);

  為了實現視圖模型和具體實現技術的解耦,Spring 在 org.springframework.web.servlet 包中定義了一個高度抽象的 View 介面

  視圖對象由視圖解析器負責實例化。由於視圖是無狀態的,所以他們不會有線程安全的問題

常用的視圖實現類

  轉發視圖:InternalResourceView

  轉發視圖:JstlView 需導入Jstl的jar包,適配器會自動調用此解析器,此解析器繼承了InternalResourceView

    若使用 JSTL 的 fmt 標簽則需要在 SpringMVC 的配置文件中裝配標準資源文件bean

  重定向視圖:RedirectView

    一般情況下,控制器方法返回字元串類型的值會被當成邏輯視圖名處理

    如果返回的字元串中帶 forward: 或 redirect: 首碼時,SpringMVC 會對他們進行特殊處理:將 forward: 和 redirect: 當成指示符,其後的字元串作為 URL 來處理

    在返回值中 return "redirect:/success_redirect.jsp";解析器會自動重定向到此頁面,不需在前面加工程路徑名RedirectView會自動幫我們追加上

註意

轉發:訪問 WEB-INF 下路徑時只允許當前請求為GET或POST請求模式的才能轉發成功,(也就是瀏覽器只支持GET、POST請求的轉發)預設攜帶當前的請求方式發起轉發請求。

   訪問 Controller 內部路徑時必須加上首碼 forward: 同樣攜帶當前的請求方式發起請求,必須有對應的請求方式的路徑

重定向:必須先加上首碼 redirect: 訪問 WEB-INF 下的路徑不被允許,預設用 GET 方法發起新的請求。

    訪問 Controller 內部路徑時同樣只能重定向到GET請求方式的路徑

視圖解析器ViewResolver

  SpringMVC 為邏輯視圖名的解析提供了不同的策略,可以在 SpringMVC 上下文中配置一種或多種解析策略,並指定他們之間的先後順序。每一種映射策略對應一個具體的視圖解析器實現類。通過反射原理

  視圖解析器的作用比較單一:將邏輯視圖解析為一個具體的視圖對象

    url= getPrefix() + viewName + getSuffix()

  每個視圖解析器都實現了 Ordered 介面並開放出一個 order 屬性,可以通過 order 屬性指定解析器的優先順序,order  越小優先順序越高。

   JSP 是最常見的視圖技術,可以使用預設的 InternalResourceViewResolve 作為視圖解析器

   BeanNameViewResolver:將邏輯視圖名解析為一個 Bean , Bean 的 id 等於邏輯視圖名

Spring表單標簽

  SpringMVC 的表單標簽可以實現將模型數據中的屬性和 HTML 表單元素相綁定,以實現表單數據更便捷編輯和表單值的回顯

   引入標簽庫

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

form 標簽

  <form:form> 標簽  可以通過 modelAttribute 屬性指定綁定的模型屬性,若沒有指定該屬性,則預設從 request 域對象中讀取 command 屬性的表單 bean,如果該屬性值也不存在,則會發生錯誤。

  SpringMVC 提供了多個表單組件標簽用以綁定表單欄位的屬性值,如 <form:input/>(同html標簽中 input type="text"),它們的共有屬性:

    • path表單欄位,對應 html 元素的 name 屬性,支持級聯屬性
    • htmlEscape:是否對錶單值的 HTML 特殊字元進行轉換,預設值為 true
    • cssClass:表單組件對應的 CSS 樣式類名
    • cssErrorClass:表單組件的數據存在錯誤時,採取的 CSS 樣式

  form:input、form:password、form:hidden、form:textarea:對應 HTML 表單的 text、password、hidden、textarea 標簽

  form:radiobutton:單選框組件標簽,當表單 bean 對應的屬性值和 value 值相等時,單選框被選中

  form:radiobuttons:單選框組標簽,用於構造多個單選框

    • items:可以是一個 List、String[] 或 Map
    • itemValue:指定 radio 的 value 值。可以是集合中 bean 的一個屬性值
    • itemLabel:指定 radio 的 label 值
    • delimiter:多個單選框可以通過 delimiter 指定分隔符

  form:checkbox:覆選框組件。用於構造單個覆選框

  form:checkboxs:用於構造多個覆選框。使用方式同 form:radiobuttons 標簽

  form:select:用於構造下拉框組件。使用方式同 form:radiobuttons 標簽

  form:option:下拉框選項組件標簽。使用方式同 form:radiobuttons 標簽

  form:errors:顯示表單組件或數據校驗所對應的錯誤

    • <form:errors path= “*” /> :顯示表單所有的錯誤
    • <form:errors path= “user*” /> :顯示所有以 user 為首碼的屬性對應的錯誤
    • <form:errors path= username /> :顯示特定表單對象屬性的錯誤
//修改功能需要增加絕對路徑,相對路徑會報錯,路徑不對
<form:form action="${pageContext.request.contextPath }/emp" method="POST" modelAttribute="employee(command)">
    LastName:<form:input path="lastName"/><br><br>
    Email:<form:input path="email"/><br><br>
    Gender:<form:radiobuttons path="gender" items="${genders }"/><br><br>
    Dept:
    <form:select path="department.id" items="${depts }" 
             itemLabel="departmentName" itemValue="id">
    </form:select>
    <br><br>
    <input type="submit" value="添加員工信息">
</form:form>

通過jQuery轉換為DELETE請求

  REST風格代碼,要求刪除功能,必須以DELETE方式提交。解決方案

    1. 準備一個以DELETE方式提交的form表單

    2. 通過單擊事件為準備好的form表單action屬性賦值。

    3. 觸發表單的submit事件

$(function(){
  $(".delete").click(function(){
    var href = $(this).attr("href");
    $("form").attr("action",href).submit();
    return false ;
  });
});

SpringMVC 處理靜態資源

  若將 DispatcherServlet 請求映射配置為 /, 則 Spring MVC 將捕獲 WEB 容器的所有請求, 包括靜態資源的請求, SpringMVC 會將他們當成一個普通請求處理, 因找不到對應處理器將導致錯誤。從而無法載入靜態資源

  解決: 需要在 SpringMVC 的配置文件中配置 <mvc:default-servlet-handler/> 它將在 SpringMVC 上下文中定義一個 DefaultServletHttpRequestHandler,它會對進入 DispatcherServlet 的請求進行篩查,如果發現是靜態資源的請求,就會由此處理器處理

    並且還需要配置<mvc:annotation-driven />,因為只配置上面一個所有請求又全部只由預設處理器來處理請求了

底層原理:Tomcat解析Servlet優先順序問題

  程式員定義的 Servlet優先順序大於Tomcat自己的Servlet

  URL中default-servlet配置 "*.jsp" 大於 "/" 的配置。

處理JSON和下載

HttpMessageConverter<T>

  HttpMessageConverter<T> 是 Spring3.0 新添加的一個介面,負責將請求信息轉換為一個對象(類型為 T),將對象(類型為 T)輸出為響應信息

  當控制器處理方法使用到 @RequestBody/@ResponseBody 或 HttpEntity<T>/ResponseEntity<T> 時, Spring 首先根據請求頭或響應頭的 Accept 屬性選擇匹配的 HttpMessageConverter,  進而根據參數類型或泛型類型的過濾得到匹配的 HttpMessageConverter, 若找不到可用的 HttpMessageConverter 將報錯 406

 

  HttpMessageConverter<T> 可將請求信息轉化並綁定到(controller)處理方法的入參中或將響應結果轉為對應類型的響應信息

SpringMVC處理 json

  1) jackson-annotations-2.1.5.jar

    jackson-core-2.1.5.jar

    jackson-databind-2.1.5.jar

  2)需要在配置文件設置 <mvc:annotation-driven />

    如此可將適配器AnnotationMethodHandlerAdapter升級為:RequestMappingHandlerAdapter 而 RequestMappingHandlerAdapter 適配器中存在MappingJackson2HttpMessageConverter

  3)@RequestBody / @ResponseBody 在處理方法上進行標註

      @RequestBody:是將Http請求正文插入到處理方法中,修飾目標方法的入參

      @ResponseBody:是將內容或對象作為Http響應正文返回去

將user對象轉為json對象返回,註意ajax設置dataType:"json"類型

@ResponseBody
@RequestMapping(value = "/json",method = RequestMethod.GET)
public User json(String string){
    return user;
}

 

非同步請求

            $("#username1").change(function () {
               var username = $("#username1").val();
               var dat = {
                   "username":username,
                   "_method":"PUT",
               };
               $.ajax({
                   url:"${pageContext.request.contextPath}/login",
                   type:"POST",
                   data:dat,
                   dataType:"json",
                   success:function (data) {
                       alert(data.name);
                   },
                   error:function () {
                       alert("請求失敗");
                   }
               });
            });

 

  HttpEntity<T>        作為處理方法的入參獲取文件大小請求頭等

  ResponseEntity<T>   作為處理方法的返回值,返回客戶端要下載的文件資源,實現文件下載功能

 下載

 @RequestMapping(value = "/downLoad",method = RequestMethod.GET)
    public ResponseEntity<byte[]> testDownLoad(HttpServletRequest request,HttpServletResponse response) throws IOException {
        ResponseEntity<byte[]> responseEntity = null;
        //1.獲取到download文件的真實路徑(推薦先放在項目根目錄下測試_downLoad為文件名)
        String path = request.getServletContext().getRealPath("/downLoad");
        //在請求體中獲取文件名
        String fileName = request.getParameter("fileName");
        //2.通過真實文件路徑創建File對象(File.separator為當前系統文件分隔符)
        File file = new File(path + File.separator + fileName);
        //3.創建文件輸入流,將要下載的文件讀取到程式中
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] bytes = new byte[fileInputStream.available()];
        //將文件一次性全部讀取到bytes中
        fileInputStream.read(bytes);
        //解決 文件名 中文亂碼問題
        String header = request.getHeader("User-Agent");
        if(header != null && header.contains("Firefox")) {
            fileName = "=?utf-8?B?"+new BASE64Encoder().encode(fileName.getBytes("utf-8"))+"?=";
        }else {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        }
        //創建響應頭
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Disposition", "attachment; filename="+fileName);
        //返回資源(HttpStatus.OK=200)
        responseEntity = new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK);
        fileInputStream.close();
        return responseEntity;
    }

 

文件上傳

  Spring MVC 為文件上傳提供了直接的支持,這種支持是通過即插即用的 MultipartResolver 實現的。實現類:CommonsMultipartResolver 

  Spring MVC 上下文中預設沒有裝配 MultipartResovler,因此預設情況下不能處理文件的上傳工作,需在上下文中配置 MultipartResolver

配置 MultipartResolver

  defaultEncoding: 必須和用戶 JSP 的 pageEncoding 屬性一致,以便正確解析表單的內容,為了讓 CommonsMultipartResolver 正確工作,必須先將 Commons-fileupload 及 Commons-io 的 jar 包添加到類路徑下。

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"></property>
        <property name="maxUploadSize" value="10240000"></property>
    </bean>

  MultipartResolver 用於處理文件上傳,當收到請求時 DispatcherServlet 的 checkMultipart() 方法會調用 MultipartResolver 的 isMultipart() 方法判斷請求中是否包含文件。如果請求數據中包含文件,則調用 MultipartResolver 的 resolveMultipart() 方法對請求的數據進行解析,然後將文件數據解析成 MultipartFile 並封裝在 MultipartHttpServletRequest (繼承了 HttpServletRequest) 對象中,最後傳遞給 Controller

上傳文件

<form action="${pageContext.request.contextPath}/upLoad" method="post" enctype="multipart/form-data">
    需上傳文件:<input type="file" name="file">
    <input type="submit">
</form>
    @RequestMapping(value = "/upLoad",method = RequestMethod.POST)
    public String upLoad(@RequestParam("file")MultipartFile multipartFile,HttpServletRequest request) throws IOException {
        //1.獲取upload的真實路徑
        String path = request.getServletContext().getRealPath("/upLoad");
        //如果此路徑不存在則創建此目錄
        File file1 = new File(path);
        if(!file1.exists()){
            file1.mkdir();
        }
        //2.獲取要上傳的文件名
        String filename = multipartFile.getOriginalFilename();
        //3.創建上傳file
        File file = new File(path + File.separator + filename);
        //4.實現文件上傳
        multipartFile.transferTo(file);
        return "home";
    }

 

多文件上傳

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 時間是這個世界上最公平東西,歲月不曾饒過誰,任何人都無法逃脫自然規律,我們程式員都要面對 35 歲這道坎,過了 35 歲就不能再跟年輕人拼體力了。隨著年齡的增長,體力不再是優勢了,這時候的優勢是更加成熟的心智,豐富的工作經歷,以及對自我更加清晰的認知。在綜合這些優勢的基礎上,重新找準自己的價值定位,... ...
  • content: 1. 為什麼要多進程編程?和多線程有什麼區別? 2. python 多進程編程 3. 進程間通信 一. 為什麼要多進程編程?和多線程有什麼區別? 由於GIL的存在,所以對於某一些多線程任務來說,無法利用多核的優勢,對這些耗cpu的任務,用多進程反而能利用多cpu。 所以多cpu的操 ...
  • 開發環境: Windows操作系統開發工具: MyEclipse+Jdk+Tomcat+MYSQL資料庫運行效果圖: 源碼及原文地址:http://javadao.xyz/forum.php?mod=viewthread&tid=73 ...
  • 本文主要介紹在web開發中經常被使用的Django框架。無論是老手亦或是剛接觸Django的開發者,肯定都會被Django易上手、周期短等優點所吸引。同樣,筆者也是特別是對其最初的設計邏輯很感興趣,於是筆者結合自己的學習在本文主要介紹Django框架的設計邏輯以及自己的一些理解,期望可以在加深本人理... ...
  • 1. 視圖 視圖的功能就是接收請求,進行處理,與M和T進行交互,返回應答。 返回html內容HttpResponse,也可能重定向redirect,還可以返回json數據。 1.1 URLconf 1.1.1 配置 用戶通過在瀏覽器的地址欄中輸入網址請求網站,對於Django開發的網站,由哪一個視圖 ...
  • Java 中的子類泛型轉型成父類泛型 步驟 1 : 對象轉型 根據面向對象學習的知識,子類轉父類 是一定可以成功的 package generic; import charactor.ADHero; import charactor.Hero; public class TestGeneric { ...
  • 需求 基於SSM實現一個垃圾分類查詢管理系統, 用戶可以根據自定義查詢分類信息, 管理員可以對分類信息, 垃圾詳情信息進行增刪改查的管理 運行環境 jdk1.8,tomcat8.5,mysql5.6,EclispseEE/Idea 項目技術 spring, springmvc, mybatis, b ...
  • 一、下載CMS源碼 https://www.yzmcms.com/xiazai 下載完成後得到一個這樣的壓縮包 接著下載PHPStudy,安裝只要一直點下一步就可以了 安裝完成後打開,如下圖啟動兩個地方 接著解壓一開始下載的那個PHPCMS壓縮包,把文件放到PHPStudy的制定目錄下,如下圖 最後 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...