14、在结果页面执行完,即将回到浏览器显示结果的时候,调用afterCompletion()方法,进行最后一次拦截。(处理异常,关闭资源,懒加载关闭Session等操作)
配置多个拦截器:
<mvc:interceptors>
<mvc:interceptor>
//指定拦截的请求,如果path=”/*”表示拦截所有请求
<mvc:mapping path=”/login.do”/>
<bean class=”cn.springmvc.myInterceptor1”/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path=”/*”/>
<bean class=”cn.springmvc.myInterceptor2”/>
</mvc:interceptor>
</mvc:interceptors>
执行过程:
请求login.do,到拦截器对象中看看是否拦截这个请求
如果符合多个拦截器请求,拦截顺序是按照配置顺序拦截(依次执行)
preHandle方法的执行:
先调用第一个拦截器的preHandle()方法,发现还有下一个拦截器就继续调用第二个拦截器的preHandle()方法,如果还有下一个拦截器就继续调用下一个拦截器的preHandle()方法,知道直到没有后就将请求下传。
handleRequest的方法的执行:
找到分派器对象,分派器找到对应的后端处理器,执行完handleRequest()方法。
postHandle()方法的执行:
handleRequest()方法执行完后先调用最后一个拦截器的postHandle()方法,依次往前,最后执行第一个拦截器的postHandle()方法。
所有的拦截器的postHandle()方法执行完后, SpringMVC拿到ModelAndView对象做以下这些事情:
根据ModelAndView对象解析出结果数据并且设到request内置对象中,
从该对象中拿到转向信息,到webFactory中拿到视图定位器,加上前缀和后缀,生成完成的转向信息。转向相应的结果页面。
afterCompletion方法的执行:
在结果页面执行完,即将回到浏览器显示结果的时候,先调用最后一个拦截器的afterCompletion()方法,做结果拦截,然后依次往上,最后执行第一个拦截器的afterCompletion()方法。(处理异常,关闭资源,懒加载关闭Session等等操作)
多个拦截器存在时,只要有一个拦截器的preHandle()方法返回的是false,请求不会就传到后端控制器,也不会再继续执行preHandle()以外的方法,直接将请求返回。
SpringMVC的上传SpringMVC的上传和struts1的原理类似,更加智能
1、 必须导入两个包 apache-commons-fileupload.jar
apache-commons-io.jar
2、 在主配置文件中添加 上传控制器 ConmmonMultipartResolver
defaultEncoding value=”gbk” 默认编码
maxInMemorySize value=”1000” 上传文件大小
uploadTempDir value=”/upload/” 上传文件夹,该文件夹不存在就会自动创建
maxUploadSize value=”-1” 指定上传文件的大小,-1表示不限制上传文件的大小
指定的上传文件夹是在创建上传控制器对象的时候的创建,tomcat一启动就创建了,由上传控制器创建。
SpringMVC的主配置文件的配置:
<!-- 配置启用springmvc的注解 -->
<context:annotation-config/>
<!-- 配置注解扫描的包 -->
<context:component-scan base-package="cn.springmvc"></context:component-scan>
<!-- 配置视图解析器 -->
<bean id="viewResolver" class=" org.springframework. web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
文件上传的配置:
<!-- 文件上传的配置信息 -->
<bean id="multipartResolver" class="org.springframework.
web.multipart.commons.CommonsMultipartResolver" >
<!-- 默认编码 (ISO-8859-1) -->
<property name="defaultEncoding" value="gbk"/>
<!-- 最大内存大小 (10240)-->
<property name="maxInMemorySize" value="10240"/>
<!-- 上传后的目录名 -->
<property name="uploadTempDir" value="/upload/"/>
<property name="maxUploadSize" value="-1"/> <!-- 最大文件大小,-1为无限止(-1) -->
</bean>
上传文件的表单:
请求方式为post, enctype=”multipart/form-data”,上传文件为file类型
<form action="upload.do" method="post" enctype="multipart/form-data">
上传文件:<input type="file" name="myFile"/><br><br>
<input type="submit" value="上传"/>
</form>
文件上传的类:
@Controller
public class UploadController implements ServletContextAware{
//注入application内置对象,用来拿到上传的文件存储的路径
private ServletContext servletContext;
public void setServletContext(ServletContext servletContext) {
this.servletContext=servletContext;
}
@RequestMapping("/upload.do")
public String upload(@RequestParam("myFile") CommonsMultipartFile file,HttpServletRequest request){
//拿到上传的文件存储的路径
String path=this.servletContext.getRealPath("/upload/");
//拿到上传文件的文件名
String fileName=file.getOriginalFilename();
request.setAttribute("filename",fileName);
//创建新的文件夹并且指定文件路径和文件名
File file1=new File(path,fileName);
try{
byte[] b=file.getBytes();//将需要上传的文件存到字节数组对象
//创建文件输出流对象
FileOutputStream fos=new FileOutputStream(file1);
fos.write(b);//将字节数组对象中的数据写入缓存中
fos.flush();//将缓存中数据写入文件
fos.close();//关闭文件输出流
}catch(Exception e){
throw new RuntimeException("文件上传错误");
}
return "upload";
}
}
上传流程: ----注解方式
1、Tomcat一启动,创建DispatcherServlet对象
2、执行init()方法,创建web工厂,
3、在web工厂中会创建以下几个对象
创建视图定位器对象
创建上传处理器对象,先看有没有上传文件目录,没有的话就在项目的根下创建目录。
创建分派器对象(映射器),到指定包下扫描后端处理器(@Controller标识的类)创建该类对象。
一创建后端处理器对象就把application内置对象注入。
@Controller
public class FileUploadController implements ServletContextAware{
private ServletContext servletContext;//注入appllication对象
public void setServletContext(ServletContext context) {
this.servletContext = context;
}
}
4、发送请求:/login.do,交给tomcat处理
5、tomcat创建request内置对象接收请求
6、将请求交给DispatcherServlet 处理,截取请求
7、到web工厂中找到分派器
8、分派器找到请求对应的后端控制器
9、传递参数:第一个参数String name,直接传递
第二个参数 表单中参数是file类型(传入的是字节数组对象)参数名myFile,方法中CommonsMultipartFile file, 形参的名为 file,类型为 CommonsMultipartFile.
自动创建CommonsMultipartFile类型的对象来封装表单中传过来的字节数组文件。
上传方法:
@RequestMapping(value="/upload.do")
public String handleUploadData(String name, @RequestParam("myFile") CommonsMultipartFile file){
上传处理:
String path=this.getServletContext().getRealPath(“/upload/”);//通过application找到上传文件夹的绝对路径
String fileName=file.getOringinalName();//得到原来的文件名
String fileType=fileName.substring(fileName.lastIndexOf(.)+1);//使用substring()截取得到上传文件的后缀名
下载处理:
File file1 = new File(path,fileName); //新建一个文件
byte[] b=file.getBytes();//将上传的文件存入字节数组对象中
FileOutputStream fos = new FileOutputStream(file1);//创建文件字节输出流对象
fos.write(b);//将文件写入文件字节输出流对象所指的文件中
fos.flush();
fos.close();
return “redirect:upload_ok.jsp”;//重定向,不需要视图定位器。
SpringMVC的异常处理
主要的类:SimpleMappingExceptionResolver
接口:AbstractHandlerExceptionResolver
Exception异常对象的数据结构:
有个私有属性private String message,
只能通过有参的构造方法设值,只提供了公有的getMessage(),
e.getMessage();显示异常信息
e.toString():显示异常类型和异常信息
e.pringStackTrace():调用toString(),显示出异常的类,方法。
SpringMVC的异常类:
异常类的定义:继承RutimeException,复写有参的构造方法
public class UserException extends RuntimeException {
public UserException(String msg){
super(msg);
}
}
SpringMVC的主配置文件: springmvc-servlet.xml
<!-- 配置启用springmvc的注解 -->
<context:annotation-config/>
<!-- 配置注解扫描的包 -->
<context:component-scan base-package="cn.springmvc"/>
<!-- 配置视图解析器 -->
<bean id="viewResolver" class=" org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
异常信息的配置:
<!-- 配置异常处理信息 -->
<bean id="exceptionResolver"class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="cn.springmvc.exception.UserException">
UserExceptionPage</prop>
</props>
<!-- 配置默认异常处理转向 -->
</property>
<property name="defaultErrorView">
<value>error</value>
</property>
</bean>
在主配置文件中引入异常处理类SimpleMappingExceptionReslover
key:是异常类型(自定义异常类路径名)
value:异常转向页面,通过视图解析器自动加上前缀和后缀,然后完成跳转。(相当于 struts1的input属性)
配置在exceptionMappings外的异常处理信息,表示找不到指定的key时,会调用这个默认的key(defaultErrorView)所指定的转向页面value完成转向。
异常抛出类(业务类直接抛出异常,后端控制器类也直接抛出异常,最后交给SpingMVC处理的中央处理器处DispatcherServlet):
public class UserImpl implements UserManager{
public String login(User user) {
if("DFX".equals(user.getUsername())){
return "main";
}
//通过有参的构造方法抛出异常,参数为异常信息值,存到message属性中
throw new UserException("用户名不对啊"+user.getUsername());
}
}
所有从jsp页面中取出的时候用 ${exception.message}
异常处理流程:
1、Tomcat一启动,创建DispatcherServlet对象
2、执行init()方法,创建web工厂,
3、在web工厂中会创建以下几个对象
创建分派器对象
创建后端处理器对象
创建视图定位器对象
创建异常处理器对象
4、发送请求:/login.do,交给tomcat处理
5、tomcat创建request内置对象接收请求
6、将请求交给DispatcherServlet 处理,截取请求
7、到web工厂中找到分派器
8、分派器到mappings的prop中找到id对应的后端控制器
9、执行后端控制器的handlerRequest()方法
10、在方法中调用业务层方法做验证,不合法就抛出异常
在业务层:throw new UserNotFoundException(username);
11、后端控制器也不处理异常,继续抛出异常
12、最后把异常交给DispatcherServlet处理
异常处理DispatcherServlet:
1、拿到异常对象,设到request内置对象中,属性名为exception
2、通过getClass().getName()拿到异常对象的类型,到web工厂中找异常处理器对象,从异常处理器中找到和异常类型相对应的异常value(异常转向页面)。
3、异常转向找到视图定位器加上前缀和后缀,转到相应的jsp页面。
4、在异常转向jsp页面中:${exception.message}
Throw new Exception(“haha”+password);//抛出异常信息
拿到异常对象,设到request内置对象中,属性名为exception,属性值为异常值(message)
拿到异常对象的类型,到web工厂中找异常处理器,从异常处理器中的prop找到和异常类型相对的异常value(异常转向页面)。发现没有
就找到异常处理器默认的配置异常页面,直接到property配置中 name=”defaultErrorView”找到value(异常转向)
异常转向找到视图定位器加上前缀和后缀,转到相应的jsp页面。
在异常转向jsp页面中:${exception.message}
银行项目和物料项目使用springmvc+spring+hibernate继承
基于注解Spring3实现:
1、 建立web项目
2、 导入Spring3的jar包和hiberante的jar 包