组件扫描器:
由于SpringMVC是属于Spring的一个子项目,对Spring有着很好的兼容性,所以不需要进行过多的配置。
只需要在xml配置文件中配置上扫描器即可:让Spring来扫描Controller层的组件。
<context:component-scan base-package="org.wuancake.controller"/>
处理器适配器、映射器:
我们还需要配置处理器的适配器(RequestMappingHandlerMapping),处理器的映射器(RequestMappingHandlerAdapter)。
这样相对比较麻烦,可以使用<mvc:annotation-driven> SpringMVC使用这个配置来自动加载适配器和映射器
视图解析器(InternalResourceViewResolver):
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置逻辑视图的前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 配置逻辑视图的后缀 -->
<property name="suffix" value=".jsp" />
</bean>
最终jsp物理地址:前缀+逻辑视图名+后缀
在web.xml中同样需要进行配置:前端控制器
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
//这里还需要配置springmvc.xml的位置
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
//设置所有以action结尾的请求进入SpringMVC
<url-pattern>*.action</url-pattern>
</servlet-mapping>
ps:Spring主配置文件位置(ContextConfigLocation),Spring监听器(ContextLoderListener),也需要配置。
ps: post请求乱码问题:
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
ps: get请求乱码问题:
--tomcat配置文件<Connector>标签 URIEncoding="utf-8"
--直接对中文参数进行操作 String(xxx.getBytes("ISO-8859-1"),"utf-8")
Controller层组件书写方式:
--在类上注解@Controller告诉Spring让它来管理这个组件;在类上注解@RequestMapping("xxx")代表请求url路径上需加上此xxx前缀
--在方法上注解@RequestMapping("/xxx.action")/或者@RequestMapping(value="xxx")指定了前台请求的路径,action可有可无
--value值为数组类型,即可以将多个url请求映射到同一个方法上如:value={"findUserById","findAllUser","findUserByEmail"}
--对请求方法进行限定:@RequestMapping(method=RequestMethod.GET/POST/两者都用)
参数绑定和处理(处理器适配器来对参数进行处理):
--直接形参处写上要使用的前台传过来的参数
--在HttpServletRequest对象中已包含了请求参数,形参可为HttpServletRequest对象
HttpServletRequest来获取请求信息
HttpServletResponse来处理相应信息
HttpSession得到session中的对象
返回ModelAndView,模型和视图信息都封装在此对象中(一般只用于全局异常处理)
同样也可以在形参写上Model对象(model.addAttribute()),返回String视图
--ModelMap是Model接口的实现类,和Model使用效果相同。如果形参直接使用Model,SpringMVC框架会自动实例化ModelMap
不管是Model还是ModelAndView,其本质都是使用Request对象向jsp传递数据
--返回void(一般处理ajax异步请求),那么可以在形参上加HttpServletRequest,HttpServletResponse,来用request进行转发,或者用response进行重定向或者打印json数据
--返回String时也可以不仅可以指定逻辑视图名如 return "前缀+list+后缀"; 还可以返回重定向和转发视图
--重定向如return "redirect:/user.action?itemId=" + item.getId(); 毕竟重定向会丢失参数,需手动加上需要的参数
--转发 如return "forward:/user.action";
ps:一般使用Model模型+String视图方式,松耦合。
--简单类型参数的处理:
--如果请求参数名和处理器形参名相同,则会绑定二者。
--@RequestParam注解常用来处理简单参数类型的绑定
--value:请求的参数名
--required:是否必须
--defaultValue:默认值(如果请求参数没有)
--绑定pojo
--形参直接为pojo,前提是请求参数名和pojo字段名一致(适配器会自动将请求参数赋值给pojo的属性)!
--绑定包装pojo
--形参为包装pojo的类,使用时直接包装的类.getPojo()即可使用参数
--绑定自定义的参数(注意:使用pojo绑定参数时,请求中如果有日期类型数据,会有400错误,需自定义参数)
需求分析:SpringMVC没办法对多种格式的日期类型数据进行处理为字符串,我们需要自定义参数
原理:处理器适配器对方法参数进行处理操作,对于日期转换类Converter来说可以定义在适配器上来进行参数绑定
在<mvc:annotation-driven/>(配置适配器,映射器)此标签上进行配置
方案:--jsp界面上需要打开日期注释如:
<input type="text" name="createtime" value="<fmt:formatDate value='${user.createtime}' pattern='yyyy-MM-dd HH:mm:ss'"/>
--Converter接口<source要转换的源目标,target转换成的目标对象>
--重写convert方法,内部进行实现。
--<mvc:annotation-driver加上 conversion-service="conversionService"/>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="xxx.DateConverter" />
</set>
</property>
</bean>
--高级参数绑定:
--数组:前台传输过来n个id值,在后台形参处,可以直接写对应类型,相同名的数组;或者写pojo类内部封装这个数组都可以拿来使用。
--List: 只能通过pojo类内部封装这个List,因为SpringMVC并没有能力直接处理形参上的List;注意前台书写格式:list属性名+下标+元素属性
全局异常处理(需用到ModelAndView返回值)
由dao层向上抛出到controller的共性异常,controller可以再向上抛给DispatcherServlet,前端控制器接到异常后交由HandlerExceptionResolver异常处理器来处理异常.
自定义异常处理器:自定义异常类实现HandlerExceptionResolver接口,实现resolveException方法,返回值为ModelAndView对象,进而进一步操作。
–而在springmvc.xml中只需要配置异常处理器类即可如:<bean id=”MyHanderExceptionResolver” class=”xxx.MyHanderExceptionResolver”/>
文件上传:
三要素:
1 <input type="file" name="jackson"/>
2 表单中enctype="multipart/form-data"
3 表单method="post"
SpringMVC文件上传方法:
在方法形参加上MultipartFile jackson---->jackson.getOriginalFilaname()/.transferTo("D:/programfiles/xxx"+文件名+后缀名)
在springmvc.xml中需要配置固定的文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置文件上传大小 -->
<property name="maxUploadSize" value="xxxxxxxxx" />
</bean>
json数据交互:
SpringMVC提供的两大注解@RequestBody和@ResponseBody
如:public @ResponseBody
User findUser(@RequestBody Pojo pojo){
return User对象;//不需要考虑具体格式,两大注解已经内部解决
}
Restful开发风格:
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
使用RESTful操作资源
http://127.0.0.1/user/1 查询,GET
http://127.0.0.1/user 新增,POST
http://127.0.0.1/user 更新,PUT
http://127.0.0.1/user/1 删除,DELETE
-->而在Controller中获取这个简单参数,RequestMapping中("/xxx/{id}") 简单参数以路径形式存在,形参中不再是@RequestParam而是(@PathVariable() Integer id)
自定义拦截器:
大致流程:方法前---方法后---视图渲染后
自定义拦截器需要自定义拦截器类实现HandlerInterceptor接口,重写三个方法:preHandle(HttpServletRequest,HttpServletResponse,Object)
postHandle(HttpServletRequest,HttpServletResponse,Object,ModelAndView)
afterCompletion(HttpServletRequest,HttpServletResponse,Object,Exception)
在springmvc.xml中配置自定义拦截器:
<mvc:interceptors>
<mvc:interceptor>
<!-- 所有的请求都进入拦截器 -->
<mvc:mapping path="/**" />
<!-- 配置具体的拦截器 -->
<bean class="xxx.MyHandlerInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
具体执行情况: preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用
SpringMVC与Struts2比较:
SpringMVC作为视图层框架,和Struts2一样实现相似的功能。
Struts2入口为StrutsPreparedAndExcuteFilter过滤器,在类的级别进行操作;而SpringMVC入口为DispatcherServlet前端控制器,基于方法级别进行操作。
SpringMVC基于方法开发(一个url对应一个方法),一般来说最好设计为单例模式;struts2基于类开发,参数处理通过类的属性,只能设计为多例。
Struts2通过ValueStack值栈(与ActionContext数据中心互为引用)存储请求和响应的数据,通过OGNL存取数据;SpringMVC通过参数解析器将request请求解析,给方法形参赋值,将数据 和视图封装到ModelAndView中,又通过request域传输到jsp页面。(jsp视图解析器默认使用JSTL)