1.Web MVC基础
MVC的本质是表现层模式,我们以视图模型为中心,将视图和控制器分离出来。就如同分层模式一样,我们以业务逻辑为中心,把表现层和数据访问层代码分离出来是一样的方法。框架只能在技术层面上给我们帮助,无法在思考和过程上帮助我们,而我们很多人都不喜欢思考和尝试。
2.实现Web MVC的基础
实现Web MVC基础可以概括为1个前段控制器和2个映射。
(1)前端控制器FrontController
ASP.NET和JSP都是以Page路径和URL一一对应,Web MVC要通过URL映射Controller和View,就需要一个前端控制器统一接收和解析请求,再根据的URL将请求分发到Controller。由于ASP.NET和Java分别以IHttpHandler和Servlet作为核心,因此ASP.NET MVC和Spring MVC分别使用实现了对应接口的MvcHandler和DispatcherServlet作为前段控制器。
ASP.NET中通过HttpModule的实现类处理URL映射,UrlRoutingModule根据URL将请求转发给前端控制器MvcHandler。Spring MVC中,则根据URL的配置,直接将请求转发给前端控制器DispatcherServlet。
(2)URL和Contrller的映射
ASP.NET MVC将URL和Controller的映射规则存储在RouteCollection中,前端控制器MvcHandler通过IController接口查找控制器。Spring MVC则通过RequestMapping和Controller注解标识映射规则,无需通过接口依赖实现控制i器。
(3)URL和View的映射
ASP.NET MVC 默认通过RazorViewEngine来根据URL和视图名称查找视图,核心接口是IViewEngine。Spring MVC 通过internalResourceViewResolver根据URL和视图名称查找视图,核心接口是ViewResolver。
3.Spring MVC的基础配置
(1)前端控制器DispatcherServlet初始化:AbstractAnnotationConfigDispatcherServletInitializer
ASP.NET MVC初始化需要我们在HttpApplication.Application_Start方法中注册默认的URL和Controller规则,Spring MVC由于采用注解映射URL和Controller,因此没有对应的步骤。ASP.NET在根web.config中配置了UrlRoutingModule可以将请求转发给MvcHandler,Spring MVC我们需要我们配置DispatcherServlet以及其对应的URL来达到接管所有请求的目的,Spring已经利用Servlet3.0定义的ServletContainerInitializer机制,为我们提供了内置的AbstractAnnotationConfigDispatcherServletInitializer,只要只需要像继承HttpApplication的MvcApplication一样,写一个MvcInitializer。
1 packages4s;2
3 importorg.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;4
5 public class MvcInitializer extendsAbstractAnnotationConfigDispatcherServletInitializer {6
7 @Override8 protected Class>[] getRootConfigClasses() {9 return newClass[] { };10 }11
12 @Override13 protected Class>[] getServletConfigClasses() {14 return new Class[] { MvcConfig.class};15 }16
17 @Override18 protectedString[] getServletMappings() {19 return new String[] { "/"};20 }21
22 }
(2)URL和View的映射:WebMvcConfigurerAdapter
ASP.NET的RazorViewEngine内置了View的Path和扩展名.cshtml的规则。Spring MVC的internalResourceViewResolver没有提供默认值,一般我们会指定将View放置在统一的视图目录中,使用特定的扩展名。Spring同样提供了内置的WebMvcConfigurerAdapter,我们只需写一个自己的MvcConfig继承它,重写configureViewResolvers方法即可。
1 packages4s;2
3 importorg.springframework.context.annotation.ComponentScan;4 importorg.springframework.context.annotation.Configuration;5 importorg.springframework.web.servlet.config.annotation.EnableWebMvc;6 importorg.springframework.web.servlet.config.annotation.ViewResolverRegistry;7 importorg.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;8 importorg.springframework.web.servlet.view.InternalResourceViewResolver;9
10 @EnableWebMvc11 @ComponentScan12 @Configuration13 public class MvcConfig extendsWebMvcConfigurerAdapter {14
15 @Override16 public voidconfigureViewResolvers(ViewResolverRegistry registry) {17 InternalResourceViewResolver viewResolver = newInternalResourceViewResolver();18 viewResolver.setPrefix("/WEB-INF/views/");19 viewResolver.setSuffix(".jsp");20 registry.viewResolver(viewResolver);21 }22 }
4.Spring MVC的Controller、Model和View
(1)URL和Controller的映射:
Spring MVC和ASP.NET MVC的不同,不通过IController接口标识Controller,也不通过RouteCollection定义URL和Controller,取而代之的是两个注解:Controller和RequestMapping。因此我们在普通的POJO类上应用@Controller和@RequestMapping即可。
1 packages4s;2
3 importjavax.validation.Valid;4 importorg.springframework.security.access.prepost.PreAuthorize;5 importorg.springframework.security.core.context.SecurityContextHolder;6 importorg.springframework.stereotype.Controller;7 importorg.springframework.validation.BindingResult;8 importorg.springframework.web.bind.annotation.ModelAttribute;9 importorg.springframework.web.bind.annotation.RequestMapping;10 importorg.springframework.web.bind.annotation.RequestMethod;11 importorg.springframework.web.bind.annotation.RequestParam;12 importorg.springframework.web.bind.annotation.ResponseBody;13
14 @Controller15 public classMyController {16
17 @ResponseBody18 @RequestMapping(value = "/")19 publicString home() {20 return "home";21 }22
23 @RequestMapping(value = "/register")24 public String register(@ModelAttribute("model") RegisterUserModel model) {25 return "register";26 }27
28 @RequestMapping(value = "/register", method =RequestMethod.POST)29 public String register(@ModelAttribute("model") @Valid RegisterUserModel model, BindingResult result) {30 if (!result.hasErrors()) {31 return "redirect:/account";32 }33 return "register";34 }35 }
(2)Model:
通过使用@ModelAttribute、@Valid和BindingResult参数,我们可以指定Model的Name是否参与验证并获取验证结果。为在Model上使用注解验证,还需要引入validation-api和hibernate-validator。
ASP.NET将视图最终编译为WebViewPage,View和Model是一一对应并且类型匹配的,Model可以是任意的POCO。Spring MVC中View和Model是一对多的,提供了ModelMap和其子类ModelAndView提供类似ASP.NET MVC中ViewResult的功能。ModelMap的基类是LinkedHashMap。
Spring MVC中没有ViewResult类型。在Spring MVC中,我们一般返回String类型,可以有多种含义:
a.返回View的名称。
b.返回文本:在Action上应用@ResponseBody注解时。
c.返回跳转:以"redirect:"开头时。如:return "redirect:/success"
模型的验证:
(1)在Model字段上使用JSR-303定义的注解(需要引入hibernate validator)。
(2)在Controller的Model参数上应用@ModelAttribute、@Valid
(3)在View中使用标签
Spring MVC需要添加jstl和spring的tag支持才能完成模型相关的操作。由于Spring MVC中的View和ASP.NET MVC中的区别较大,没有办法指定View持有的Model类型也就没有了智能提示和错误检测的优势。
1 packages4s;2
3 importjavax.validation.constraints.NotNull;4 importjavax.validation.constraints.Size;5
6 public classRegisterUserModel {7 @Size(max = 20, min = 5)8 privateString userName;9 @Size(max = 20, min = 5)10 privateString password;11 @NotNull12 privateString confirmPassword;13
14 publicString getUserName() {15 returnuserName;16 }17
18 public voidsetUserName(String userName) {19 this.userName =userName;20 }21
22 publicString getPassword() {23 returnpassword;24 }25
26 public voidsetPassword(String password) {27 this.password =password;28 }29
30 publicString getConfirmPassword() {31 returnconfirmPassword;32 }33
34 public voidsetConfirmPassword(String confirmPassword) {35 this.confirmPassword =confirmPassword;36 }37 }
register.jsp
1
2
3
4
5
6
7
8
Getting Started: Serving Web Content9
10
11
12
13
14
15
16 Form has errors