SpringMVC笔记二

版权声明:本文为博主原创文章,未经博主允许不得转载。 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接口,自定义全局异常处理器必须要实现这个接口。

 全局异常处理器处理思路:

  1. 解析出异常类型
  2. 如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示
  3. 如果该异常类型不是系统自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)

    

自定义异常类:

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>

猜你喜欢

转载自blog.csdn.net/Sugar_map/article/details/80602365