版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Sugar_map/article/details/80602365
本文核心内容:基于SpringMVC的文件上传与下载、SpringMVC实现验证码、拦截器、全局异常处理
一:文件上传(基于SpringMVC)
前置:导入相关包(第三方文件操作、I/O包),SpringMVC相关Jar包
1:JSP页面
<form method="post" action="${pageContext.request.contextPath}/file/fileUpLoad.do" enctype="multipart/form-data">
请选择文件:<input type="file" name="myFile" /><br/>
<input type="submit" value=">>>上传"/>
</form>
2:Controller
@Controller
@RequestMapping("/file")
public class FileUpLoadDownController {
@RequestMapping("/fileUpLoad")
//MultipartFile形参名与JSP页面 <input file/>的name属性一致 myFile
public String fileUpLoad(MultipartFile myFile,HttpSession session) throws Exception{
//1.获取文件夹的名称
String realPath=session.getServletContext().getRealPath("/Files");
//2.获取保存文件的文件名 ->UUID无 '-'
String fileName= UUID.randomUUID().toString().replace("-","");
//3.①获取上传文件的原文件名②截取后缀名
String oldName=myFile.getOriginalFilename();
String suffix=oldName.substring(oldName.lastIndexOf("."));
//4.保存上传文件 使用流保存到本地磁盘中
myFile.transferTo(new File(realPath+"/Files"+fileName+suffix));
System.out.println(realPath+fileName+suffix);
return "redirect:/success.jsp";
}
}
3:文件解析器
配置spring-mvc.xml文件
<!--固定ID值-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--配置文件上传的配置入最大上传文件大小等-->
<property name="maxUploadSize" value="102400000"/>
</bean>
总结:Java Web上传文件的核心步骤
①:客户端上传文件、发送请求到Servlet或者(控制器)
②:服务器端:以I/O流的形式将上传的文件写到服务器的文件夹中
优化思路:
使用第三方流读写文件,避免手写I/O流,简化操作。
文件夹路径动态获取。
文件名应该随意生成,以免文件名相同造成覆盖。
二:文件下载
①:写个Controller获取文件夹下的所有文件
@RequestMapping("/getFileNames")
public String getAllFileName(Model model)throws Exception{
File file=new File("D:\\Program\\IDEA\\SSM_Project\\out\\artifacts\\SSM_Project_war_exploded\\Files");
String[] fileNames=file.list();
model.addAttribute("fileName",fileNames);
return "fileDownLoad";
}
②:下载文件
@RequestMapping("/fileDownLoad")
public void fileDownLoad(HttpServletResponse response, String fileName)throws Exception{
//通过第三方工具文件从本地写入字节数组
byte[] bytes= FileUtils.readFileToByteArray(new File("D:\\Program\\IDEA\\SSM_Project\\out\\artifacts\\SSM_Project_war_exploded\\Files"+"\\"+fileName));
//设置输出的头,并指定文件名的编码形式【防止中文文件名乱码】
response.setHeader("content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
//以流的形式输出文件到客户端
response.getOutputStream().write(bytes);
}
三:验证码
JSP页面
<img src="${pageContext.request.contextPath}/comment/getImage.do" id="code" />
Controller
@Controller
@RequestMapping("/comment")
@SessionAttributes(value = {"code"})
public class CommentController {
@RequestMapping("/getImage")
public void getImage(Model model, HttpServletResponse response)throws Exception{
CreateValidateCode validateCode=new CreateValidateCode(100,30,4,10);
//获取验证码 并存入Session作用域中
String code=validateCode.getCode();
model.addAttribute("code",code);
//将图片以流的形式 响应到客户端
validateCode.write(response.getOutputStream());
}
}
验证码应该以流的形式,输出响应到客户端, Controller方法的返回值类型 void。
补充:若想实现验证码刷新 【为验证码添加单击事件】
<script type="text/javascript">
$(function () {
$("#code").click(function () {
//更新验证码的请求路径就可以了,为了避免浏览器缓存问题 请求路径参数加个时间戳
$("#code").attr("src","http://localhost:8088/practic/comment/getImage.do?time"+new Date().getTime());
});
});
</script>
四:拦截器
自定义拦截器需要实现HandlerInterceptor接口 ->配置spring-mvc.xml文件:
/**
* Created by Maps on 2018/6/23.
*/
public class MyInterceptor implements HandlerInterceptor{
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("拦截请求。");
return true;//返回true允许继续调用
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("拦截响应。");
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
Exception e) throws Exception {
System.out.println("异常处理。");
}
}
实战:用户权限验证
/**
* Created by Maps on 2018/6/23.
*/
public class CheckInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String uri=httpServletRequest.getRequestURI();//获取URI
if(uri.contains("single.do")||uri.contains("add.do")){
System.out.println("我是第二个拦截器");
return true;//登录和注册,让请求继续
}else{
HttpSession session=httpServletRequest.getSession();
User user=(User)session.getAttribute("user");
if(user!=null){
//用户已经登录,让请求继续
return true;
}
else{
//用户未登录,重定向到登录页面
httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/login.jsp");
}
}
return false;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("我拦截响应");
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("我异常处理");
}
}
配置xml文件:
<!--配置拦截器-->
<mvc:interceptors>
<!--第一个拦截器-->
<mvc:interceptor>
<mvc:mapping path="/user/*.do"/>
<bean class="com.ssm.project.interceptor.MyInterceptor"/>
<!-- <bean class="com.ssm.project.interceptor.CheckInterceptor"/>-->
</mvc:interceptor>
<!--第二个拦截器-->
<mvc:interceptor>
<mvc:mapping path="/user/*.do"/>
<bean class="com.ssm.project.interceptor.CheckInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
那么多个拦截器的执行顺序? log日志如下:
拦截请求。
我是第二个拦截器
DEBUG 2018-06-23 12:03:09,029 org.springframework.web.cors.DefaultCorsProcessor: Skip CORS processing: request is from same origin
DEBUG 2018-06-23 12:03:09,066 org.springframework.beans.factory.support.AbstractBeanFactory: Returning cached instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'
DEBUG 2018-06-23 12:03:09,072 org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource: Adding transactional method 'com.ssm.project.service.impl.UserServiceImpl.getSingleUser' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
DEBUG 2018-06-23 12:03:09,078 org.springframework.beans.factory.support.AbstractBeanFactory: Returning cached instance of singleton bean 'transactionManager'
DEBUG 2018-06-23 12:03:09,090 org.springframework.transaction.support.AbstractPlatformTransactionManager: Creating new transaction with name [com.ssm.project.service.impl.UserServiceImpl.getSingleUser]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
DEBUG 2018-06-23 12:03:09,115 org.springframework.jdbc.datasource.DataSourceTransactionManager: Acquired Connection [jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC, UserName=root@localhost, MySQL Connector/J] for JDBC transaction
DEBUG 2018-06-23 12:03:09,124 org.springframework.jdbc.datasource.DataSourceUtils: Setting JDBC Connection [jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC, UserName=root@localhost, MySQL Connector/J] read-only
DEBUG 2018-06-23 12:03:09,126 org.springframework.jdbc.datasource.DataSourceTransactionManager: Switching JDBC Connection [jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC, UserName=root@localhost, MySQL Connector/J] to manual commit
DEBUG 2018-06-23 12:03:09,135 org.mybatis.spring.SqlSessionUtils: Creating a new SqlSession
DEBUG 2018-06-23 12:03:09,142 org.mybatis.spring.SqlSessionUtils: Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cdb4f2f]
DEBUG 2018-06-23 12:03:09,195 org.mybatis.spring.transaction.SpringManagedTransaction: JDBC Connection [jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC, UserName=root@localhost, MySQL Connector/J] will be managed by Spring
DEBUG 2018-06-23 12:03:09,201 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ooo Using Connection [jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC, UserName=root@localhost, MySQL Connector/J]
DEBUG 2018-06-23 12:03:09,205 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Preparing: select * from t_user where email=? and pwd=?
DEBUG 2018-06-23 12:03:09,244 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Parameters: [email protected](String), 123(String)
DEBUG 2018-06-23 12:03:09,270 org.mybatis.spring.SqlSessionUtils: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cdb4f2f]
DEBUG 2018-06-23 12:03:09,270 org.springframework.transaction.support.AbstractPlatformTransactionManager: Initiating transaction commit
DEBUG 2018-06-23 12:03:09,271 org.springframework.jdbc.datasource.DataSourceTransactionManager: Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC, UserName=root@localhost, MySQL Connector/J]
DEBUG 2018-06-23 12:03:09,272 org.mybatis.spring.SqlSessionUtils$SqlSessionSynchronization: Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cdb4f2f]
DEBUG 2018-06-23 12:03:09,273 org.mybatis.spring.SqlSessionUtils$SqlSessionSynchronization: Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cdb4f2f]
DEBUG 2018-06-23 12:03:09,276 org.springframework.jdbc.datasource.DataSourceUtils: Resetting read-only flag of JDBC Connection [jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC, UserName=root@localhost, MySQL Connector/J]
DEBUG 2018-06-23 12:03:09,277 org.springframework.jdbc.datasource.DataSourceTransactionManager: Releasing JDBC Connection [jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC, UserName=root@localhost, MySQL Connector/J] after transaction
DEBUG 2018-06-23 12:03:09,277 org.springframework.jdbc.datasource.DataSourceUtils: Returning JDBC Connection to DataSource
我拦截响应
拦截响应。
DEBUG 2018-06-23 12:03:09,278 org.springframework.web.servlet.DispatcherServlet: Null ModelAndView returned to DispatcherServlet with name 'springMVC': assuming HandlerAdapter completed request handling
我异常处理
异常处理。
分析结果:拦截器的前置方法按照拦截器的配置顺序去执行,拦截器的后置方法和完成方法(异常处理)是按照配置逆序运行的。
五:全局异常处理
springmvc提供一个HandlerExceptionResolver接口,自定义全局异常处理器必须要实现这个接口。
全局异常处理器处理思路:
- 解析出异常类型
- 如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示
- 如果该异常类型不是系统自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
自定义异常类:
public class SystemException extends Exception {
private String message;
public SystemException(String message, String message1) {
super(message);
this.message = message1;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
全局异常处理
@Component
public class GlobleException implements HandlerExceptionResolver {
/*
* @Param: Obeject ->发生异常的方法 ;Exception ->捕获异常的异常
* @Return:
* @Author: Maps
* @Date: 2018/7/15 18:57
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
String message="";
ModelAndView modelAndView=new ModelAndView();
if(ex instanceof SystemException){
message="系统错误,请联系管理员!";
}else {
message=ex.getMessage();
}
modelAndView.addObject("message",message);
modelAndView.setViewName("error");
return modelAndView;
}
}
注册到Spring-mvc.xml的配置文件中
<bean class="com.baizhi.exception.GlobleException"></bean>