文件上傳客戶端表單須要知足:html
表單項type=「file」前端
表單的提交方式是postjava
表單的enctype屬性是多部分表單形式,及enctype=「multipart/form-data」web
<form action="${pageContext.request.contextPath}/user/quick22" method="post" enctype="multipart/form-data"> 名稱<input type="text" name="username"><br/> 文件1<input type="file" name="uploadFile"><br/> <input type="submit" value="提交"> </form>
添加依賴spring
<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.3</version> </dependency>
配置多媒體解析器spring-mvc
<!--配置文件上傳解析器--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UYF-8"/> <property name="maxUploadSize" value="500000"/> </bean>
後臺程序session
@RequestMapping(value="/quick22") @ResponseBody public void save22(String username, MultipartFile uploadFile) throws IOException { System.out.println(username); System.out.println(uploadFile); }
完成文件上傳mvc
@RequestMapping(value="/quick22") @ResponseBody public void save22(String username, MultipartFile uploadFile) throws IOException { System.out.println(username); //得到上傳文件的名稱 String originalFilename = uploadFile.getOriginalFilename(); uploadFile.transferTo(new File("C:\\upload\\"+originalFilename)); }
多文件上傳,只須要將頁面修改成多個文件上傳項,將方法參數MultipartFile類型修改成MultipartFile[]便可app
<form action="${pageContext.request.contextPath}/user/quick23" method="post" enctype="multipart/form-data"> 名稱<input type="text" name="username"><br/> 文件1<input type="file" name="uploadFile"><br/> 文件2<input type="file" name="uploadFile"><br/> <input type="submit" value="提交"> </form>
@RequestMapping(value="/quick23") @ResponseBody public void save23(String username, MultipartFile[] uploadFile) throws IOException { System.out.println(username); for (MultipartFile multipartFile : uploadFile) { String originalFilename = multipartFile.getOriginalFilename(); multipartFile.transferTo(new File("C:\\upload\\"+originalFilename)); } }
Spring MVC 的攔截器相似於 Servlet 開發中的過濾器 Filter,用於對處理器進行預處理和後處理。jsp
將攔截器按必定的順序聯結成一條鏈,這條鏈稱爲攔截器鏈(InterceptorChain)。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其以前定義的順序被調用。攔截器也是AOP思想的具體實現。
關於interceptor和filter的區別,如圖所示:
自定義攔截器很簡單,只有以下三步:
①建立攔截器類實現HandlerInterceptor接口
②配置攔截器
③測試攔截器的攔截效果
編寫攔截器:
public class MyInterceptor1 implements HandlerInterceptor { //在目標方法執行以前 執行 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException { System.out.println("preHandle....."); } //在目標方法執行以後 視圖對象返回以前執行 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { System.out.println("postHandle..."); } //在流程都執行完畢後 執行 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("afterCompletion...."); } }
配置:在SpringMVC的配置文件中配置
<!--配置攔截器--> <mvc:interceptors> <mvc:interceptor> <!--對哪些資源執行攔截操做--> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.MyInterceptor1"/> </mvc:interceptor> </mvc:interceptors>
編寫測試程序測試:
編寫Controller,發請求到controller,跳轉頁面
@Controller public class TargetController { @RequestMapping("/target") public ModelAndView show(){ System.out.println("目標資源執行......"); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("name","itcast"); modelAndView.setViewName("index"); return modelAndView; } }
頁面
<html> <body> <h2>Hello World! ${name}</h2> </body> </html>
攔截器在預處理後什麼狀況下會執行目標資源,什麼狀況下不執行目標資源,以及在有多個攔截器的狀況下攔截器的執行順序是什麼?
再編寫一個攔截器2,
public class MyInterceptor2 implements HandlerInterceptor { //在目標方法執行以前 執行 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException { System.out.println("preHandle22222....."); return true; } //在目標方法執行以後 視圖對象返回以前執行 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { System.out.println("postHandle2222..."); } //在流程都執行完畢後 執行 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("afterCompletion2222...."); } }
配置攔截器2
<!--配置攔截器--> <mvc:interceptors> <mvc:interceptor> <!--對哪些資源執行攔截操做--> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.MyInterceptor2"/> </mvc:interceptor> <mvc:interceptor> <!--對哪些資源執行攔截操做--> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.MyInterceptor1"/> </mvc:interceptor> </mvc:interceptors>
結論:
當攔截器的preHandle方法返回true則會執行目標資源,若是返回false則不執行目標資源
多個攔截器狀況下,配置在前的先執行,配置在後的後執行
攔截器中的方法執行順序是:preHandler-------目標資源----postHandle---- afterCompletion
攔截器中的方法說明以下
在day06-Spring練習案例的基礎之上:用戶沒有登陸的狀況下,不能對後臺菜單進行訪問操做,點擊菜單跳轉到登陸頁面,只有用戶登陸成功後才能進行後臺功能的操做
需求圖:
判斷用戶是否登陸 本質:判斷session中有沒有user,若是沒有登錄則先去登錄,若是已經登錄則直接放行訪問目標資源
先編寫攔截器以下:
public class PrivilegeInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { //邏輯:判斷用戶是否登陸 本質:判斷session中有沒有user HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); if(user==null){ //沒有登陸 response.sendRedirect(request.getContextPath()+"/login.jsp"); return false; } //放行 訪問目標資源 return true; } }
而後配置該攔截器:找到項目案例的spring-mvc.xml,添加以下配置:
<!--配置權限攔截器--> <mvc:interceptors> <mvc:interceptor> <!--配置對哪些資源執行攔截操做--> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.PrivilegeInterceptor"/> </mvc:interceptor> </mvc:interceptors>
在登錄頁面輸入用戶名密碼,點擊登錄,經過用戶名密碼進行查詢,若是登錄成功,則將用戶信息實體存入session,而後跳轉到首頁,若是登錄失敗則繼續回到登錄頁面
在UserController中編寫登錄邏輯
@RequestMapping("/login") public String login(String username,String password,HttpSession session){ User user = userService.login(username,password); if(user!=null){ //登陸成功 將user存儲到session session.setAttribute("user",user); return "redirect:/index.jsp"; } return "redirect:/login.jsp"; }
service層代碼以下:
//service層 public User login(String username, String password) { User user = userDao.findByUsernameAndPassword(username,password); return user; }
dao層代碼以下:
//dao層 public User findByUsernameAndPassword(String username, String password) throws EmptyResultDataAccessException{ User user = jdbcTemplate.queryForObject("select * from sys_user where username=? and password=?", new BeanPropertyRowMapper<User>(User.class), username, password); return user; }
此時仍然登錄不上,由於咱們須要將登錄請求url讓攔截器放行,添加資源排除的配置
<!--配置權限攔截器--> <mvc:interceptors> <mvc:interceptor> <!--配置對哪些資源執行攔截操做--> <mvc:mapping path="/**"/> <!--配置哪些資源排除攔截操做--> <mvc:exclude-mapping path="/user/login"/> <bean class="com.itheima.interceptor.PrivilegeInterceptor"/> </mvc:interceptor> </mvc:interceptors>
JdbcTemplate.queryForObject對象若是查詢不到數據會拋異常,致使程序沒法達到預期效果,如何來解決該問題?
在業務層處理來自dao層的異常,若是出現異常service層返回null,而不是將異常拋給controller
所以改造登錄的業務層代碼,添加異常的控制
public User login(String username, String password) { try { User user = userDao.findByUsernameAndPassword(username,password); return user; }catch (EmptyResultDataAccessException e){ return null; } }
系統中異常包括兩類:預期異常和運行時異常RuntimeException,前者經過捕獲異常從而獲取異常信息,後者主要經過規範代碼開發、測試等手段減小運行時異常的發生。
系統的Dao、Service、Controller出現都經過throws Exception向上拋出,最後由SpringMVC前端控制器交由異常處理器進行異常處理,以下圖:
① 使用Spring MVC提供的簡單異常處理器SimpleMappingExceptionResolver
② 實現Spring的異常處理接口HandlerExceptionResolver 自定義本身的異常處理器
SpringMVC已經定義好了該類型轉換器,在使用時能夠根據項目狀況進行相應異常與視圖的映射配置
<!--配置簡單映射異常處理器--> <bean class=「org.springframework.web.servlet.handler.SimpleMappingExceptionResolver」> <property name=「defaultErrorView」 value=「error」/> 默認錯誤視圖 <property name=「exceptionMappings」> <map> 異常類型 錯誤視圖 <entry key="com.itheima.exception.MyException" value="error"/> <entry key="java.lang.ClassCastException" value="error"/> </map> </property> </bean>
①建立異常處理器類實現HandlerExceptionResolver
public class MyExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { //處理異常的代碼實現 //建立ModelAndView對象 ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("exceptionPage"); return modelAndView; } }
②配置異常處理器
<bean id="exceptionResolver" class="com.itheima.exception.MyExceptionResolver"/>
③編寫異常頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> 這是一個最終異常的顯示頁面 </body> </html>
④測試異常跳轉
@RequestMapping("/quick22") @ResponseBody public void quickMethod22() throws IOException, ParseException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); simpleDateFormat.parse("abcde"); }
異常處理方式
配置簡單異常處理器SimpleMappingExceptionResolver 自定義異常處理器
自定義異常處理步驟
①建立異常處理器類實現HandlerExceptionResolver ②配置異常處理器 ③編寫異常頁面 ④測試異常跳轉