一、了解
Spring Web MVC是一种基于java,并实现了WebMVC设计模式的请求驱动类型的轻量级Web框架(基于请求驱动指的是就是使用请求-相应模型)。
该框架也是用了MVC架构模式的思想,将web层进行职责解耦。它的目的就是帮助我们简化开发。
Spring Web MVC的前端控制器为DispatcherServlet,其应用控制器可以拆解为:
A、(Handler Mapping)处理器管理;
B、视图解析器(View Resolver)进行视图管理;
C、页面控制器/动作/处理器为Controller接口
二、流程说明
在请求离开浏览器时,会带有用户所请求内容的信息,至少会包含请求的URL。但是还可能带有其他的信息,例如用户提交的表单信息。
1、请求的第一站是Spring的DispatcherServlet。与大多数基于Java的Web框架一样,SpringMVC所有的请求都会通过一个前端控制器(front controller)Servlet。前端控制器是常用的Web应用程序模式,在这里一个单例的Servlet将请求委托给应用程序的其他组件来执行实际的处理。在Spring MVC中DispatcherServlet就是前端控制器。(DispatcherServlet的任务就是将请求送给SpringMVC控制器controller),控制器是一个用于处理请求的Spring组件。
2、请求的第二站是处理器映射,在典型的应用程序中可能会有多个控制器,DispatcherServlet需要知道应该请求发送给哪个控制器。所以DispatcherServlet以查询一个或多个处理器映射(handler mapping)来确定请求的下一站在哪里。处理器映射会根据请求所携带的URL信息来进行决策。一旦选择了合适的控制器,DispatcherServlet会将请求发送给选中的控制器。
3、到了控制器,请求会卸下其负载(用户提交的信息)并耐心等待控制器处理这些信息。(实际上,设计良好的控制其本身只处理很少甚至不处理工作,而是将业务逻辑委托给一个或多个服务对象进行处理。)
控制器在完成逻辑处理后,通常会产生一些信息,这些信息需要返回给用户并在浏览器上显示。这些信息被称为模型(model)
不过仅仅给用户返回原始信息是不够的,这些信息需要以用户友好的方式进行格式化,一般会是HTML。所以信息需要发送一个视图(view),通常是一个JSP
4、控制器所做的最后一件事就是将模型数据打包,并且标示出用于渲染输出的视图名。它接下来会将请求连同模型和视图名发送会DispatcherServlet。这样控制器就不会与特定的视图相耦合,传递给DispatcherServlet的视图名并不直接表示某个特定的JSP。实际上,它甚至并不能确定视图就是JSP。相反,它仅仅传递了一个逻辑名称,这个名字将会用来查找产生结果的真正视图。
5、DispatcherServlet将会使用视图解析器(view resolver)来将逻辑视图名匹配为一个特定的视图实现,它可能是JSP也可能不是。既然DispatcherServlet已经知道由哪个视图渲染结果,那请求的任务基本上也就完成了。它的最后一站是视图的实现。
6、在这里它交付了模型数据。请求的任务就完成了。
7、视图将使用模型数据渲染输出,这个输出会通过相应对象response传递给客户端。
三、配置SpringMVC的例子
在配置SpringMVC前需要配置gradle,build.gradle如下:
group 'B10' version '1.0-SNAPSHOT' apply plugin: 'java' apply plugin: 'war' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { testCompile group: 'junit', name: 'junit', version: '4.11' compile group: 'org.springframework', name: 'spring-webmvc', version: '5.0.0.RELEASE' compile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0' compile group: 'javax.servlet', name: 'jstl', version: '1.2' }
按照之前的方法,servlet的配置信息会放在web.xml下,而现在,我们可以通过继承AbstractAnnotationConfigDispatcherServletInitializer类而生成的子类WebInitializer,而这个类就是所谓的DispatcherServlet,所以WebInitializer如下:
package com.zxc.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import javax.servlet.Filter; /** * Created by Administrator on 2018/4/2. */ public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[0]; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class};//注册 配置文件 } @Override protected Filter[] getServletFilters() { CharacterEncodingFilter filter=new CharacterEncodingFilter(); filter.setEncoding("utf-8"); filter.setForceEncoding(true); return new Filter[]{filter}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
我们书写DispatcherServlet的时候,需要重写三个方法:
1、getServletMappings():它会将一个或多个路径映射到DispatcherServlet上。在本例中,它映射的是“/”,这表示它会是引用的默认Servlet。它会处理进入引用的所有请求。
2、getServletConfigClasses(),方法返回的带有@Configuration注解的类将会用来定义DispatcherServlet引用上下文中的bean。
3、getRootConfigClasses()方法返回的带有@Configuration注解的类将会用来配置ContextLoaderListener创建的应用上下文中的bean。
如果愿意的话可以web.xml和上面的DispatcherServlet一起写,但没什么更多的用处,因为重复。
我们需要配置DispatcherServlet,上面的getServletConfigClasses()方法可以读取到其配置文件webConfig.xml,代码如下:
package com.zxc.config; 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.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; /** * Created by Administrator on 2018/4/2. */ @Configuration @EnableWebMvc @ComponentScan("com.weikun") public class WebConfig extends WebMvcConfigurerAdapter { @Bean public ViewResolver viewResolver(){//告诉SpringMVC 他的V层在哪里 InternalResourceViewResolver vr=new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/view/"); vr.setSuffix(".jsp"); return vr; } @Override//允许spring mvc控制器对静态资源进行放行。 public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // TODO Auto-generated method stub super.addResourceHandlers(registry); } }
@EnableWebMvc:启用SpringMVC。
@ComponentScan:启用组件扫描,告诉控制器扫描哪里
viewResolver()方法用来配置JSP视图解释器,在查找的时候它会在视图名称上加上特定的前后缀。(注意方法上需要加@Bean)
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
上面这个方法的作用是配置静态资源处理,我们要求DispatcherServlet将对静态资源的请求转发到Servlet容器中默认的Servlet上,而不是亲自来处理请求。
配置完DispatcherServlet后,需要我们写具体的一个控制器:
package com.zxc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import java.util.Map; @Controller public class MyController { @RequestMapping("/hello") public String hello(){ return "success"; } }
请求为/hello时候,映射到这里。
前端页面主要内容:
<a href="/hello">你好</a>
四、Spring MVC的注解写法
在Spring2.5版本之前我们通过实现Controller接口或其实现来定义我们的处理器类,现在我们使用注解式的控制器。通过@Controller和@RequestMapping注解定义我们的处理器类。并且提供了一组强大的注解:
1、@Controller:用于标识是处理器类
2、@RequestMapping:请求到处理器功能方法的映射规则;
3、@RequestParam:请求参数到处理器功能处理方法的方法参数上绑定。
4、@ModelAttribute:请求参数到命令对象的绑定;
5、@SessionAttributes:用于声明session级别存储的属性,放置在处理器类上,通常列出模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session中;
6、窄化请求映射:2是对1的窄化;当我们在不同的控制器中有多个针对于/hello的映射,这样,前端就不知道该映射到哪一个,这样,现在类上进行一次映射规则设定,再在具体方法上进行窄化规则。
7、URL路径映射方式一:
普通的URL路径映射:
@RequestMapping(value={"/test1","/user/create"}):多个URL路径可以映射到同一个控制器的功能处理方式(/test1和/user/create都会映射到这个控制器类下)
URI模板模式映射:
@RequestMapping(value="/users/{userId}"):其中{xxx}为占位符,请求的URL可以是“/users/123456"或“/user/abcd”,
@RequestMapping(value="/users/{userId}/create"):这样也是可以的,请求的URL可以是“/users/123/create”.
@ResquestMapping(value="/users/{userId}/topics/{topicId}"):这样也是可以的,请求的URL可以是“/user/123/topics/123”
URL路径映射-ANT风格
@RequestMapping(value = "/ok2/{username}/{pwd}") public String ok2(@PathVariable String username,@PathVariable String pwd){ System.out.println(username); System.out.println(pwd); return "success"; }
URL路径映射-正则风格
从Spring3.0开始支持正则表达式风格的URL路径映射,格式为{变量名:正则表达式}
@RequestMapping(value = "/ok3/{username:\d+}-{pwd:\d+}") public String ok3(@PathVariable String username,@PathVariable String pwd){ System.out.println(username); System.out.println(pwd); return "success"; }
8、 @RequestMapping(value = "/ok1",method = {RequestMethod.POST})
这样可以限定映射的方式只为post