你真的了解嗎?一文詳解底層原理!

      網友投稿 732 2025-04-03

      前言


      一、SpringMVC簡介

      1.1、SpringMVC引言

      為了使Spring有可插入的MVC架構,SpringFrameWork在Spring基礎上開發SpringMVC框架,從而在使用Spring進行WEB開發時可以選擇使用Spring的SpringMVC框架作為web開發的控制器框架。

      1.2、SpringMVC的優勢

      SpringMVC是一個典型的輕量級MVC框架,在整個MVC架構中充當控制器框架,相對于之前的struts2框架,SpringMVC運行更快,其注解式開發更高效靈活。

      可以和Spring框架無縫整合。

      運行效率遠遠高于struts2框架。

      注解式開發更高效。

      二、SpringMVC入門

      2.1、環境搭建

      依賴就忽略了,我放在了評論區!

      1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      Archetype Created Web Application springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc.xml springmvc / 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      package com.lin.controller; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author XiaoLin * @date 2021/2/17 17:09 */ @Controller public class HellowController { /** * @Description:第一個springmvc測試類 * @author XiaoLin * @date 2021/2/17 * @Param: [username, password] * @return java.lang.String */ /* RequestMapping的修飾范圍:可以用在類上和方法上,他的作用如下: 1. 用在方法上可以給當前方法加入指定的請求路徑 2. 用在類上可以給類中的所有方法都加入一個統一的請求路徑,在這個方法訪問之前都必須加上 */ @RequestMapping("/hello") public String hello(String username,String password){ System.out.println("hello"); return "index"; } } 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      2.2、注解詳解

      該注解用來類上標識這是一個控制器組件類并創建這個類實例,告訴spring我是一個控制器。

      這個注解可以作用在方法上或者是類上,用來指定請求路徑。

      傳統的Servlet開發跳轉方式有兩種:

      forward:forward跳轉,是在服務器內部跳轉,所以是一次請求,地址欄不變。跳轉時可以攜帶數據進行傳遞(使用request作用域進行傳遞)。

      redirect:redirect跳轉是客戶端跳轉,所以是多次請求,地址欄會改變,跳轉時不可以攜帶數據傳遞。

      通過測試我們可以發現,SpringMVC默認的就是使用請求轉發的方式來進行跳轉到前臺頁面的;

      @Controller @RequestMapping("forwoartAndRedirect") public class TestForwoartAndRedirect { @RequestMapping("test") public String test(){ System.out.println("test"); return"index"; } }1.2.3.4.5.6.7.8.9.10.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      如果我們想使用重定向的方式來進行跳轉的話,需要使用SpringMVC提供給我們的關鍵字——redirect:來完成。

      語法:return “redirect:/視圖全路徑名”;

      **注意:**在redirect:后接頁面的不是邏輯名,而是全路徑名。因為redirect跳轉不會經過視圖解析器。

      如果我們想使用請求轉發的方式跳轉到相同(不同)Controller的不同方法的時候,我們也需要使用SpringMVC提供的關鍵字:forward:。

      語法:return:“forward: /需要跳轉的類上的@RequestMapping的值/需要跳轉的方法上的@RequestMapping的值;”

      如果我們想使用重定向的方式跳轉到相同(不同)Controller的不同方法的時候,我們也需要使用SpringMVC提供的關鍵字:redirect:。

      語法:return:“redirect: /需要跳轉的類上的@RequestMapping的值/需要跳轉的方法上的@RequestMapping的值;”

      2.4、SpringMVC的參數接收

      在傳統的Servlet開發,我們一般都是用這種方式來進行接收請求參數的。

      // 接收名字為name的參數 request.getParameter(name)1.2.

      1

      2

      他有幾個需要注意的點:

      參數要求是表單域的name屬性。

      getParameter方法用于獲取單個值, 返回類型是String。

      getParameterValues方法用于獲取一組數據, 返回結果是String[]。

      冗余代碼較多, 使用麻煩, 類型需要自己轉換。

      SpringMVC使用的是控制器中方法形參列表來接收客戶端的請求參數,他可以進行自動類型轉換,要求傳遞參數的key要與對應方法的形參變量名一致才可以完成自動賦值。他的優勢很明顯:

      簡化參數接收形式(不需要調用任何方法, 需要什么參數, 就在控制器方法中提供什么參數)。

      參數類型不需要自己轉換了。日期時間(默認為yyyy/MM/dd)得注意,需要使用@DateTimeFormat注解聲明日期轉換時遵循的格式, 否則拋出400異常。

      要求傳遞參數的key要與對應方法的形參變量名一致才可以完成自動賦值。

      如果我們需要接收對象類型的話,直接將需要接收的對象作為控制器的方法參數聲明即可。SpringMVC會自動封裝對象,若傳遞參數key與對象中屬性名一致,就會自動封裝成對象。

      如果我們需要接收數組類型的時候,只需將要接收的數組類型直接聲明為方法的形式參數即可。

      SpringMVC不能直接通過形式參數列表的方式接收集合類型的參數,如果需要接收集合類型的參數必須將集合放入一個對象中,并且提供get/set方法,才可以。推薦放入VO對象中進行封裝,進而使用對象類型來進行接收。

      2.5、SpringMVC接收參數中文亂碼問題

      GET請求方式出現亂碼需要分Tomcat版本進行討論:

      Tomcat8.x版本之前:默認使用server.xml中的URIEncoding="ISO-8859-1"編碼,而不是"UTF-8"編碼,進而會出現中文亂碼。

      Tomcat8.x版本之后:默認使用server.xml中的URIEncoding=“UTF-8”,所以不會出現中文亂碼問題。

      SpringMVC中默認沒有對POST請求進行任何編碼處理,所以無論什么版本直接接收POST請求都會出現中文亂碼。

      在Servlet階段,我們學過過濾器,我們可以自定義過濾器來進行過濾編碼。

      package com.filter; import javax.servlet.*; import java.io.IOException; //自定義編碼filter public class CharacterEncodingFilter implements Filter { private String encoding; @Override public void init(FilterConfig filterConfig) throws ServletException { this.encoding = filterConfig.getInitParameter("encoding"); System.out.println(encoding); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(encoding); response.setCharacterEncoding(encoding); chain.doFilter(request,response); } @Override public void destroy() { } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      charset com.filter.CharacterEncodingFilter encoding UTF-8 charset /* 1.2.3.4.5.6.7.8.9.10.11.12.13.14.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      charset org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 charset /* 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      package com.filter; import javax.servlet.*; import java.io.IOException; //自定義編碼filter public class CharacterEncodingFilter implements Filter { private String encoding; @Override public void init(FilterConfig filterConfig) throws ServletException { this.encoding = filterConfig.getInitParameter("encoding"); System.out.println(encoding); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(encoding); response.setCharacterEncoding(encoding); chain.doFilter(request,response); } @Override public void destroy() { } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      2.6、SpringMVC中數據傳遞機制

      數據傳遞機制主要包含三個問題:

      數據如何存儲?

      如何在頁面中獲取數據?

      在頁面中獲取的數據該如何展示?

      在以前的Servlet開發中,我們一般是將數據放入作用域(request、session、Application),如果數據是單個的直接用EL表達式在前端進行展示,如果是集合或者數組,可以用EL表達式?JSTL標簽進行遍歷后在前端進行展示。

      三、前端控制器

      3.1、什么是前端控制器

      在 MVC 框架中都存在一個前端控制器,在 WEB 應用的前端(Front)設置一個入口控制器(Controller),是用來提供一個集中的請求處理機制,所有的請求都被發往該控制器統一處理,然后把請求分發給各自相應的處理程序。一般用來做一個共同的處理,如權限檢查,授權,日志記錄等。因為前端控制的集中處理請求的能力,因此提高了可重用性和可拓展性。

      在沒有前端控制器的時候,我們是這樣傳遞和處理請求的。

      有了前端控制器之后,我們變成了這樣。

      3.2、代碼實現

      Spring MVC 已經提供了一個 DispatcherServlet 類作為前端控制器,所以要使用 Spring MVC 必須在web.xml 中配置前端控制器。

      dispatcherServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:mvc.xml 1 dispatcherServlet / 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.

      1

      2

      3

      4

      你真的了解嗎?一文詳解底層原理!

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      3.3、注意

      load-on-startup 元素是可選的:若值為 0 或者大于 0 時,表示容器在應用啟動時就構建 Servlet 并調用其 init 方法做初始化操作(非負數的值越小,啟動該 Servlet 的優先級越高);若值為一個負數時或者沒有指定時,則在第一次請求該 Servlet 才加載。配置的話,就可以讓 SpringMVC 初始化的工作在容器啟動的時候完成,而不是丟給用戶請求去完成,提高用戶訪問的體驗性。

      3.4、映射路徑

      配置前端控制器的映射路徑一般有以下的三種形式:

      配置如 .do、.htm 是最傳統方式,可以訪問靜態文件(圖片、 JS、 CSS 等),但不支持 RESTful風格。

      配置成 /,可以支持流行的 RESTful 風格,但會導致靜態文件(圖片、 JS、 CSS 等)被攔截后不能訪問。

      配置成 /*,是錯誤的方式,可以請求到 Controller 中,但跳轉到調轉到 JSP 時被攔截,不能渲染JSP 視圖,也會導致靜資源訪問不了。

      Tomcat 容器處理靜態資源是交由內置 DefaultServlet 來處理的(攔截路徑是 /),處理 JSP 資源是交由內置的 JspServlet 處理的(攔截路徑是*.jsp | *.jspx)。 啟動項目時,先加載容器的 web.xml,而后加載項目中的 web.xml。當攔截路徑在兩者文件中配置的一樣,后面會覆蓋掉前者。 所以前端控制器配置攔截路徑是 / 的所有靜態資源都會交由前端控制器處理,而攔截路徑配置 /*,所有靜態資源和 JSP 都會交由前端控制器處理。1.2.3.

      1

      2

      3

      在 web.xml 中修改,修改前端控制器的映射路徑修改為*.do,但注意,訪問控制器里的處理方法時,請求路徑須攜帶 .do。

      dispatcherServlet *.do 1.2.3.4.

      1

      2

      3

      4

      在 mvc.xml中加入一段配置,這個配置會在 Spring MVC 上下文中創建存入一個

      DefaultServletHttpRequestHandler 的 bean,它會 對進入DispatcherServlet的請求進行篩查,若不是映射的請求,就將該請求交由容器默認的 Servlet處理。

      1.

      1

      3.5、@ModelAttribute注解

      在形參中的對象(必須是自定義類型),SpringMVC會默認將他存入Model中,名稱是參數的類名首字母小寫,有些時候,這個類會顯得格外長,但是我們又有這種需求,比方說:查詢條件的回顯。我們只需在自定義類的前面加@ModelAttribute,里面寫我們需要修改的key的名稱即可。

      package cn.wolfcode.web.controller; @Controller public class RequestController { @RequestMapping("/req7") public String resp7(@ModelAttribute("u") User user) { return "m"; } }1.2.3.4.5.6.7.8.

      1

      2

      3

      4

      5

      6

      7

      8

      四、處理響應

      SpringMVC的作用是請求和處理響應,響應處理是指怎么編寫控制器里面的處理方法接受請求做響應,找視圖文件和往作用域中存入數據。要處理方法要做響應,一般處理方法返回的類型為 ModelAndView 和 String。

      4.1、返回 ModelAndView

      方法中返回 ModelAndView 對象,此對象中設置模型數據并指定視圖。前端依舊是使用JSTL+CgLib來進行取值。他有兩個常用方法:

      addObject(String key, Object value):設置共享數據的 key 和 value。

      addObject(Object value):設置共享數據的 value,key 為該 value 類型首字母小寫。

      package cn.linstudy.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class ResponseController { // 提供方法處理請求,localhost/resp1 @RequestMapping("/resp1") public ModelAndView resp1() { // 通過創建這個類對象,告訴 Spring MVC 找什么視圖文件, 往作用域或者說往模型中存入什么數據 ModelAndView mv = new ModelAndView(); // 往作用域或者模型中存入數據 mv.addObject("msg", "方法返回類型是 ModelAndView"); // 找視圖 mv.setViewName("/WEB-INF/views/resp.jsp"); return mv; }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      4.2、返回String

      返回 String 類型(使用廣泛),此時如果我們需要共享數據,那么就需要用到HttpServlet對象,Spring幫我們封裝好了一個對象:Model 。組合使用,用其往作用域或模型中存入數據。

      package cn.instudy.web.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class ResponseController { // 提供方法處理請求,localhost/resp2 @RequestMapping("/resp2") public String resp2(Model model) { // 往作用域或者模型中存入數據 model.addAttribute("msg", "方法返回類型是 String"); // 返回視圖名 return "/WEB-INF/views/resp.jsp"; } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      4.3、改進

      我們會發現,如果我們需要寫返回界面的話需要不斷地寫前綴和后綴,這個時候需要進行消除消除視圖前綴和后綴,我們只需在Spring中進行配置視圖解析器即可。

      1.2.3.4.5.6.7.8.9.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      五、請求轉發和重定向

      5.1、請求轉發和重定向的區別

      5.2、請求轉發

      加上forward 關鍵字,表示請求轉發,相當于

      request.getRequestDispatcher().forward(request,response),轉發后瀏覽器地址欄不變,共享之前請求中的數據。加了關鍵字后,配置的視圖解析器就不起作用了。如果返回視圖必須寫全路徑

      package cn.linstudy.web.controller; @Controller public class ResponseController { @RequestMapping("/TestForward") public String forward() { return "forward:/WEB-INF/views/welcome.jsp"; } }1.2.3.4.5.6.7.8.9.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      5.3、重定向

      加上 redirect 關鍵字,表示重定向,相當于 response.sendRedirect(),重定向后瀏覽器地址欄變為重定向后的地址,不共享之前請求的數據。

      package cn.linstudy.web.controller; @Controller public class ResponseController { // localhost/r @RequestMapping("/TestRedirect") public String redirect() { return "redirect:/static/demo.html"; } }1.2.3.4.5.6.7.8.9.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      5.4、請求路徑

      在請求轉發和重定向的時候,我們一般有兩種方式來寫請求路徑:

      加/:使用是絕對路徑(推薦使用),從項目根路徑找。(/response/test6 —> “redirect:/hello.html” —> localhost:/hello.html)

      不加/:使用是相對路徑,相對于上一次訪問上下文路徑的上一級找。(/response/test6 —> “redirect:hello.html” —> localhost:/response/hello.html)

      六、參數處理

      6.1、處理簡單類型的請求參數

      我們在控制器的如何獲取請求中的簡單數據類型的參數參數?簡單數據類型包含基本數據類型及其包裝類、String 和BigDecimal 等形參接收。

      如果前臺傳遞過來的參數名和控制器方法中參數列表的形參參數名相同就無需做任何操作,SpringMVC會自動幫我們進賦值。

      // 請求路徑為:/req1?username=zs&age=18 package cn.linstudy.web.controller; @Controller public class RequestController { @RequestMapping("/req1") public ModelAndView resp1(String username, int age) { System.out.println(username); System.out.println(age); return null; } }1.2.3.4.5.6.7.8.9.10.11.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      如果前臺傳遞過來的參數名和控制器方法中參數列表的形參參數名不相同的話,我們需要使用一個注解@RequestParam(“前臺攜帶的參數名”)來告訴SpringMVC我們任何對數據來進行賦值。

      // 請求路徑為:/req1?username=zs&age=18 package cn.linstudy.web.controller; @Controller public class RequestController { @RequestMapping("/req1") public ModelAndView resp1(@RequestParam("username") String username1, @RequestParam("age") int age1) { System.out.println(username); System.out.println(age); return null; } }1.2.3.4.5.6.7.8.9.10.11.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      6.2、處理復雜類型的請求參數

      對于數組類型參數,我們只需在方法參數的形參列表中定義一個同名的數組類型進行接收即可。

      // 請求路徑 /req3?ids=1&ids=2&ids=3 package cn.linstudy.web.controller; @Controller public class RequestController { @RequestMapping("/req3") public ModelAndView resp3(Long[] ids) { System.out.println(Arrays.toString(ids)); return null; } }1.2.3.4.5.6.7.8.9.10.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      我們在很多的時候,需要接收的是一個自定義類型的對象。比如說我們進行保存用戶,需要將前臺傳遞的數據進行封裝成一個自定義的用戶類型,那么這個時候,只需要保證自定義的類型里面的字段和前端傳過來的字段相同(注意傳遞參數名與封裝對象的屬性名一致),SpringMVC即可自動進行封裝。

      // /req4?username=hehe&password=666 package cn.linstudy.web.controller; @Controller public class RequestController { @RequestMapping("/req4") public ModelAndView resp4(User user) { System.out.println(user); return null } }1.2.3.4.5.6.7.8.9.10.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      底層 Spring MVC 根據請求地址對應調用處理方法,調用方法時發現要傳遞 User 類型的實參,SpringMVC 會反射創建 User 對象,之后通過請求參數名找對應的屬性,給對象的屬性設置對應的參數值。

      6.3、處理日期類型的請求參數

      如果日期在請求參數上,那么我們需要在處理方法的 Date 類型的形參貼上 @DateTimeFormat注解。

      package cn.linstudy.controller; @Controller public class RequestController { @RequestMapping("/req5") // 注意形參的類型為 java.util.Date public ModelAndView resp5(@DateTimeFormat(pattern="yyyy-MM-dd")Date date) { System.out.println(date.toLocaleString()); return null; } }1.2.3.4.5.6.7.8.9.10.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      如果日期在封裝對象的字段,那么我們需要在字段的上貼@DateTimeFormat注解。

      package cn.linstudy.domain; public class User { private Long id; private String Username; private String password; // 增加下面這個字段,并貼注解 @DateTimeFormat(pattern="yyyy-MM-dd") private Date date; // 省略 setter getter toString }1.2.3.4.5.6.7.8.9.10.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      package cn.linstudy.controller; @Controller public class RequestController { @RequestMapping("/req6") public ModelAndView resp6(User user) { System.out.println(user); return null; } }1.2.3.4.5.6.7.8.9.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      七、文件上傳與下載

      7.1、文件上傳

      回顧之前使用 Servlet3.0 來解決文件上傳的問題,編寫上傳表單(POST、multipart/form-data),還在處理方法 doPost 中編寫解析上傳文件的代碼。但是在SpringMVC是可以幫我們簡化文件上傳的步驟和代碼。

      注意請求數據類型必須是:multipart/form-data,且請求方式是POST。

      文件上傳

      文件:
      1.2.3.4.5.6.7.8.9.10.11.12.13.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      我們可以在web.xml中指定上傳文件的大小。

      dispatcherServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:mvc.xml 1 52428800 52428800 dispatcherServlet / 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      在mvc.xml中配置上傳解析器,使用springmvc中multipartfile接收客戶端上傳的文件必須配置文件上傳解析器且解析的id必須為multipartResolver

      1.2.3.4.

      1

      2

      3

      4

      package cn.linstudy.controller; @Controller public class UploadController { // Spring 容器存在 ServletContext 類型的對象,所以定義好 ServletContext 類型字段貼@Autowired 注解即可獲取到 @Autowired private ServletContext servletContext; @RequestMapping("/upload") public ModelAndView upload(Part pic) throws Exception { System.out.println(pic.getContentType()); // 文件類型 System.out.println(pic.getName()); // 文件參數名 System.out.println(pic.getSize()); // 文件大小 System.out.println(pic.getInputStream()); // 文件輸入流 // FileCopyUtils.copy(in, out),一個 Spring 提供的拷貝方法 // 獲取項目 webapp 目錄下 uploadDir 目錄的絕對路徑 System.out.println(servletContext.getRealPath("/uploadDir")); return null; } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      7.2、文件下載

      文件下載:將服務器上的文件下載到當前用戶訪問的計算機的過程稱之為文件下載

      下載時必須設置響應的頭信息,指定文件以何種方式保存,另外下載文件的控制器不能存在返回值,代表響應只用來下載文件信息`

      復制

      /** * 測試文件下載 * @param fileName 要下載文件名 * @return */ @RequestMapping("download") public String download(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException { //獲取下載服務器上文件的絕對路徑 String realPath = request.getSession().getServletContext().getRealPath("/down"); //根據文件名獲取服務上指定文件 FileInputStream is = new FileInputStream(new File(realPath, fileName)); //獲取響應對象設置響應頭信息 response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8")); ServletOutputStream os = response.getOutputStream(); IOUtils.copy(is,os); IOUtils.closeQuietly(is); IOUtils.closeQuietly(os); return null;

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      MVC Spring

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:奇妙的Excel自定義數字格式
      下一篇:突然打不出來字了(為什么突然打不出來字)
      相關文章
      亚洲av无码专区在线观看下载| 亚洲Av无码一区二区二三区| 亚洲熟女综合一区二区三区| 亚洲三级在线免费观看| 亚洲AV成人无码久久精品老人 | 亚洲一区AV无码少妇电影☆| 亚洲国产精品毛片av不卡在线 | 少妇亚洲免费精品| 亚洲6080yy久久无码产自国产| 亚洲精品无码久久久久YW| 亚洲一区二区三区在线观看网站| 亚洲国产午夜精品理论片| 亚洲国产精品成人精品小说| 亚洲首页在线观看| 亚洲春色另类小说| 亚洲啪啪免费视频| 国产精品亚洲综合久久| 亚洲真人无码永久在线观看| 亚洲午夜成人精品无码色欲| 亚洲欧美成人av在线观看| 亚洲AV永久无码精品放毛片| 久久精品熟女亚洲av麻豆| 欧洲亚洲综合一区二区三区| 内射无码专区久久亚洲| 亚洲欧洲日产国码一级毛片| 久久精品国产精品亚洲艾草网美妙| 国产国拍亚洲精品福利| 久久亚洲国产午夜精品理论片| 久久久久亚洲av无码专区蜜芽| 亚洲天天在线日亚洲洲精| 亚洲沟沟美女亚洲沟沟| 亚洲日本乱码卡2卡3卡新区| 亚洲乱码中文字幕在线| 亚洲成a人片在线观看久| 久久久久久久亚洲精品| 亚洲AV无码一区二区乱子伦| 中文字幕亚洲精品| 色天使亚洲综合在线观看| 久久无码av亚洲精品色午夜 | 亚洲XX00视频| 久久亚洲国产欧洲精品一|