分布式文件系統(tǒng)如何做?終于有篇文章分布式文件上傳講清楚了">分布式文件系統(tǒng)如何做?終于有篇文章分布式文件上傳講清楚了
827
2022-05-29
三、前端控制器
3.1、什么是前端控制器
在 MVC 框架中都存在一個前端控制器,在 WEB 應(yīng)用的前端(Front)設(shè)置一個入口控制器(Controller),是用來提供一個集中的請求處理機(jī)制,所有的請求都被發(fā)往該控制器統(tǒng)一處理,然后把請求分發(fā)給各自相應(yīng)的處理程序。一般用來做一個共同的處理,如權(quán)限檢查,授權(quán),日志記錄等。因為前端控制的集中處理請求的能力,因此提高了可重用性和可拓展性。
在沒有前端控制器的時候,我們是這樣傳遞和處理請求的。
有了前端控制器之后,我們變成了這樣。
3.2、代碼實現(xiàn)
Spring MVC 已經(jīng)提供了一個 DispatcherServlet 類作為前端控制器,所以要使用 Spring MVC 必須在web.xml 中配置前端控制器。
3.3、注意
load-on-startup 元素是可選的:若值為 0 或者大于 0 時,表示容器在應(yīng)用啟動時就構(gòu)建 Servlet 并調(diào)用其 init 方法做初始化操作(非負(fù)數(shù)的值越小,啟動該 Servlet 的優(yōu)先級越高);若值為一個負(fù)數(shù)時或者沒有指定時,則在第一次請求該 Servlet 才加載。配置的話,就可以讓 SpringMVC 初始化的工作在容器啟動的時候完成,而不是丟給用戶請求去完成,提高用戶訪問的體驗性。
3.4、映射路徑
配置前端控制器的映射路徑一般有以下的三種形式:
配置如 .do、.htm 是最傳統(tǒng)方式,可以訪問靜態(tài)文件(圖片、 JS、 CSS 等),但不支持 RESTful風(fēng)格。
配置成 /,可以支持流行的 RESTful 風(fēng)格,但會導(dǎo)致靜態(tài)文件(圖片、 JS、 CSS 等)被攔截后不能訪問。
配置成 /*,是錯誤的方式,可以請求到 Controller 中,但跳轉(zhuǎn)到調(diào)轉(zhuǎn)到 JSP 時被攔截,不能渲染JSP 視圖,也會導(dǎo)致靜資源訪問不了。
3.4.1、訪問靜態(tài)資源和 JSP 被攔截的原因
Tomcat 容器處理靜態(tài)資源是交由內(nèi)置 DefaultServlet 來處理的(攔截路徑是 /),處理 JSP 資源是交由內(nèi)置的 JspServlet 處理的(攔截路徑是*.jsp | *.jspx)。 啟動項目時,先加載容器的 web.xml,而后加載項目中的 web.xml。當(dāng)攔截路徑在兩者文件中配置的一樣,后面會覆蓋掉前者。 所以前端控制器配置攔截路徑是 / 的所有靜態(tài)資源都會交由前端控制器處理,而攔截路徑配置 /*,所有靜態(tài)資源和 JSP 都會交由前端控制器處理。
3.4.2、如何解決
在 web.xml 中修改,修改前端控制器的映射路徑修改為*.do,但注意,訪問控制器里的處理方法時,請求路徑須攜帶 .do。
在 mvc.xml中加入一段配置,這個配置會在 Spring MVC 上下文中創(chuàng)建存入一個 DefaultServletHttpRequestHandler 的 bean,它會
對進(jìn)入DispatcherServlet的請求進(jìn)行篩查,若不是映射的請求,就將該請求交由容器默認(rèn)的 Servlet處理。
3.5、@ModelAttribute 注解
在形參中的對象(必須是自定義類型),SpringMVC會默認(rèn)將他存入Model中,名稱是參數(shù)的類名首字母小寫,有些時候,這個類會顯得格外長,但是我們又有這種需求,比方說:查詢條件的回顯。我們只需在自定義類的前面加@ModelAttribute,里面寫我們需要修改的key的名稱即可。
package cn.wolfcode.web.controller; @Controller public class RequestController { @RequestMapping("/req7") public String resp7(@ModelAttribute("u") User user) { return "m"; } }
四、處理響應(yīng)
SpringMVC的作用是請求和處理響應(yīng),響應(yīng)處理是指怎么編寫控制器里面的處理方法接受請求做響應(yīng),找視圖文件和往作用域中存入數(shù)據(jù)。要處理方法要做響應(yīng),一般處理方法返回的類型為 ModelAndView 和 String。
4.1、返回 ModelAndView
方法中返回 ModelAndView 對象,此對象中設(shè)置模型數(shù)據(jù)并指定視圖。前端依舊是使用JSTL+CgLib來進(jìn)行取值。他有兩個常用方法:
addObject(String key, Object value):設(shè)置共享數(shù)據(jù)的 key 和 value。
addObject(Object value):設(shè)置共享數(shù)據(jù)的 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() { // 通過創(chuàng)建這個類對象,告訴 Spring MVC 找什么視圖文件, 往作用域或者說往模型中存入什么數(shù)據(jù) ModelAndView mv = new ModelAndView(); // 往作用域或者模型中存入數(shù)據(jù) mv.addObject("msg", "方法返回類型是 ModelAndView"); // 找視圖 mv.setViewName("/WEB-INF/views/resp.jsp"); return mv; }
4.2、返回String
返回 String 類型(使用廣泛),此時如果我們需要共享數(shù)據(jù),那么就需要用到HttpServlet對象,Spring幫我們封裝好了一個對象:Model 。組合使用,用其往作用域或模型中存入數(shù)據(jù)。
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) { // 往作用域或者模型中存入數(shù)據(jù) model.addAttribute("msg", "方法返回類型是 String"); // 返回視圖名 return "/WEB-INF/views/resp.jsp"; } }
4.3、改進(jìn)
我們會發(fā)現(xiàn),如果我們需要寫返回界面的話需要不斷的寫前綴和后綴,這個時候需要進(jìn)行消除消除視圖前綴和后綴,我們只需在Spring中進(jìn)行配置視圖解析器即可。
五、請求轉(zhuǎn)發(fā)和重定向
5.1、請求轉(zhuǎn)發(fā)和重定向的區(qū)別
5.2、請求轉(zhuǎn)發(fā)
加上forward 關(guān)鍵字,表示請求轉(zhuǎn)發(fā),相當(dāng)于request.getRequestDispatcher().forward(request,response),轉(zhuǎn)發(fā)后瀏覽器地址欄不變,共享之前請求中的數(shù)據(jù)。加了關(guān)鍵字后,配置的視圖解析器就不起作用了。如果返回視圖必須寫全路徑
package cn.linstudy.web.controller; @Controller public class ResponseController { @RequestMapping("/TestForward") public String forward() { return "forward:/WEB-INF/views/welcome.jsp"; } }
5.3、重定向
加上 redirect 關(guān)鍵字,表示重定向,相當(dāng)于 response.sendRedirect(),重定向后瀏覽器地址欄變?yōu)橹囟ㄏ蚝蟮牡刂罚还蚕碇罢埱蟮臄?shù)據(jù)。
package cn.linstudy.web.controller; @Controller public class ResponseController { // localhost/r @RequestMapping("/TestRedirect") public String redirect() { return "redirect:/static/demo.html"; } }
5.4、請求路徑
在請求轉(zhuǎn)發(fā)和重定向的時候,我們一般有兩種方式來寫請求路徑:
加/:使用是絕對路徑(推薦使用),從項目根路徑找。(/response/test6 —> “redirect:/hello.html” —> localhost:/hello.html)
不加/:使用是相對路徑,相對于上一次訪問上下文路徑的上一級找。(/response/test6 —> “redirect:hello.html” —> localhost:/response/hello.html)
六、參數(shù)處理
6.1、處理簡單類型的請求參數(shù)
我們在控制器的如何獲取請求中的簡單數(shù)據(jù)類型的參數(shù)參數(shù)?簡單數(shù)據(jù)類型包含基本數(shù)據(jù)類型及其包裝類、String 和BigDecimal 等形參接收。
6.1.1、請求參數(shù)名和控制器方法參數(shù)列表形參同名
如果前臺傳遞過來的參數(shù)名和控制器方法中參數(shù)列表的形參參數(shù)名相同就無需做任何操作,SpringMVC會自動幫我們進(jìn)賦值。
// 請求路徑為:/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; } }
6.1.2、請求參數(shù)名和控制器方法參數(shù)列表形參不同名
如果前臺傳遞過來的參數(shù)名和控制器方法中參數(shù)列表的形參參數(shù)名不相同的話,我們需要使用一個注解@RequestParam("前臺攜帶的參數(shù)名")來告訴SpringMVC我們?nèi)魏螌?shù)據(jù)來進(jìn)行賦值。
// 請求路徑為:/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; } }
6.2、處理復(fù)雜類型的請求參數(shù)
6.2.1、數(shù)組類型
對于數(shù)組類型參數(shù),我們只需在方法參數(shù)的形參列表中定義一個同名的數(shù)組類型進(jìn)行接收即可。
// 請求路徑 /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; } }
6.2.2、自定義類型
我們在很多的時候,需要接收的是一個自定義類型的對象。比如說我們進(jìn)行保存用戶,需要將前臺傳遞的數(shù)據(jù)進(jìn)行封裝成一個自定義的用戶類型,那么這個時候,只需要保證自定義的類型里面的字段和前端傳過來的字段相同(注意傳遞參數(shù)名與封裝對象的屬性名一致),SpringMVC即可自動進(jìn)行封裝。
// /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 } }
底層 Spring MVC 根據(jù)請求地址對應(yīng)調(diào)用處理方法,調(diào)用方法時發(fā)現(xiàn)要傳遞 User 類型的實參,SpringMVC 會反射創(chuàng)建 User 對象,之后通過請求參數(shù)名找對應(yīng)的屬性,給對象的屬性設(shè)置對應(yīng)的參數(shù)值。
6.3、處理日期類型的請求參數(shù)
6.3.1、日期在請求參數(shù)上
如果日期在請求參數(shù)上,那么我們需要在處理方法的 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; } }
6.3.2、在封裝的對象上
如果日期在封裝對象的字段,那么我們需要在字段的上貼@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 }
package cn.linstudy.controller; @Controller public class RequestController { @RequestMapping("/req6") public ModelAndView resp6(User user) { System.out.println(user); return null; } }
七、文件上傳與下載
7.1、文件上傳
回顧之前使用 Servlet3.0 來解決文件上傳的問題,編寫上傳表單(POST、multipart/form-data),還在處理方法 doPost 中編寫解析上傳文件的代碼。但是在SpringMVC是可以幫我們簡化文件上傳的步驟和代碼。
7.1.1、編寫表單
注意請求數(shù)據(jù)類型必須是:multipart/form-data,且請求方式是POST。
7.1.2、修改web.xml
我們可以在web.xml中指定上傳文件的大小。
7.1.3、配置上傳解析器
在mvc.xml中配置上傳解析器,使用springmvc中multipartfile接收客戶端上傳的文件必須配置文件上傳解析器且解析的id必須為multipartResolver
7.1.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()); // 文件參數(shù)名 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; } }
7.2、文件下載
文件下載
:將服務(wù)器上的文件下載到當(dāng)前用戶訪問的計算機(jī)的過程稱之為文件下載
7.2.1、開發(fā)控制器
下載時必須設(shè)置響應(yīng)的頭信息,指定文件以何種方式保存,另外下載文件的控制器不能存在返回值,代表響應(yīng)只用來下載文件信息`
/** * 測試文件下載 * @param fileName 要下載文件名 * @return */ @RequestMapping("download") public String download(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException { //獲取下載服務(wù)器上文件的絕對路徑 String realPath = request.getSession().getServletContext().getRealPath("/down"); //根據(jù)文件名獲取服務(wù)上指定文件 FileInputStream is = new FileInputStream(new File(realPath, fileName)); //獲取響應(yīng)對象設(shè)置響應(yīng)頭信息 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; }
MVC Servlet web前端
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。