在三次学习已经简单介绍了springmvc工程的搭建,springmvc的三大组件,参数绑定,@Controller返回值,下面介绍springmvc的功能配置,后续添加…
1.异常处理器
使用场景:在程序运行的时候,可能会出现异常,此时直接返回用户异常页面是及其不友好的,做一个全局异常处理器,处理所有没有处理过的运行时异常用于更友好地提示用户。
处理思路:系统中的异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异从而获取异常信息,或者通过测试减少运行时异常的发生。
其中dao,service,Controller都用throws Exception向上抛出,最后有sringmvc前端控制器交由异常处理器去处理。HandlerExceptionResolver(异常处理器)
具体实现:
- 创建全局异常处理器
public class CustomerExceptionResolve implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handle,
Exception e) {
// TODO Auto-generated method stub
//响应用户错误提示
ModelAndView modelAndView = new ModelAndView();
String message="页面错误";
//自定义异常,显示自定义信息
if(e instanceof MyException){
message = ((MyException)e).getMessage();
}
//返回错误消息
modelAndView.addObject("msg", message);
//响应错误提示页面
modelAndView.setViewName("error");
return modelAndView;
}
}
- 配置异常处理器(springmvc.xml)
<!-- 配置全局异常处理器 -->
<bean class="ctgu.utils.CustomerExceptionResolve"/>
- 测试
/**
* 全局异常处理
* 包括自定义异常信息
* @throws MyException
*/
@RequestMapping("/error")
public void MyError() throws MyException{
// int a=1/0;
/**
* 模拟商品查询不到的场景
* 这样的话,错误页面无需定义多个,而直接抛出exception,然后全局异常处理器接收后处理
*/
if(true){
throw new MyException("你查找的商品不存在");
}
}
2.拦截器
应用:springmvc的处理器拦截器类似于servlet中的过滤器Filter,用于处理器进行预处理和后处理
- 就是一个普通的类去继承HandlerInterceptor接口;
- afterCompletion():只要放行了都会执行
- 用于:处理异常,记录日志
- postHandle():在控制器COntroller执行之后,返回ModelAndView视图,之前被执行
- 作用:设置或清理页面共用参数,比如标题栏共用
- preHandle():在执行Controller方法之前时执行
- 作用:登录拦截,用户认证
public class UserIntercepter implements HandlerInterceptor {
/**
* 只要放行了都会执行
* 用于:处理异常,记录日志
*/
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
//System.out.println("afterCompletion执行...");
}
/**
* 在控制器COntroller执行之后,返回ModelAndView视图,之前被执行
* 作用:设置或清理页面共用参数,比如标题栏共用
*/
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
//System.out.println("postHandle执行...");
}
/**
* 在执行Controller方法之前时执行
* 作用:登录拦截,用户认证
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
// TODO Auto-generated method stub
//System.out.println("preHandle执行...");
String name = (String) request.getSession().getAttribute("username");
if(name!=null){
//放行
//当我们输入其他URL的时候,必须判断用户是否完成登录,如果没有,必须返回登录页面
return true;
}else{
response.sendRedirect(request.getContextPath()+"/user/toLogin.action");
return false;
}
}
}
springmvc.xml的配置:
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 配置拦截地址 -->
<mvc:mapping path="/**/"/>
<!-- 配置不拦截地址 -->
<mvc:exclude-mapping path="/user/*"/>
<bean class="ctgu.intercepter.UserIntercepter"/>
</mvc:interceptor>
</mvc:interceptors>
说明:拦截器可以配置多个,即配置多个 mvc:interceptor,但是如果第一个拦截器preHandler没有放行(返回的是false),那其他的两个方法也不会执行,第二个拦截器的所有方法都不会执行,Controller也不执行了。
问:当有两个即两个以上的拦截器存在时,afterCompletion()、postHandle()、preHandle()的执行顺序是如何的?
- preHandle()按照拦截器定义的顺序调用
- postHandle()按照拦截器定义逆序调用
- afterCompletion()按照拦截器定义逆序调用
- postHandle()在拦截器链内所有拦截器返回成功调用
- afterCompletion()只有在preHandle返回true才调用
3.图片上传
- 配置虚拟目录
相当于配置了一个tomcat与本地磁盘的路径映射。
相当于在tomcat的server.xml中添加了一行
<Context docBase=“springmvc03-mybatis” path="/"reloadable=“true” source=“org.eclipse.jst.jee.server:springmvc03-mybatis”/>
-
导jar包
commons-fileupload-1.2.2.jar
commons-io-2.4.jar -
jsp页面
注意method一定要为"post"
enctype=“multipart/form-data”
<form id="itemForm" action="${pageContext.request.contextPath }/updateItem.action" method="post" enctype="multipart/form-data">
<tr>
<td>商品图片</td>
<td>
<c:if test="${item.pic !=null}">
<img src="/pic/${item.pic}" width=100 height=100/><br/>
</c:if>
<input type="file" name="pictureFile"/>
</td>
</tr>
4.springmvc.xml配置
<!-- 配置多媒体处理器 -->
<!-- 注意:这里id必须填写:multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 最大上传文件大小 -->
<property name="maxUploadSize" value="8388608" />
</bean>
- 图片上传处理代码Controller
思路:
- 拿到图片的名字,根据托图片名拿到其后缀名,再拼接一个图片的新的名字
- 将其写入磁盘,把图片的路径+名字(虚拟目录)写入数据库
- 在tomcat建立一个虚拟目录,因为前端页面
<img src="/pic/${item.pic}">
标签显示 - 我们上传上去的图片,需要controller层对其做出处理:
- 1.将其保存在虚拟目录对应的目录,否则前端页面找不到;
- 2.给其一个新的名字(设计到获取其后缀,给一个唯一标识)并赋值给item.pic
说明:相当于将上传的图片保存在tomcat能找的到的目录 (前面映射的虚拟目录),但是我们将其保存的时候给其一个新名字(防止重复),保存在数据库里面的是图片的名字。
@RequestMapping(value="/updateItem.action")
public String updateItem(Model model,MultipartFile pictureFile,Item item) throws Exception{
//生成唯一标识作为图片id,uuid
String name=UUID.randomUUID().toString();
//获取上传图片的名字
String originalFilename = pictureFile.getOriginalFilename();
//得到图片名后缀
String newname = originalFilename.substring(originalFilename.lastIndexOf("."));
//保存在磁盘
File file = new File("C:\\Users\\DELL\\Pictures\\java\\"+name+newname);
pictureFile.transferTo(file);
//把图片名保存到数据库
item.setPic(name+newname);
itemService.update(item);
model.addAttribute("item", item);
model.addAttribute("msg", "修改商品成功");
return "itemEdit";
}