SpringMVC补充文件上传下载,异常与拦截

1 文件上传

1.1 jsp

  • post提交
  • file文件域
  • enctype=mutipart/form-data
<form  action="<c:url value='/test01/upload.action'/>" method="post"  enctype="multipart/form-data">
    <table>
        <tr>
            <th>name:</th>
            <td><input type="text" name="name"/></td>
        </tr>
        <tr>
            <th>sex:</th>
            <td><input type="text" name="sex"/></td>
        </tr>
        <tr>
            <th>file:</th>
            <td><input type="file" name="photo_file"/></td>
        </tr>
        <tr>
            <th>age:</th>
            <td><input type="text" name="age"/></td>
        </tr>
        <tr>
            <th colspan="2">
                <input  type="submit" value="文件上传"/>
            </th>
        </tr>
    </table>
</form>

1.2 action

  • MultiPartFile来接受文件域组件

  • 对象的属性名一定不要和文件域的name相同

@Controller
@RequestMapping("/test01")
public class Test01 {
	  @RequestMapping("/upload.action")
	  public String uplaodMethod(Student stu,@RequestParam("photo_file") MultipartFile  file)throws Exception{
		  //System.out.println("getOriginalFilename="+file.getOriginalFilename());//文件名字
		  //System.out.println("getName="+file.getName());//组件名字
		  //System.out.println("getSize="+file.getSize());//文件大小
		  //System.out.println("getContentType="+file.getContentType());//文件类型
		  //System.out.println("getInputStream="+file.getInputStream());//获取文件的输入流
		  //System.out.println("getBytes="+file.getBytes());//获取文件的字节
		  //System.out.println("transferTo="+file.transferTo(File);); //文件复制
		  //获取文件名字
		  String fileName=file.getOriginalFilename();
		  //创建目的文件
		  File fileMuDi=new File("e:/imgs_uplaod",System.currentTimeMillis()+"_"+fileName);
		  System.out.println(fileMuDi.getAbsolutePath());
		  //实现文件的复制
		  file.transferTo(fileMuDi);
		  stu.setPhoto(fileMuDi.getName());
		  return "test01_sucess";
	  }
}

2 文件下载

2.1 在web.xml中指定文件下载的源文件夹

<!-- 定义项目初始化参数  指定文件下载的目录 -->
<context-param>
    <param-name>download_path</param-name>
    <param-value>/imgs</param-value>
</context-param>

2.2 jsp提供超链接 指定文件名即可

<h1>文件下载</h1>
<a   href="<c:url value='/test02/download.action?fileName=11.jpg'/>">下载11.jpg</a><br/>
<a   href="<c:url value='/test02/download.action?fileName=12.jpg'/>">下载12.jpg</a><br/>
<a   href="<c:url value='/test02/download.action?fileName=13.jpg'/>">下载13.jpg</a><br/>
<a   href="<c:url value='/test02/download.action?fileName=14.jpg'/>">下载14.jpg</a><br/>
<a   href="<c:url value='/test02/download.action?fileName=换行.jpg'/>">下载换行.jpg</a><br/>

2.3 action

  • 设置响应头 指定响应内容的类型
  • 设置响应头 指定客户端以附件形式保存
  • 返回值类型是ResponseEntity<byte[]>
@Controller
@RequestMapping("/test02")
public class Test02 {
    @RequestMapping("/download.action")
    public ResponseEntity<byte[]> downloadMethod(String fileName,HttpServletRequest req)throws Exception{
        //获取文件的类型
        String type=req.getServletContext().getMimeType(fileName);
        //获取web.xml中配置的初始化参数:download_path
        String path=req.getServletContext().getInitParameter("download_path");// /imgs
        //获取真实路径
        String realPath=req.getServletContext().getRealPath(path);
        File yuanFile=new File(realPath,fileName);

        //		  byte[] arr=new byte[(int)yuanFile.length()];
        //		  FileInputStream fin=new FileInputStream(yuanFile);
        //		  fin.read(arr);
        //		  fin.close();
        byte[] arr=FileUtils.readFileToByteArray(yuanFile);

        //创建heander对象  响应头
        HttpHeaders headers=new HttpHeaders();
        headers.set("Content-Type", type);
        headers.set("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "utf-8"));

        //获取源文件
        //context.get
        ResponseEntity<byte[]>  entity=new ResponseEntity<byte[]>(arr,headers,HttpStatus.OK);
        return entity;
    }
}

3 异常处理

3.1 自定义异常

public class UserLoginException extends RuntimeException{
    public UserLoginException(String message){
    	super(message);
    }
}
public class UserNameException extends RuntimeException{
    public UserNameException(String message){
    	super(message);
    }
}
public class UserPwdException extends RuntimeException{
    public UserPwdException(String message){
    	super(message);
    }
}

3.2 定义处理异常的通知类

  • 实现接口HandlerExceptionResolver
  • 添加注解@Component
  • 在resolveException方法中对不同异常进行选择处理
@Component
public class MyExceptionAdvice   implements HandlerExceptionResolver{

	@Override
	public ModelAndView resolveException(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,
			Exception e) {
		ModelAndView mv=new ModelAndView();
		mv.addObject("message", e.getMessage());
		mv.addObject("exception2", e);
		mv.setViewName("test03_error");
		if(e instanceof UserLoginException){
			mv.addObject("status","5001");
		}
		if(e instanceof UserNameException){
			mv.addObject("status","4001");
		}
		if(e instanceof UserPwdException){
			mv.addObject("status","4002");
		}
		return mv;
	}
}

3.3 创建抛出异常的action和service

  • service
@Service
public class Test21Service {
    public boolean login(String name,String pwd){
    	 if(name.length()>4){
			 throw new UserNameException("用户名长度错误!");
		 }else  if(!pwd.equals("123456")){
			 throw new UserPwdException("用户密码错误!");
		 }
    	 return true;
    }
}
  • action
@Controller
@RequestMapping("/test21")
public class Test21 {
	  @Autowired
	  private Test21Service test21Service;
	  @RequestMapping("/login.action")
	  public String loginMethhod(String name,String pwd,Model m){
		 boolean b=test21Service.login(name, pwd);
		 if(!name.matches("^[\u4e00-\u9fa5]{2,4}$")){
			 throw new UserLoginException("用户名必须是2到4个汉字");
		 }
		 m.addAttribute("name", name);
		 m.addAttribute("pwd", pwd);
		 return "test03_success";
	  }
}

3.4 请求页面 和 错误页面

  • test03.jsp
<h1>异常处理:登录表单</h1>
<form  action="<c:url value='/test21/login.action'/>" method="post">
    <table>
        <tr>
            <th>name:</th>
            <td><input type="text" name="name"/></td>
        </tr>
        <tr>
            <th>pwd:</th>
            <td><input type="text" name="pwd"/></td>
        </tr>
        <tr>
            <th colspan="2">
                <input  type="submit" value="用户登录"/>
            </th>
        </tr>
    </table>
</form>
  • test03_error.jsp
exception=${exception}<br/>
exception2=${exception2}<br/>
message=${message }<br/>
status=${status }<br/>

3.5 spring3.2以后处理异常

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(UserLoginException.class)
    public String handleException(Exception e){
        ...
        return "test03_error";
    }
    @ExceptionHandler(UserNameException.class)
    public String handleException(Exception e){
        ...
        return "test03_error";
    }
}

4 拦截器Interceptor

4.1 概念

 * 拦截器:interceptor
 *   springmvc中定义的类似于filter的组件  用于对指定的action进行拦截 拦截后可以选择放行
 *   而且在action之前和之后添加代码
 *   作用:异常处理 权限控制  日志管理 资源释放 等..

4.2 案例

  • 创建action
@Controller
@RequestMapping("/test31")
public class Test31 {
	
	@RequestMapping("/m1.action")
	public String method01(int age,String name,Model m){
		System.out.println(age+":"+name);
		m.addAttribute("name", name);
		m.addAttribute("age", age);
		m.addAttribute("message", "method01");
		return "test04";
	}
	@RequestMapping("/m2.action")
	public String method02(int age,String name,Model m){
		System.out.println(age+":"+name);
		m.addAttribute("name", name);
		m.addAttribute("age", age);
		m.addAttribute("message", "method0122222");
		return "test04";
	}
}
  • 创建jsp
<h1>拦截器</h1>
<c:if test="${not empty message}">
    message=${message}<br/>
</c:if>
<c:if test="${not empty age}">
    age=${age}<br/>
</c:if>
<c:if test="${not empty name}">
    name=${name}<br/>
</c:if>
<a  href="<c:url value='/test31/m1.action?age=111&name=韩梅梅1'/>">请求/test31/m1.action</a><br/>
<a  href="<c:url value='/test31/m2.action?age=112&name=韩梅梅2'/>">请求/test31/m2.action</a><br/>
<a  href="<c:url value='/test31/m3.action?age=113&name=韩梅梅3'/>">请求/test31/m3.action</a><br/>
  • 创建拦截器:实现接口HandlerInceptor
public class Test31Interceptor01   implements HandlerInterceptor{

	//afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("afterCompletion====");
	}

	//postHandle:该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("postHandle===age="+arg3.getModel().get("age"));
		System.out.println("postHandle===name="+arg3.getModel().get("name"));
		arg3.addObject("age", (Integer)arg3.getModel().get("age")+1);
	}

	// preHandle:进行预处理的代码:在action执行之前执行的代码::权限控制。。请求参数转换验证。。
	// 返回true 放行  返回false 不放行
	public boolean preHandle(HttpServletRequest req, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("preHandle===arg2="+arg2.getClass());//arg2参数是当前action方法对象
		System.out.println("preHandle===请求的url="+req.getServletPath());
		return true;
	}
}
  • 在核心配置文件中通过mvc标签配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/test31/*"/>
        <!--  <mvc:exclude-mapping path="/test31/m1.action"/>指定不拦截的action:此标签适用于4.+以上的版本-->
        <bean class="com.zhiyou100.test03_interceptor.Test31Interceptor01"/>
    </mvc:interceptor>
</mvc:interceptors>
  • 验证 略

4.3 拦截器和过滤器的区别

  • 概念
拦截器interceptor:springmvc中对指定action进行拦截 选择放行 并且在action执行前后可以加代码的组件
过滤器filter:javaweb三大组件之一 由web容器创建、维护和销毁的组件 可以对web资源进行拦截 选择放行 并且在资源处理请求之前和之后添加代码
  • 相同之处
都可以拦截对action请求
都可以在请求前后添加代码
功能基本一致
  • 不同之处
1 实现接口不同
    过滤器实现接口:javax.servlet.Filter
    拦截器实现接口:org.springframework.web.servlet.HandlerInterceptor
2 是否依赖web容器
    filter依赖web容器  需要tomcat创建、调用和销毁:只适用于web项目
    interceptor不依赖web容器 适用于所有项目  只需要导入拦截器依赖的jar即可
3  拦截的资源不同
     filter可以拦截所有资源:html action css servlet img
     interceptor只能拦截action
4  原理不同
     filter原理是方法回调
     interceptor原理是反射和动态代理
posted @ 2021-11-11 22:18  RenVei  阅读(87)  评论(0编辑  收藏  举报