SpringMVC的请求处理过程:
请求首先交给前端控制器(DispatcherSerlet)来处理;前端控制器的任务是把请求交给哪一个控制器(Controller);在这之前它会查询处理器映射(handler mapping)来确定具体的Controller;处理器映射怎么知道呢?是根据URL所携带的参数进行决策的;控制器会根据用户提交的信息把业务逻辑交给了一个或者多个服务对象对其处理,并耐心等待;处理后的信息被称为模型(Model),然后打包模型数据和输出逻辑视图名,最后一起交给前端控制器(DispatcherSerlet);前端控制器接下来使用视图解析器将逻辑视图匹配为一个特定的视图实现,可能是JSP;前端控制器将渲染结果显示给视图,交付模型数据;视图将使用模型数据渲染输出,通过相应对象传递给客户端,如浏览器。
使用Java将DispatcherServlet配置在Servlet容器中:
定义个一个继承AbsractAnnotationConfigDispatcherServletInitializer的任意类。实际上会同时创建DispatcherServlet和ContextLoaderListener,这样能够代替传统的web.xml,但是它只能支持Servlet3.0的服务器,即tomcat7以上的版本。
启动SpringMVC:通过spring的XML配置,使用<mvc:annotation-driven>启用注解驱动的SpringMVC 。
测试控制器:
Spring3.2开始到现在包含了一种mock SpringMVC并针对控制器执行http请求的机制,测试控制器的时候不需要重新启动web浏览器和web服务器。相关依赖包在spring-test中。
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import spittr.web.HomeController;
public class HomeControllerTest {
@Test
public void testHomePage() throws Exception {
HomeController controller = new HomeController();
MockMvc mockMvc = standaloneSetup(controller).build(); //搭建MockMvc
mockMvc.perform(get("/")) //对/执行get请求
.andExpect(view().name("home")); //预期得到home的视图
}
}
定义类级别的请求处理:
import static org.springframework.web.bind.annotation.RequestMethod.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/")//将home的方法映射到路径为/的get请求
@RequestMapping({"/","/page"})//将home的方法映射到路径为/和/page的get请求
public class HomeController {
@RequestMapping(method = GET)
public String home(Model model) {
return "home";
}
}
接收请求的输入:
SpringMVC将客户端中的数据传递给控制器的方式有:查询参数、表单参数、路径变量。
1、查询参数
@RequestMapping(method=RequestMethod.GET)
public List<Spittle> spittles(
@RequestParam(value="max", defaultValue=MAX_LONG_AS_STRING) long max,
@RequestParam(value="count", defaultValue="20") int count) {
return spittleRepository.findSpittles(max, count);
}
2、通过路径参数接收输入
@RequestMapping(value="/{spittleId}", method=RequestMethod.GET)
public String spittle(
@PathVariable("spittleId") long spittleId,
Model model) {
model.addAttribute(spittleRepository.findOne(spittleId));
return "spittle";
}
3、处理表单:展现表单和处理用户通过表单提交的数据。
注册、校验
@RequestMapping(value="/register", method=GET)
public String showRegistrationForm() {
return "registerForm";
}
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.validator.constraints.Email;
@RequestMapping(value="/register", method=POST)
public String processRegistration(
@Valid Spitter spitter,
Errors errors) {
if (errors.hasErrors()) {
return "registerForm";
}
spitterRepository.save(spitter);
return "redirect:/spitter/" + spitter.getUsername();
}
视图渲染
SpringMVC定义了一个接口ViewResolver:视图名和对象Locale为变量,返回一个对象为View。
public interface ViewResolver{
View resolverViewName(String viewName, Locale locale)throws Exception;
}
而View是另外一个接口;View的任务就是接收模型以及servlet的request和response对象,并将输出结果渲染到response。
public interface View {
String getContentType();
void render(Map<String,?>model, HttpServletRequest request,
HttpServletResponse response) throws Exception;
}
一般情况下,我们不关心这些接口,是因为为了了解视图解析器内部是怎样工作的。spring提供了内置实现,一共13个视图解析器。不需要过多的了解,每种解析器对应Java Web应用中的特定的某种视图技术。学习常用的视图解析器就好了,比如InternalResourceViewResolver 一般用来解析jsp,jsp被大部分Java Web所用到。
配置用于JSP的视图解析器:
InternalResourceViewResolver会按照约定在逻辑视图加上前缀和后缀,进而确定一个Web应用中视图资源的物理路径,就会将逻辑视图解析为jsp文件。
使用Apache Tiles视图定义布局(后续补充)
使用Thymeleaf渲染视图(后续补充)