⑤. 文件上传
1>.
文件上传客户端三要素
- ①. 表单项type="file"
- ②. 表单的提交方式是post
- ③. 表单的enctype属性是多部分表单形式,及enctype="multipart/form-data"
<form action="${pageContext.request.contextPath}/user/quick22" method="post" enctype="multipart/form-data"> 名称<input type="text" name="username" multiple="multiple"><br/> 文件1<input type="file" name="uploadFile"><br/> <input type="submit" value="提交"> </form>
解释:
(1).上述代码中,除了满足上传表单所需的3个条件外,在input元素中还添加了一个multiple属性。该属性是HTML5中的新属性,如果使用了该属性,则可以同时选择多个文件进行上传,即可实现多文件上传
(2).当客户端form表单的enctype属性为multipart/form-data时,浏览器就会采用二进制流的方式来处理表单的数据,服务器就会对文件上传的请求进行解析处理
2>.
实现原理
3>.
单文件上传步骤
- ①. 导入fileupload和io坐标
- ②. 配置文件上传解析器
- ③. 编写文件上传代码
<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>
<!--配置文件上传解析器--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--配置默认编码集--> <property name="defaultEncoding" value="UTF-8"/> <!--配置最大文件上传大小(以字节为单位)--> <property name="maxUploadSize" value="500000"/> </bean>
解释:
(1). SpringMvc为文件上传提供了直接的支持,这种支持时通过MutipartResolver(多部件解析器)对象实现的
(2). MultipartResolver是一个接口对象,需要通过它的实现类CommonsMultipartResolver来完成文件上传工作
(3).因为MultipartResolver接口的实现类CommonsMultipartResolver内部引用multipartResolver字符串获取该实现类对象并完成文件解析,所以在配置CommonsMultipartResolver时必须指定改Bean的id为multipartResolver
<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>
@RequestMapping(value="/quick22") @ResponseBody public void save22(String username, MultipartFile uploadFile) throws IOException { System.out.println(username); System.out.println(uploadFile); }
//上传实现升级版 @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 接口方法说明:
(1).String getName( ):获取多部件form表单的参数名称
(2).String getOriginalFilename:获取文件上传的初始化名
(3).boolean isEmpty():判断上传的文件是否为空
(4).void transferTo(File file):将上传文件保存到目标目录中
4>.
多文件上传
- ①. 实现方式1
<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>
- ②. 实现方式2
<form action="${pageContext.request.contextPath}/user/quick23" method="post" enctype="multipart/form-data"> 名称<input type="text" name="username"><br/> 文件<input type="file" name="uploadFile" multiple="multiple"><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)); } }
⑥. SpringMVC的拦截器
1>.拦截器的作用(理解)
- ①. Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理
- ②. 将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现
2>.
Interceptor和filter区别(理解,记忆)
注意:
只会拦截访问的控制器方法,如果访问的是jsp,html,css,image,js是不会进行拦截的
3>.
快速入门(应用)
- ①. 创建拦截器类实现HandlerInterceptor接口
- ②. 配置拦截器
- ③. 测试拦截器的拦截效果
//1.创建拦截器类实现HandlerInterceptor接口 public class MyInterceptor1 implements HandlerInterceptor { //在目标方法执行之前 执行 //用于身份认证、身份授权-- //比如身份证,如果认证通过标识当前用户没有登录,需要此方法不在向下执行 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException { System.out.println("preHandle方法执行了......"); return true; } //在目标方法执行之后 视图对象返回之前执行 //应用场景从modelAndView出发:将公用的模型数据(菜单的导航)在这里传到视图,也可以在这里指定视图 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { System.out.println("postHandle方法执行了......"); } //在流程都执行完毕后 执行 //执行Handler完成执行此方法 //应用场景:统一的异常处理、统一的日志处理 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("afterCompletion方法执行了......."); } }
//2.在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.jsp"); return modelAndView; } }
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <% System.out.println("index.jsp执行了"); %> 你好!${name} </body> </html>
4>.
拦截器详解
- ①.
preHandle( )
:在目标方法执行之前 执行 - ②.
postHandle( )
:在目标方法执行之后 视图对象返回之前执行 - ③.
afterCompletion( )
: 在流程都执行完毕后执行
5>.
配置多个拦截器
<!--配置拦截器--> <mvc:interceptors> <mvc:interceptor> <!--对哪些资源执行拦截操作--> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.AInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> <mvc:interceptors> <mvc:interceptor> <!--对哪些资源执行拦截操作--> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.AInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
6>.
用户登录权限控制
//1. 先编写拦截器如下: 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; } }
//2.然后配置该拦截器:找到项目案例的spring-mvc.xml,添加如下配置: <!--配置权限拦截器--> <mvc:interceptors> <mvc:interceptor> <!--配置对哪些资源执行拦截操作--> <mvc:mapping path="/**"/> <bean class="com.itheima.interceptor.PrivilegeInterceptor"/> </mvc:interceptor> </mvc:interceptors>
//在登陆页面输入用户名密码,点击登陆,通过用户名密码进行查询, 如果登陆成功,则将用户信息实体存入session,然后跳转到首页, 如果登陆失败则继续回到登陆页面 @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层代码如下: public User login(String username, String password) { User user = userDao.findByUsernameAndPassword(username,password); return user; }
//dao层代码如下: public User login(String username, String password) { try { User user = userDao.findByUsernameAndPassword(username,password); return user; }catch (EmptyResultDataAccessException e){ return null; } }
- 此时仍然登陆不上,因为我们需要将登陆请求url让拦截器放行,添加资源排除的配置
<!--配置权限拦截器--> <mvc:interceptors> <mvc:interceptor> <!--配置对哪些资源执行拦截操作--> <mvc:mapping path="/**"/> <!--配置哪些资源排除拦截操作--> <mvc:exclude-mapping path="/user/login"/> <bean class="com.itheima.interceptor.PrivilegeInterceptor"/> </mvc:interceptor> </mvc:interceptors>
7>.
拦截器测试[ 测试多个拦截器各个方法的执行时机 ]
- 环境搭建
1.
两个拦截器都放行
- ①. preHandle方法按顺序执行
- ②. postHandle和afterCompletion 按拦截器配置的逆向顺序
2.
拦截器1放行,拦截器2不放行
- ①. 拦截器1放行,拦截器2preHandler才会执行
- ②. 拦截器2preHandler不放行,拦截器postHandle和afterCompletion不会执行
- ③. 只要有一个拦截器不放行,postHandle就不会执行
3.
拦截器1不放行,拦截器2不放行
- ①. 拦截器1 preHandler不放行,拦截器postHandle和afterCompletion不会执行
- ②. 拦截器1 preHandler不放行,拦截器2就不会执行