构建Spring Web整个过程的解析
1. 请求过程
2. 搭建Spring MVC 2.1. 配置DispatcherServlet AbstractAnnotationConfigDispatcherServletInitializer
在Servlet环境下,容器在类路径查找javax.servlet.ServletContainerInitializer接口实现类
Spring中实现名为SpringServletContainerInitializer类并查找WebAplicationInitializer类
AbstractAnnotationConfigDispatcherServletInitializer就是一个WebAplicationInitializer
DispatcherServlet加载包含Web组件的bean,控制器,视图解析器以及处理器映射
ContextLoaderListener 加载应用中驱动应用后端的中间层和数据层组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class <?>[] {RootConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class <?>[] {WebConfig.class}; } @Override protected String[] getServletMappings() { return new String []{"/" }; } }
WebConfig.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.ViewResolver;import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import org.springframework.web.servlet.view.InternalResourceViewResolver;@Configuration @EnableWebMvc @ComponentScan(basePackages="com.runnaccpeted.controller") public class WebConfig extends WebMvcConfigurerAdapter { @Bean public ViewResolver viewResolver () { InternalResourceViewResolver resolver = new InternalResourceViewResolver (); resolver.setPrefix("/WEB-INF/views/" ); resolver.setSuffix(".jsp" ); resolver.setExposeContextBeansAsAttributes(true ); return resolver; } @Override public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
RootConfig.class
1 2 3 4 @Configuration @ComponentScan(basePackages={"com.runnaccpeted"},excludeFilters={@Filter(type=FilterType.ANNOTATION,value=EnableWebMvc.class)}) public class RootConfig {}
配置控制器
解析 /WEB-INF/views/home.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.runnaccpeted.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;@Controller public class HomeController { @RequestMapping(value="/",method=RequestMethod.GET) public String home () { return "home" ; } }
视图 home.jsp
1 2 3 4 5 6 7 8 9 10 11 12 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > <html > <head > <meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" > <title > Insert title here</title > </head > <body > <h1 > Home</h1 > </body > </html >
测试控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;import org.junit.Test;import com.runnaccpeted.controller.HomeController;import org.springframework.test.web.servlet.MockMvc;import org.springframework.test.web.servlet.setup.MockMvcBuilders;public class HomeControllerTest { @Test public void test () throws Exception{ HomeController home = new HomeController (); MockMvc mockMvc = MockMvcBuilders.standaloneSetup(home).build(); mockMvc.perform(get("/" )).andExpect(view().name("home" )); } }
3. 传递模型数据 model是一个map集合,可以把集合数据传递给视图
1 2 3 4 5 6 7 8 import org.springframework.ui.Model;@RequestMapping(method=RequestMethod.GET) public String show (Model model) { List<User> list=userService.show(Long.MAX_VALUE, 20 ); model.addAttribute("list" ,list); return "list" ; }
访问数据
1 2 3 4 5 6 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <c:forEach items ="${list}" var ="user" > <c:out value ="${user.id}" > </c:out > <c:out value ="${user.name}" > </c:out > </c:forEach >
4. 接受请求输入
查询参数
/Users?max=230&count=50
@RequestParam
1 2 3 4 5 6 7 8 9 10 private static final long MAX=Long.MAX_VALUE;@RequestMapping(method=RequestMethod.GET) public String show ( @RequestParam(value="max",defaultValue="MAX") Long max, @RequestParam(value="count",defaultValue="20") int count, Model model) { List<User> list=userService.show(Long.MAX_VALUE, 20 ); model.addAttribute("list" ,list); return "list" ; }
路径参数输入
PathVariable
/Users/123
1 2 3 4 5 @RequestMapping(value="/{userId}",method=RequestMethod.GET) public void show (@PathVariable("userId") long userId,Model model) { model.addAttribute("list" ,userService.findOne(userId)); return "selectbyId" ; }
1 2 3 4 5 @RequestMapping("/register",method=RequestMethod.POST) public void register (User user) { userService.save(user); return "redirect:/Users/" +user.getId(); }
5. 渲染Web视图 SpringMVC中定义了名为ViewResolver的接口,resolveViewName方法传入视图名和Locale对象
1 2 3 4 5 6 7 package org.springframework.web.servlet;import java.util.Locale;public abstract interface ViewResolver { public abstract View resolveViewName (String paramString, Locale paramLocale) throws Exception; }
从中的view 接受了request,response对象,结果渲染给response
1 2 3 4 5 6 7 8 9 10 11 package org.springframework.web.servlet;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public abstract interface View { public abstract void render (Map<String, ?> paramMap, HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse) throws Exception; }
Spring定义的13种视图解析器
视图解析器
描述
BeanNameViewResolver
视图解析为Spring应用上下文的bean
ContentNegotiatingViewResolver
考虑客户端需要的内容类型来解析视图,委托给另外一个能够产生对应内容类型的视图解析器
InternalResourceViewResolver
解析为内部资源 .jsp
JasperReportViewResolver
解析为JasperReport定义
ResourceBundleViewResolver
资源bundle 属性文件
TitlesViewResolver
解析为Apache Title定义
UrlBasedViewResolver
根据视图的名称解析视图
VelocityLayoutViewResolver
解析为Velocity布局
VelocityViewResolver
解析为Velocity模版
XmlViewResolver
解析为xml特定xml文件中的bean定义
XsltViewResolvet
解析为XSLT转换后的结果
InternalResourceViewResolver
1 2 3 4 5 6 7 8 9 @Bean public ViewResolver viewResolver () { InternalResourceViewResolver resolver = new InternalResourceViewResolver (); resolver.setPrefix("/WEB-INF/views/" ); resolver.setSuffix(".jsp" ); resolver.setExposeContextBeansAsAttributes(true ); return resolver; }
xml配置
1 2 3 4 <bean id ="viewResolver" class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/views/" > </property > <property name ="suffix" value =".jsp" > </property > </bean >
5.1. Spring 的jsp标签库 commandName构建模型对象上下文信息
1 2 3 4 5 @RequestMapping("/register") public String show (Model model) { model.addAttribute(new User ()); return "form" ; }
input的value属性值会设置为模型对象中path属性对应的值
<sf:input path=”id”/> == < input name=”id” value=”0” type=”text”/>
1 2 3 4 5 6 7 <%@taglib uri="http://www.springframework.org/tags/form" prefix="sf" %> <sf:form method ="POST" commandName ="user" > <sf:input path ="id" /> <sf:input path ="name" /> <sf:password path ="password" /> </sf:form >
错误展示
path设定对象中的属性
1 2 3 <sf:errors path ="id" /> == <span id ="user.errors" > </span >
添加样式
*表示所有属性
element 表示错误渲染在div上
1 2 3 4 5 6 7 <sf:errors path ="*" element ="div" cssClass ="errors" /> <style > div .errors { font -color :#f00 ; } </style >
错误设置在每个属性上
1 2 3 4 5 6 7 8 9 <sf:label path ="name" cssErrorClass ="error" > </sf:label > <label for ="name" class ="error" > </label > <style > label .error { color :red; } </style >
5.2. 错误信息展示 1 2 3 @NotNull @Size(min=5,max=23,message="{name.size}") private String name;
在根目录下创建 ValidationMessages.properties
1 name.size =Last name must be between {min} and {max} characters long.
6. spring通用标签库 <s:message />
1 2 3 4 <%@ taglib uri="http://www.springframework.org/tags" prefix="s"%> <s:message code ="login.welcome" />
实现MessageSource接口
1 2 3 4 5 6 7 8 9 10 11 12 import org.springframework.context.MessageSource;import org.springframework.context.annotation.Bean;import org.springframework.context.support.ReloadableResourceBundleMessageSource; @Bean public MessageSource messageSource () { ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource (); messageSource.setBasename("file:///etc/messages" ); messageSource.setCacheSeconds(10 ); return messageSource; }
messages.properites
<s:url />
htmlEscape=”true” 展现 url内容到web页面上
1 2 3 4 5 <s:url href ="/Users/register" var ="register" scope ="request" htmlEscape ="true" > <s:param name ="id" value ="60" > </s:param > <s:param name ="name" value ="wt" > </s:param > </s:url > <a href ="${register}" > </a >
<s:escapeBody />
1 2 3 4 5 6 7 <s:escapeBody > <h1 > Hello </h1 > </s:escapeBody > < h1> Hello< /h1>