SpringMVC温故知新
1. SpringMVC流程简记
(1) 用户发送请求至前端控制器DispatcherServlet
(2) DispatcherServlet收到请求调用HandlerMapping处理器映射器
(3) 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
(4) DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
(5) 执行处理器(Controller,也叫后端控制器)。
(6) Controller执行完成返回ModelAndView
(7) HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
(8) DispatcherServlet将ModelAndView传给ViewReslover视图解析器
(9) ViewReslover解析后返回具体View
(10) DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
(11) DispatcherServlet响应用户
2. 组件简要说明
(1) DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
(2) HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求找到Handler,即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等
(3) Handler:处理器
Handler是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
(4) HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行
(5) View Resolver:视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户
(6) View:视图
springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面
在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。需要用户开放的组件有handler、view
3. 简单参数绑定
(1)当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定,参数类型推荐使用包装数据类型,因为基础数据类型不可以为null
整形:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean
说明:对于布尔类型的参数,请求的参数值为true或false
(2)使用@RequestParam常用于处理简单类型的绑定
value:参数名字,即入参的请求参数名字,如value=“item_id,表示请求的参数区中的名字为item_id的参数的值将传入;
required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报;
TTP Status 400 - Required Integer parameter 'XXXX' is not present
defaultValue:默认值,表示如果请求中没有同名参数时的默认值
public String editItem(@RequestParam(value="item_id",required=true) String id) { }
形参名称为id,但是这里使用value="item_id"限定请求的参数名为item_id,所以页面传递参数的名必须为item_id。
注意:如果请求参数中没有item_id将跑出异常:
HTTP Status 500 - Required Integer parameter 'item_id' is not present
这里通过required=true限定item_id参数为必需传递,如果不传递则报400错误,可以使用defaultvalue设置默认值,即使required=true也可以不传item_id参数值
(3)使用pojo接收表单数据
如果提交的参数很多,或者提交的表单中的内容很多的时候可以使用pojo接收数据。要求pojo对象中的属性名和表单中input的name属性一致。请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性,注意:提交的表单中不要有日期类型的数据,否则会报400错误。如果想提交日期类型的数据需要用到后面的自定义参数绑定的内容。
(4)自定义参数绑定
由于日期数据有很多种格式,所以springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定。在springmvc这可以在处理器适配器上自定义Converter进行参数绑定。如果使用<mvc:annotation-driven/>可以在此标签上进行扩展。
publicclass DateConverter implements Converter<String, Date> { @Override public Date convert(String source) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { returnsimpleDateFormat.parse(source); } catch (ParseException e) { e.printStackTrace(); } returnnull; } }
<!-- 加载注解驱动 -->
<mvc:annotation-drivenconversion-service="conversionService"/>
<!-- 转换器配置 -->
<beanid="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<propertyname="converters">
<set>
<beanclass="cn.itcast.springmvc.convert.DateConverter"/>
</set>
</property>
</bean>
4. 高级参数绑定
4.1 数组
Controller方法中可以用String[]接收,或者pojo的String[]属性接收。两种方式任选其一即可
4.2 List对象
List中存放对象,并将定义的List放在包装类中,使用包装pojo对象接收
5. RequestMapping
通过RequestMapping注解可以定义不同的处理器映射规则,@RequestMapping(value="/item")或@RequestMapping("/item)
value的值是数组,可以将多个url映射到同一个方法
5.1 限定方法
@RequestMapping(method = RequestMethod.GET)或者@RequestMapping(method = RequestMethod.POST)或@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
6. Controller 返回值
6.1 返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view
6.2 返回字符串
(1)controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址
(2)Contrller方法返回结果重定向到一个url地址,如下商品修改提交后重定向到商品查询方法,参数无法带到商品查询方法中,redirect方式相当于“response.sendRedirect()”,重定向后浏览器的地址栏变为转发后的地址,因为重定向即执行了一个新的request和response。由于新发起一个request原来的参数在重定向时就不能传递到下一个url,如果要传参数可以/item/queryItem.action后边加参数,如下:/item/queryItem?...&…..
(3) forward转发,forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址。转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到。
7. 异常处理器
springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。 系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。
为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息
1. 自定义异常类
public class CustomException extends Exception { /** serialVersionUID*/ private static final long serialVersionUID = -5212079010855161498L; public CustomException(String message){ super(message); this.message = message; } //异常信息 private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
2. 自定义异常处理器
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
ex.printStackTrace();
CustomException customException = null;
//如果抛出的是系统自定义异常则直接转换
if(ex instanceof CustomException){
customException = (CustomException)ex;
}else{
//如果抛出的不是系统自定义异常则重新构造一个系统错误异常。
customException = new CustomException("系统错误,请与系统管理 员联系!");
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", customException.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
8. 文件上传
在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:<Context docBase="F:\develop\upload\temp" path="/pic" reloadable="false"/>,访问http://localhost:8080/pic即可访问F:\develop\upload\temp下的图片。CommonsMultipartResolver解析器依赖commons-fileupload和commons-io
8.1 配置解析器
<!-- 文件上传 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置上传文件的最大尺寸为5MB --> <property name="maxUploadSize"> <value>5242880</value> </property> </bean>
Tip: <Context>
元素,用于将本地文件系统中的一个目录,映射成一个可供Web浏览器访问的虚拟根目录
path属性,用于指定Web应用的虚拟路径
docBase属性,用于指定该虚拟路径,所映射到的本地文件系统目录,可以使用绝对路径,或者相对于<Tomcat安装目录>/webapps
的相对路径
9. Json数据交互
9.1 @requestBody
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。List.action?id=1&name=zhangsan&age=12
9.2 @ResponseBody
该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
10. RESTful
@RequestMapping(value="/ viewItems/{id}"):{×××}占位符,请求的URL可以是“/viewItems/1”或“/viewItems/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上
11. 静态资源访问
如果在DispatcherServlet中设置url-pattern为 /,则必须对静态资源进行访问处理。spring mvc 的<mvc:resources mapping="" location="">实现对静态资源进行映射访问。如下是对js文件访问配置:<mvc:resources location="/js/" mapping="/js/**"/>
SpringMVC提供<mvc:resources>来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下方案进行解决:
方案一. 拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml)
<mvc:resources location="/" mapping="/**/*.js"/> <mvc:resources location="/" mapping="/**/*.css"/> <mvc:resources location="/assets/" mapping="/assets/**/*"/> <mvc:resources location="/images/" mapping="/images/*" cache-period="360000"/> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**/*"/> <mvc:exclude-mapping path="/**/fonts/*"/> <mvc:exclude-mapping path="/**/*.css"/> <mvc:exclude-mapping path="/**/*.js"/> <mvc:exclude-mapping path="/**/*.png"/> <mvc:exclude-mapping path="/**/*.gif"/> <mvc:exclude-mapping path="/**/*.jpg"/> <mvc:exclude-mapping path="/**/*.jpeg"/> <mvc:exclude-mapping path="/**/*login*"/> <mvc:exclude-mapping path="/**/*Login*"/> <bean class="com.luwei.console.mg.interceptor.VisitInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
方案二. 使用默认的静态资源处理Servlet处理静态资源(涉及spring-mvc.xml, web.xml)
在spring-mvc.xml中启用默认Servlet
<mvc:default-servlet-handler/>
在web.xml中增加对静态资源的处理
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> <url-pattern>*.css</url-pattern> <url-pattern>/assets/*"</url-pattern> <url-pattern>/images/*</url-pattern> </servlet-mapping>
但是当前的设置必须在Spring的Dispatcher的前面
方案三. 修改Spring的全局拦截设置为*.do的拦截(涉及web.xml)
<servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
在SpringMVC3.0之后推荐使用:
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.html"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.ico"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.js"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.css"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.png"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.gif"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.jpg"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.ttf"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.woff"/> <mvc:resources location="/WEB-INF/html/" mapping="/**/*.woff2"/>