SpringMVC是Spring框架的一个模块,是一个基于MVC的web框架。
流程:
1,向服务器发送的http request请求被DispatcherServerlet捕获。
2,DispatcherServerlet根据xml文件中的配置或注解对请求的URL进行解析,得到uri(请求资源标识符)。然后根据uri调用HandlerMapping,获得处理该请求的Handler和Handler对应的拦截器,最后以HandlerExecutionChain对象的形式返回。
3,DispatcherServerlet根据获得的Handler选择一个合适的HandlerAdapter去执行该Handler。
4,HandlerAdapter提取request中的模型数据,填充Handler入参,执行Handler(也称为Controller)。
5,Handler(Controller)执行完后,向HandlerAdapter返回一个ModelAndView对象,HandlerAdapter再向DispatcherServerlet返回一个ModelAndView对象。
6,根据返回的ModelAndView,DispatcherServerlet请求一个合适的ViewResolver(必须已经注册到Spring容器中)去进行视图解析,然后ViewResolver向DispatcherServerlet返回一个真正的视图View(jsp)。
7,DispatcherServerlet通过Model解析出ModelAndView中的参数进行解析,最终展现完整的view并通过Http response返回给客户端。
整个过程我们只需编码Handler和jsp,在WEB-INF/web.xm中配置DispatcherServerlet
前台post提交乱码问题如何解决:
可以在web.xml中配置过滤器解决
SpringMVC拦截器
定义拦截器要实现HandlerInterceptor接口,并实现其三个方法:
boolean preHandle:返回值为false表示拦截,true表示放行,在进入Handler方法前执行,可用于身份认证等
void postHandle:执行于进入Handler方法之后和返回ModelAndView之前。其形参中包含ModelAndView,可以用其返回公用的模型数据(公用导航菜单栏)给视图,或者指定统一的返回视图
void afterCompletion:在Handler方法执行完后执行,可用于统一日记管理,统一异常处理等。
拦截器是根据具体映射器进行配置的,它配置于某个映射器中,也就是说经由某个HandlerMaping映射成功的Handler可以使用该拦截器。
拦截器的执行规律(假如配置三个):
1,三个拦截器同时放行的情况下,preHandle方法的执行顺序是:1,2,3。postHandel和afterCompletion方法的执行顺序是3,2,1。
2,不过只要三个拦截器中有一个进行拦截,那么其后面的拦截器的preHandle方法不会执行,而且三个拦截器的postHandle都不会执行,三个拦截器中执行过preHandle并且返回true的会执行afterCompletion方法。
SpringMVC参数绑定
1,默认参数绑定
可以在controller的形参上直接定义以下默认类型的参数,SpringMVC就会自动绑定。
HttpServletRequest
HttpServletResponse
HttpSession
Model/ModelMap对象:model是个接口ModelMap是个接口实现类,作用和ModelAndView类似,是将Model数据填充到request域。
2,简单参数绑定
参数名得和前台传入的值名称一样,如若不同得加上@RequestParam
3,POJO类型参数绑定
需要前台input标签的name属性值和POJO中参数名称一致。若需要传入date类型的值,则需要转换。
转换可以是在前台用date类型的input,然后在POJO中加上注解@DateTimeFormat(pattern = "yyyy-MM-dd")
注意此种转换后,存入数据库的不是yyyy-MM-dd形式,在前台展示的时候需要controller转换下传入前端。
还可以定义一个转换器类,继承Converter接口,在实现的convert方法里将传入的String类型参数用SimpleDadteFormat转换为date类型。做好后,在servlet配置文件中,开启转换器和适配器的那行代码中加入转换器声明,然后加入转换器的bean就可以。
如何绑定包装的POJO类型(POJO里有另一个POJO):
1,用HttpserverletRequest接收(原始而通用)
2,直接让包装类型的POJO接收
重点说第二种:很简单,直接在前台将input的name值,设置为另一个POJO的参数名.参数名即可。
4,集合类型的绑定
1)数组的绑定:例如前台同时传入一连串的ID让后台批量删除
前台:
Controller
2)list的绑定:例如前台同时传入一连串的商品信息提交修改
封装的POJO类,里定义一个list属性。前台jsp中对每个item的命名方式是包装类中的list属性名+下标+对应list中的POJO属性名,然后controller中直接让POJO接收即可
3)Map的绑定
Public classQueryVo {
private Map
//get/set方法..
}
<tr>
<td>学生信息:td>
<td>
姓名:<inputtype="text"name="itemInfo['name']"/>
年龄:<inputtype="text"name="itemInfo['price']"/>
.. .. ..
td>
tr>
SpringMVC异常处理:
思路:dao、service、controller层一层层将异常抛出,最终由前端控制器交给全局异常处理器处理。
springMVC中自带的简单异常处理器
SimpleMappingExceptionResolver:实现了HandlerExceptionResolver接口。需要在SpringMVC.xml文件中配置该处理器。
自定义全局异常处理器:
处理思路:
1,继承HandlerexceptionResolver接口,解析出异常类型。
2,如果该异常类型是系统自定义的异常,直接取出异常信息,在错误界面显示。
3,如果该异常类型不是系统自定义的异常,构造出一个自定义的异常类型(信息为“未知错误”)
4,在SpringMVC.xml中配置。
@ExceptionHandler注解实现异常处理
首先写个baseController类,并在类中使用@ExceptionHandler注解声明异常处理的方法
public class BaseController {
@ExceptionHandler
public String exp(HttpServletRequest request, Exception ex) {
//异常处理
//......
}
}
然后所有需要处理异常的controller都继承这个类,不需要配置什么东西,但是代码有侵入性。
SpringMVC和前台的json交互
SpringMVC和前台主要有两种交互形式
一种是key/value一种是json
首先准备加载json所需要的jar包,SpringMVC3和SpringMVC4有所差别
SpringMVC4是:
我项目中用的是gson和fastjson
第二件事是配置json转换器如果使用注解驱动形式:
具体交互时:如果前台传入json则后台controller使用@RequestBody接收前台的json串,用@ResponseBody将bean转换为json并返回json。
如果前台请求的事key/value则后台只需要用@ResponseBody返回json即可。
文件上传常用组件有两个cos fileupload和commons fileupload
Spring已经完全集成了这两种组件,使用Commonsfileupload的较多一些
首先集成两个jar包
其次前台传入的时候需要注明,form表单需要注明enctype=”multipart/form-data”属性
在后台的springMVC中注明multipartfile解析器
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8" />
<property name="maxInMemorySize" value="1024000" />
<property name="maxUploadSize" value="-1" />
bean>
这样,一旦某个Request是MultipartRequest,它就会首先被MultipartResolver处理。
然后再转发相应的controller。
在具体的controller中将HttpservletRequest转型为MultipartHttservletRequest,就能非常方便的得到文件名和文件内容。最后调用其transferTo(newFile);即可保存到本地。
如果想将前台传入的图片转换为缩略图,则不需要借助第三方软件,jdk标准库就包含了图像处理API。
1. public static void createPreviewImage(String srcFile, String destFile) {
2. try {
3. File fi = new File(srcFile); // src
4. File fo = new File(destFile); // dest
5. BufferedImage bis = ImageIO.read(fi);
6. int w = bis.getWidth();
7. int h = bis.getHeight();
8. double scale = (double) w / h;
9. int nw = IMAGE_SIZE; // final int IMAGE_SIZE = 120;
10. int nh = (nw * h) / w;
11. if (nh > IMAGE_SIZE) {
12. nh = IMAGE_SIZE;
13. nw = (nh * w) / h;
14. }
15. double sx = (double) nw / w;
16. double sy = (double) nh / h;
17. transform.setToScale(sx, sy);
18. AffineTransformOp ato = new AffineTransformOp(transform, null);
19. BufferedImage bid = new BufferedImage(nw, nh,
20. BufferedImage.TYPE_3BYTE_BGR);
21. ato.filter(bis, bid);
22. ImageIO.write(bid, " jpeg ", fo);
23. } catch (Exception e) {
24. e.printStackTrace();
25. throw new RuntimeException(
26. " Failed in create preview image. Error: "
27. + e.getMessage());
28. }
29. }