<!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>SpringDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置DispatcherServlet的一个初始化参数:配置SpringMVC配置文件的名称和路径 -->
<!--
实际上也可以不通过contextConfigLocation来配置SpringMVC的配置文件,而使用默认的
默认的配置文件为:/WEB-INF/<servlet-name>-servlet.xml
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!-- 注解驱动
这一个相当于上面两个
-->
<mvc:annotation-driven/>
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="top.wu.controller"></context:component-scan>
<!-- 配置视图解析器 - 把handler返回的值解析为实际的物理视图-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
在控制器的类定义及方法定义处都可标注 @RequestMapping
@RequestMapping 的 value、method、params 及 heads
分别表示请求 URL、请求方法、请求参数及请求头的映射条
件,他们之间是与的关系,联合使用多个条件可让请求映射
更加精确化。
params 和 headers支持简单的表达式:
不能为 value1
的两个请求参数,且 param1 参数的值必须为 value1
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过 @PathVariable("xxx") 绑定到操作方法的入参中。
在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法
的参数,若不存在,将抛出异常
@RequestMapping("/hello")
public void testCookieValue(@CookieValue(value = "JSESSIONID") String JSESSIONID) {
System.out.println(JSESSIONID);
}
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。
如:dept.deptId、dept.address.tel 等
控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型数据信息。 SpringMVC会把ModelAndView的model中的数据放到request域对象中
• 添加模型数据:
– MoelAndView addObject(String attributeName, Object
attributeValue)
– ModelAndView addAllObject(Map<String, ?> modelMap)
• 设置视图:
– void setView(View view)
– void setViewName(String viewName)
@RequestMapping("/testmap")
//实际上也可以是Model、ModelMap类型
public String testMap(Map<String,Object> map) {
map.put("test","test");
return "success";
}
若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes, Spring MVC 将在模型中对应的属性暂存到 HttpSession 中。
• @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中
– @SessionAttributes(types=User.class) 会将隐含模型中所有类型 为 User.class 的属性添加到会话中。
– @SessionAttributes(value={“user1”, “user2”})
– @SessionAttributes(types={User.class, Dept.class})
– @SessionAttributes(value={“user1”, “user2”}, types={Dept.class})
PS:这个注解只能放在类的上面
• 在方法定义上使用 @ModelAttribute 注解:Spring MVC在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
• 在方法的入参前使用 @ModelAttribute 注解:
– 可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参
– 将方法入参对象添加到模型中
1.执行@ModelAttribute注解修饰的方法:从数据库中取出对象,把对象放入到Map中,键为user
2.SpringMVC从Map中取出User对象,并把请求参数赋给User对象对应的属性
3.SpringMVC把上述对象传入目标方法的参数
注意:在@ModelAttribute修饰的方法中,放入到Map时的键需要和目标方法的入参类型的第一个字母小写的字符串一致
1.调用@ModelAttribute注解修饰的方法,实际上把@ModelAttribute方法中Map中的数据放在了implicitModel中。
2.解析请求处理器的目标参数,实际上该属性来自于WebDataBinder对象的target属性。
(1)创建WebDataBinder对象:
@Component
public class HelloView implements View {
@Override
public String getContentType() {
return "html/text";
}
@Override
public void render(Map<String, ?> map, javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
httpServletResponse.getWriter().print("hello view");
}
}
<!-- 配置视图BeanNameViewResolver解析器,使用视图名字来解析视图 -->
<!-- 通过order属性来定义视图解析器的优先级,order值越小优先级越高 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
springmvc不支持将字符串转换为日期格式
<!-- 注解驱动,配置转换器时要用到conversion-service这个属性 -->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>
<!-- 配置转换器工厂 -->
<bean id="conversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 配置多个转换器 -->
<property name="converters">
<list>
<!-- 配置日期转换器 -->
<bean class="com.wu.conversion.DataConveter"/>
</list>
</property>
</bean>
//泛型第一个为转换前的类型,后一个为转换后的类型
public class DataConveter implements Converter<String, Date> {
//这里的s为要转换的字符串
@Override
public Date convert(String s) {
try {
if (s != null) {
DateFormat df = new SimpleDateFormat("yyyy_MM-dd hh:mm-ss");
return df.parse(s);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
<!-- 显示所有的错误消息 -->
<form:errors path="*"></form:errors>
<!-- 显示对应字段的错误消息 -->
<input type="text" name="name">
<form:errors path="name"></form:errors>
• 每个属性在数据绑定和数据校验发生错误时,都会生成一个对应的 FieldError 对象。
• 当一个属性校验失败后,校验框架会为该属性生成 4 个消息代码,这些代码以校验注解类名为前缀,结合modleAttribute、属性名及属性类型名生成多个对应的消息代码:例如 User 类中的 password 属性标准了一个 @Pattern 注解,当该属性值不满足 @Pattern 所定义的规则时, 就会产生以下 4 个错误代码:
– Pattern.user.password
– Pattern.password
– Pattern.java.lang.String
– Pattern
eg:
#i18n.properties
NotEmpty.Animal.name=名字不能为空
• 当使用 Spring MVC 标签显示错误消息时, Spring MVC 会查看WEB 上下文是否装配了对应的国际化消息,如果没有,则显示默认 的错误消息,否则使用国际化消息。
<!-- 配置国际化资源文件 -->
<bean id="resourceBundleMessageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
<!-- 配置SessionLocaleResolver -->
<bean id="sessionLocaleResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
<!-- 配置LocaleChangeInterceptor -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
<a href="/i18n?locale=zh_CH">中文</a>
<a href="/i18n?locale=en_US">英文</a>
<mvc:interceptors>
<!-- 配置拦截器作用(或者是不作用)的路径 -->
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean class="top.wu.controller.MyInterceptHandler"></bean>
</mvc:interceptor>
<!-- 配置LocaleChangeInterceptor -->
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
public class MyInterceptHandler implements HandlerInterceptor {
/**
* 该方法在目标方法之前被调用
* 若返回值为true,则继续调用后续的拦截器和目标方法
* 若返回值为false,则不会调用后续的拦截器和目标方法
*
* 可以考虑做权限,日志,事务等
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return false;
}
/**
*调用目标方法之后,但渲染视图之前
* 可以对请求域中的属性或视图做出修改
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 渲染视图之后被调用。释放资源
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
<mvc:interceptors>
<!-- 配置自定义拦截器 -->
<bean class="top.wu.controller.MyInterceptHandler"></bean>
</mvc:interceptors>