首發日期:2018-11-01前端
【SpringMVC的配置有註解式配置的,也有XML配置的,因爲如今廣泛使用註解式的開發,因此這篇博文也主要講解註解式。】java
1.創建web工程,導入依賴包:web
【這裏只是一個基礎的包,僅僅實現簡單的springmvc功能,支持什麼切面編程之類的包都沒有。爲何說是最基礎的包,有個老哥測試過了:https://blog.csdn.net/frankcheng5143/article/details/50512340】spring
2.配置web.xml,聲明springmvc核心servlet。express
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!--springmvc.xml是咱們建立的springmvc核心配置文件 --> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
【有註解式配置的,也有XML配置的,因爲如今廣泛使用註解式的開發,因此這篇博文也主要講解註解式。】編程
1.下載springjson
2.建立web工程導入依賴包:數組
3.在web.xml中配置前端控制器,同時要指定springmvc配置文件的位置spring-mvc
<!-- 配置前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 設置springmvc的配置文件名稱 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <!-- Spring依賴核心servlet來分發請求,須要配置攔截路徑來將請求先交給servlet --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
【這裏要提一下:SpringMVC也須要Spring IOC容器,但若是Spring沒有初始化IOC容器,SpringMVC也會嘗試去初始化IOC;若是你的功能不涉及Spring,那麼你能夠不初始化IOC,若是你的功能涉及到Spring,那麼你應該在web.xml中加上下面的代碼來提早初始化】
<!-- 利用監聽器來初始化Spring工廠 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置參數,告訴核心過濾器讀取哪一個文件來建立工廠 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
4.建立HelloController:HelloController用於處理請求
package work.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; //先用註解的方式聲明是一個bean,方便springmvc管理。 @Controller public class HelloController{ //使用註解把/MySpringMVC01/hello.action請求與下面的方法對應起來 @RequestMapping("hello") public ModelAndView hello() { System.out.println("僞裝在處理業務"); //返回結果,由視圖解析器解析成視圖 return new ModelAndView("/WEB-INF/jsp/index.jsp"); } }
5.在springmvc配置文件中配置組件掃描,這樣纔可以把控制器上使用註解標明的請求與控制器的映射關係告訴springmvc【這個包掃描須要context的xsd】【注意,配置文件的講解將會在很後面講,但事實上內容很少,在尚未講以前,你均可以使用下面的配置文件來作練習】:
<?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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--掃描控制器所在的包,這樣纔可以識別註解 --> <context:component-scan base-package="work.controller" /> <mvc:annotation-driven /> </beans>
6.測試訪問:http://localhost:8080/MySpringMVC01/hello.action
上面的示例演示了請求是如何交給SpringMVC處理以及如何返回視圖的。這已經演示了「請求發起-請求處理-請求返回」的步驟了。
1.使用@Controller來註解類:
package work.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController{ //RequestMapping負責將請求與處理方法對應起來 @RequestMapping("/hello.action") public ModelAndView hello() { System.out.println("僞裝在處理業務"); //返回結果,由視圖解析器解析成視圖 return new ModelAndView("/WEB-INF/jsp/index.jsp"); } }
2.在配置文件中開啓包掃描:
<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 開啓組件掃描,使得spring可以識別出注解 --> <context:component-scan base-package="work.controller" /> </beans>
spring要知道請求與控制器的映射纔可以把提交的請求交給對應的控制器處理
/hello.action
/hello.action
或者/hello.*.action
或者/hello/*.action
/hello.action
或者/hello.*.action
或者/hello/*.action
@Controller public class HelloController{ //如下三種方式都會把/MySpringMVC01/hello.action請求與下面的方法對應起來 // @RequestMapping("/hello") // @RequestMapping("hello") @RequestMapping("/hello.action") public ModelAndView hello() { System.out.println("僞裝在處理業務"); //返回結果,由視圖解析器解析成視圖 return new ModelAndView("/WEB-INF/jsp/index.jsp"); } }
public ModelAndView save(HttpServletRequest request,HttpServletResponse response,HttpSession session)
,而後利用數據域對象來獲取數據:String id = request.getParameter("id");
【在形參中包含的數據域對象,springmvc會幫咱們封裝到形參中】@RequestMapping("login1") public ModelAndView login1(HttpServletRequest request) { System.out.println(request.getParameter("id")); return new ModelAndView("/WEB-INF/jsp/index.jsp"); }
在方法上增長參數同名形參。好比,頁面中有一個name="id"的輸入框提交了數據,那麼能夠在方法中定義一個與這個輸入框提交的數值數據類型相同的、形參名與name的屬性一致的形參。public ModelAndView save(Integer id)
【注意,定義了同名形參,但頁面沒有提交對應的表單項,這時候封裝的值爲null,因此若是形參的類型沒法存儲null則會報錯】
頁面表單的編寫:
<form action="login2.action" method="post"> <input type="text" name="id" > <input type="submit"> </form>
控制器方法的編寫:
@RequestMapping("login2") public ModelAndView login2(Integer id) {//頁面表單項名稱爲id System.out.println(id); return new ModelAndView("/WEB-INF/jsp/index.jsp"); }
同名參數自動封裝也支持POJO類中同名屬性,若是把一個POJO類對象做爲形參,當提交的表單項與POJO類對象的屬性同名時,也會把數據封裝到POJO類對象中,但要注意表單提交的name屬性必需與pojo的屬性名稱一致。表單的name要是 pojo的屬性名
,若是屬性是一個對象,那麼使用 pojo的內嵌對象變量名.內嵌對象的屬性名
頁面表單的編寫:
<form action="login3.action" method="post"> <!-- 普通屬性直接使用屬性名 --> <input type="text" name="id" > <input type="text" name="name" > <!-- 內嵌對象的屬性,用內嵌對象變量名.內嵌對象的屬性名 --> <input type="text" name="account.money" > <input type="submit"> </form>
控制器方法的編寫:
@RequestMapping("login3") public ModelAndView login3(User user) { System.out.println(user.getId()+"..."+user.getName()+"..."+ user.getAccount().getMoney()); return new ModelAndView("/WEB-INF/jsp/index.jsp"); }
@RequestParam:定義參數綁定規則,解決參數名與形參名不一致問題。這時候參數默認不能爲空(由@RequestParam的required屬性限制,required默認爲true)。
// public ModelAndView login4(@RequestParam("id") Integer uid) {//這時候必需要提交上來 public ModelAndView login4(@RequestParam(value="id",required=false) Integer uid) { //把提交的表單項名爲id的值存儲到形參uid中 System.out.println(uid); return new ModelAndView("/WEB-INF/jsp/index.jsp"); }
頁面的編寫:
<form action="login5.action" method="post"> <input type="checkbox" name="courses" value="Chinese" >語文 <input type="checkbox" name="courses" value="English" >英語 <input type="checkbox" name="courses" value="Math" >數學 <input type="submit"> </form>
控制器方法的編寫:
@RequestMapping("login5") public ModelAndView login5(String[] courses) { for (String course : courses) { System.out.println(course); } return new ModelAndView("/WEB-INF/jsp/index.jsp"); }
數組類型的數據封裝也是能夠封裝到POJO類對象中的,只要遵循形參命名規則便可。
而對於非同名的多選框,但又須要出現屢次時(相似批量修改多個表單項的狀況),一般使用List搭配POJO類來存儲。【注意這裏List封裝須要把List放到一個POJO類中(或者使用json方式來傳遞),它不可以直接在形參中使用同名形參封裝】
頁面的編寫:
<form action="login6.action" method="post"> 1:<input type="text" name="accounts[0].money"> 2:<input type="text" name="accounts[1].money"> 3:<input type="text" name="accounts[2].money"> <input type="submit"> </form>
控制器方法的編寫:
@RequestMapping("login6") public ModelAndView login6(MContainer mcontainer) { //MContainer類沒什麼特別意義,它裏面有List<Account> accounts。僅做演示 for (Account account : mcontainer.getAccounts()) { System.out.println(account); } return new ModelAndView("/WEB-INF/jsp/index.jsp"); }
{}
來包裹參數,而後在方法的形參中使用@PathVariable來指定形參獲取的是URL中的參數。@RequestMapping("shop/{product}/{id}") public ModelAndView shopOperation(@PathVariable("product") String product,@PathVariable("id")Integer id) { System.out.println("product:"+product+" id:"+id); return new ModelAndView("/WEB-INF/jsp/index.jsp"); } //<而後訪問`http://localhost:8080/項目名/shop/food/1000.action`,就能夠得出product爲food和id的值爲1000。
利用request傳遞數據:在方法中添加形參HttpServletRequest request,而後在方法中調用request的API便可。
@RequestMapping("paramreturn1") public ModelAndView paramreturn1(HttpServletRequest request) { //把數據存到request域中 request.setAttribute("name", "huluwa"); return new ModelAndView("/WEB-INF/jsp/showparam.jsp"); }
經過ModelAndView傳遞數據:在代碼中new ModelAndView()而後調用addObject方法把參數添加進去(數據會存儲到request域中,在視圖中能夠用EL表達式${參數名}
獲取)。ModelAndView還能夠做爲視圖返回結果,調用setName方法來設置返回的視圖。
@RequestMapping("paramreturn2") public ModelAndView paramreturn2() { ModelAndView mav = new ModelAndView(); String name=new String("Robert"); mav.addObject("name", name); mav.setViewName("/WEB-INF/jsp/showparam.jsp"); return mav; }
經過Model 傳遞數據:在方法中定義一個Model類對象的形參,利用Model類對象的addAttribute方法把參數傳遞給視圖。(數據會存儲到request域中)。
@RequestMapping("paramreturn3") public String paramreturn3(Model model) { String name=new String("Robert"); model.addAttribute("name", name); return "/WEB-INF/jsp/showparam.jsp"; }
經過ModelMap傳遞數據:在方法中定義一個ModelMap類對象的形參,利用ModelMap類對象的addAttribute方法把參數傳遞給視圖。【ModelMap是Model的實現類】
@RequestMapping("paramreturn4") public String paramreturn3(ModelMap modelmap) { String name=new String("Robert"); modelmap.addAttribute("name", name); return "/WEB-INF/jsp/showparam.jsp"; }
那麼,視圖怎麼獲取返回的參數呢?
能夠經過jsp標籤、jstl標籤、el表達式來獲取。數據都存儲在request域中,可使用以下的代碼來獲取。
<c:forEach items="${itemList }" var="item"> <tr> <td>${item.name }</td> <td>${item.price }</td> <td>${item.detail }</td> </tr> </c:forEach>
@RequestMapping的value的值還能夠是一個數組,表明控制器的方法映射給多個請求,使得多個請求路徑都交給同一個方法來處理。
@RequestMapping(value= {"mapping1","mapping2"}) public ModelAndView mapping1() { System.out.println("你訪問了mapping1"); return new ModelAndView("/WEB-INF/jsp/index.jsp");//隨意跳個頁面,關鍵是上面的打印結果 }
@RequestMapping註解除了能夠修飾方法,也能夠修飾類,修飾類的時候,至關於給方法下的@RequestMapping配置的請求路徑都加了一個父級目錄。
@Controller @RequestMapping("map") public class MappingTest { @RequestMapping(value= {"mapping1","mapping2"}) public ModelAndView mapping1() { System.out.println("你訪問了mapping1"); return new ModelAndView("/WEB-INF/jsp/index.jsp");//隨意跳個頁面,關鍵是上面的打印結果 } //如今調用方法要訪問http://localhost:8080/MySpringMVC01/map/mapping1.action }
@RequestMapping還能夠限定請求的方式,某些方法可能僅僅想限定POST方法來請求,那麼可使用method參數來設置。若是有多種容許的請求方法,使用數組括起來。
//只容許post方式請求 @RequestMapping(value="mapping3",method=RequestMethod.POST) public ModelAndView mapping3() { System.out.println("你訪問了mapping3"); return new ModelAndView("/WEB-INF/jsp/index.jsp");//隨意跳個頁面,關鍵是上面的打印結果 }
能夠經過返回一個ModelAndView對象來返回視圖:
手動設置視圖名稱:mav.setViewName("/WEB-INF/jsp/itemList.jsp");
構造函數傳入視圖名稱:ModelAndView mav=new ModelAndView("/WEB-INF/jsp/index.jsp");
@Controller public class ViewTest { @RequestMapping(value="mapping3") public ModelAndView view1() { System.out.println("你訪問了mapping3"); /*方式一,手動設置視圖名稱 ModelAndView mav=new ModelAndView(); mav.setViewName("/WEB-INF/jsp/index.jsp"); return mav; */ /*方式二,構造函數傳入視圖名稱 ModelAndView mav=new ModelAndView("/WEB-INF/jsp/index.jsp"); return mav; */ return new ModelAndView("/WEB-INF/jsp/index.jsp"); } }
經過返回一個字符串來返回視圖,字符串要求是視圖名稱字符串。
@RequestMapping(value="view2") public String view2() { System.out.println("你訪問了view2"); return "/WEB-INF/jsp/index.jsp"; }
返回void,利用request和response來進行跳轉視圖:【request和response跳轉視圖是不通過視圖解析器的】
經過request轉發:
@RequestMapping(value="view3") public void view3(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { System.out.println("你訪問了view3"); request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response); return; }
經過response重定向:
@RequestMapping(value="view4") public void view4(HttpServletResponse response) throws ServletException, IOException { System.out.println("你訪問了view4"); response.sendRedirect("/MySpringMVC01/login.jsp");//要注意路徑區別 return; }
返回以forward或redirect帶頭的字符串:
redirect:後面跟着的路徑能夠省去項目名,其餘都和response.sendRedirect()
差很少;forward:後面跟着的路徑與在request.getRequestDispatcher()
中填的差很少。【redirect:和forward:也能夠用在ModelAndView的返回視圖中】
@RequestMapping(value="view5") public String view5() { System.out.println("你訪問了view5"); // return "forward:/WEB-INF/jsp/index.jsp"; return "redirect:/login.jsp";//這裏能夠省去項目名 }
return "forward:hello.action";
return "redirect:hello.action";
return "hello.action";
request.getRequestDispatcher("hello.action").forward(request, response);
response.sendRedirect("hello.action")
return new ModelAndView("hello.action");
題外話:重定向時的數據存儲問題
按之前的來講,當咱們使用重定向時,像request數據域中的數據,在新的視圖中是獲取不了的。
咱們既想實現跳轉,又想保留數據,能夠利用redirect:和ModelAndView,咱們在ModelAndView中綁定數據,並在視圖名稱前加上
redirect:
便可,這樣ModelAndView中的數據仍然可以獲取。
<filter> <filter-name>encoding-filter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!-- 下面的參數是編碼成什麼格式,請求的數據默認是ISO-8859-1,下面的是目標字符集 --> <!-- 效果是request.setCharacterEncoding(this.encoding); --> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding-filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("utf-8");
題外話:返回視圖的時候,有些jsp文件的編碼不是utf-8,並且也沒有在代碼中顯式地設置字符編碼,爲何仍是能正確編碼?
由於Spring MVC的視圖解析器幫咱們解析了jsp文件的編碼格式,並幫咱們在http響應信息中自動設置了響應的字符編碼格式。
與applicationContext.xml的區別:springMVC.xml主要是針對SpringMVC,因此它的配置一般都是關於SpringMVC的配置,而一些例如屬性注入、事務的配置都交給Spring。
只有開啓了註解掃描,SpringMVC才能識別@Controller和@RequestMapping這些註解。
<context:component-scan base-package="work.controller" />
<mvc:annotation-driven />
上面這個操做會自動註冊RequestMappingHandlerMapping與RequestMappingHandlerAdapter兩個Bean,這兩個Bean是處理器映射器和處理器適配器,若是不配置,默認狀況下的使用的是舊版的處理器映射器和處理器適配器。新版的Bean增長了很多功能,包含數據綁定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持讀寫XML的支持(JAXB)和讀寫JSON的支持(默認Jackson)等功能
控制器返回結果給核心servlet,核心servlet把結果交給視圖解析器來進行解析。
視圖解析器負責解析視圖,咱們能夠給視圖解析器配置一些屬性,例如前綴和後綴,若是加了後綴.jsp
,那麼控制器返回的結果就會加上.jsp再進行解析。【好比加了後綴.jsp
,若是返回success,那麼解析結果應該是success.jsp】
<!-- 配置視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置視圖響應的前綴 --> <property name="prefix" value="/WEB-INF/jsp/" /> <!-- 配置視圖響應的後綴 --> <property name="suffix" value=".jsp" /> </bean>
配置了以後:以返回字符串方式的視圖跳轉爲例,return "success"解析出的視圖結果將是
/WEB-INF/jsp/success.jsp
1.定義一個攔截器類實現HandlerInterceptor接口中的三個方法。
public class LoginInterceptor implements HandlerInterceptor { @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { //注意這個方法有Exception形參 System.out.println("afterCompletion執行了"); } @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { //注意這個方法有ModelAndView形參 System.out.println("postHandle執行了"); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { if(request.getSession().getAttribute("loginUser")!=null) { //返回true放行,返回false不放行 return true; } response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("utf-8"); response.getWriter().println("你沒有權限,請登陸"); return false; } }
2.配置攔截器
定義了攔截器以後,咱們還須要把咱們定義的攔截器告訴springmvc。能夠在springmvc.xml中配置攔截器(須要注意須要引入mvc的xsd)
<!-- 開始攔截器定義,interceptors下能夠定義多個攔截器 --> <mvc:interceptors> <!-- 定義一個攔截器 --> <mvc:interceptor> <!-- path是要攔截的請求,/**表明攔截全部請求(包括二級以上目錄),/*表明攔截全部一級目錄請求 --> <mvc:mapping path="/**"/> <!-- bean的class裏面填攔截器的全限定名 --> <bean class="work.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
有多個攔截器時,攔截器的執行按照配置順序。
用於配置不進行攔截的請求。例如用戶有多個操做,不但願他在沒有登陸的狀況進行操做,但應該容許他發起登陸與註冊請求,那麼登陸和註冊就不該該被攔截器攔截,這時候就應該使用攔截排除。
<!-- 登陸攔截器 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <!-- 配置不攔截請求的地址,path裏面是不攔截的請求 --> <mvc:exclude-mapping path="/user/*"/> <bean class="work.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
<mvc:annotation-driven />
,那麼你可使用@ResponseBody和@RequestBody註解來與視圖進行JSON數據交互。【下面的依賴包是從SpringMVC4纔開始的,舊版本的話就不是下面三個】
@RequestMapping("/getCategory.action") @ResponseBody public Category getCategory(@RequestBody Category category) { System.out.println(category); return category; }
使用postman測試的結果:
在控制器中有時候可能也會發生異常,發生異常的時候,若是不進行處理,異常會顯示到頁面上。因此咱們一般都須要在控制器中進行異常處理,但下面講到的SpringMVC支持的全局異常處理器能夠攔截控制器拋出的全部異常,也就是說能夠在全局異常處理器中統一處理異常。
若是控制器沒有處理異常,那麼能夠由全局異常處理器處理異常。
1.實現接口HandlerExceptionResolver並實現resolveException方法,resolveException是用來處理異常的,返回結果是一個ModelAndView,這表明了處理完異常了能夠跳轉到一個視圖中顯示異常。
public class CategoryException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object hanlder, Exception e) { System.out.println(e.getStackTrace()); String message="抱歉,系統發生了錯誤"; ModelAndView mav = new ModelAndView(); mav.addObject("message", message); mav.setViewName("/error.jsp"); return mav; } }
2.配置異常處理器
只須要把全局異常處理器配置成一個bean便可,因爲繼承了andlerExceptionResolver,SpringMVC很清楚它是什麼東西。
<bean class="work.exception.CategoryException"></bean>
1.首先,建立自定義異常類,繼承Exception,要求要有帶錯誤信息的構造方法(這樣就能構造自定義的異常信息了。)另外,最好有異常信息的getter和setter方法,這樣全局異常處理器就能夠經過getter來獲取異常信息了,否則採用默認的異常構造方式的話還要利用e.getMessage()來獲取異常。
public class MyException extends Exception { private String msg;//這是自定義的異常信息 public MyException() { super(); } public MyException(String msg) { super(); this.msg = msg; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
2.在控制器中拋出自定義異常。
@RequestMapping("/save.action") public ModelAndView save(Category category) throws MyException { System.out.println(category); categoryService.save(category); if(true) {//這裏假設發生了異常 throw new MyException("保存商品失敗!"); } return new ModelAndView("findAll.action"); }
3.修改全局處理器代碼,使得可以獲取自定義異常信息。
public class CategoryException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object hanlder, Exception e) { String message="抱歉,系統發生了錯誤"; //獲取拋出的自定義異常信息 if(e instanceof MyException) { message=((MyException)e).getMsg();; } ModelAndView mav = new ModelAndView(); mav.addObject("message", message); mav.setViewName("/error.jsp"); return mav; } }
在開發中,或許須要上傳文件,SpringMVC也提供了很方便的上傳文件功能。
1.首先導入依賴包:
2.在springmvc.xml中配置多媒體解析器
<!-- 配置多媒體處理器 --> <!-- 下面的id必須是multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 裏面能夠配置一系列的值,用於配置上傳文件的限制 --> </bean>
3.編寫測試頁面:
【要加上enctype="multipart/form-data",但注意這並不會影響其餘數據的封裝,由於有了多媒體處理器。】
<form class="form-inline" action="save.action" method="post" enctype="multipart/form-data"> <!-- 省去其餘內容 --> <div class="form-group"> <label for="pimage">商品圖片</label> <input type="file" class="form-control" id="pimage" placeholder="商品圖片" name="uploadFile"> </div> <div class="form-group"> <button type="submit" class="btn btn-default">提交</button> </div> </form>
4.編寫文件上傳代碼:在形參中添加一個參數:MultipartFile uploadfile【若是是MultipartFile類的,那麼上傳的數據會自動封裝到對象中】【要求MultipartFile形參的名字與上傳項的name相同,否則須要@RequestParam強制對應】
@RequestMapping("save.action") public ModelAndView save(Product product,MultipartFile uploadFile) throws Exception { System.out.println(product); String name = UUID.randomUUID().toString(); //隨機獲取文件名,避免重複 String oldName = uploadFile.getOriginalFilename();//獲取原文件名 System.out.println(oldName); String extName = oldName.substring(oldName.lastIndexOf("."));//獲取擴展名 File file=new File("D:\\upload\\"+name+extName);//文件存儲的路徑 uploadFile.transferTo(file);//存儲文件到指定位置 product.setPimage(name+extName); productService.save(product); ModelAndView mav= new ModelAndView(); mav.setViewName("findAll.action"); return mav; }
這裏沒寫,準備後期有空寫的內容: