1.Spring MVC起步
1.1 Spring MVC的请求流程
请求的第一站是Spring的DispatcherServlet,Spring mvc所有的请求都会经过一个前端控制器Servlet,这个前端控制器就是DispatcherServlet。
DispatcherServlet将请求发送给Spring MVC控制器,这个控制器其实是一个用于处理请求的Spring组件,在一个典型的应用程序中可能会有多个控制器,DispatcherServlet需要知道要将请求发送给哪个控制器,因此他会查询一张处理器映射表,来确认下一个站点去哪里。它根据url携带的信息进行选择。
选择了合适的处理器之后,DispatcherServlet就会卸载它携带的信息给对应的处理器,然后等待处理器去执行。控制器在完成处理后,一般会返回一些信息给用户,这些信息会在浏览器上显式,这些信息就被称为模型。信息一般是格式化的信息,可以转化为HTML,因此信息需要发送给一个视图,通常是JSP。
控制器做的最后一件事是将模型数据打包,然后标注用于渲染输出的视图名,然后把模型和视图名返回给DispatcherServlet。DispatcherServlet则在接收信息后,使用视图解析器匹配一个特定的视图实现。DispatcherServlet将结果交给视图实现器,视图使用模型数据进行渲染,在页面上呈现给用户。
1.2 搭建Spring MVC
DispatcherServlet是Spring MVC的核心,在早期是使用web.xml文件配置,如今都是使用java 配置。下面是配置的代码:
package com.liumiao.miyao;import com.liumiao.miyao.config.RootConfig;
import com.liumiao.miyao.config.WebConfig;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class<?>[]{RootConfig.class};}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class<?>[]{WebConfig.class};}@Overrideprotected String[] getServletMappings() {return new String[] {"/"};}
}
WebConfig和RootConfig是配置类。
这段代码可能不需要了解态度,只需要知道它会自动配置DispatcherServlet和Spring应用上下文,其实就是相关类都在这个抽象类里面配置。
这个类实现了三个方法,getServletMappings将路径映射到DispatcherServlet上,这里的/代表他是默认的Servlet,他会处理所有的请求。
另外两个方法与Spring上下文有关。
当DispatcherServlet启动的时候,他会创建Spring应用上下文,并加载配置文件和生成bean,在getServletConfigClass方法中,我们要求DispatcherServlet加载应用上下文时,它就会使用WebConfig配置需要的类的bean。但是在web应用中,通常还会加载另一个应用上下文,它是由ContextLoaderListener中创建。DispatcherServlet加载包含web组件的bean,比如控制器,视图解析器,以及处理器映射,而ContextLoaderListener加载其他应用中的bean,这些bean通过是驱动应用后端的中间件和数据层组件。
AbstractAnnotationConfigDispatcherServletInitializer会同时创建DispatcherServlet和ContextLoaderListener,而getServletConfigClasses会返回DispatcherServlet需要的bean,getRootConfigClasses会返回ContextLoaderListener所需要的bean。
1.3 启动Spring MVC
我们依然是使用java代码配置。
这里需要一个注解@EnableWebMvc
启动Spring MVC需要配置视图解析器,启动组件扫描,如果不进行配置,那么就会使用默认的servlet。
下面是webconfig的配置文件。
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;
import org.springframework.web.servlet.view.JstlView;@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.example.controller"})
public class WebConfig extends WebMvcConfigurerAdapter {//配置视图解析器@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();viewResolver.setViewClass(JstlView.class);viewResolver.setPrefix("/WEB-INF/jsp/");viewResolver.setSuffix(".jsp");viewResolver.setExposeContextBeansAsAttributes(true);return viewResolver;}//配置静态资源的处理@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}
}
首先它有一个扫描的注解,因此它会这个包下的bean,这是后面会补充的部分。
其次配置了视图解析器的bean
最后的重写方法要求DispatcherServlet将静态资源发送给默认的servlet
下面RootConfig类,没有写什么代码,只加入了一个扫描,一个配置类的注解。
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;@Configuration
@ComponentScan(basePackages = {"com.example.spitter"},
excludeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION, value = {EnableWebMvc.class})})
public class RootConfig {}
2. 基本的控制器
2.1 最简单的控制器
import com.liumiao.miyao.controller.SimpleController;
import org.junit.Test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;@Configuration
@EnableWebMvc
public class TestOne {@Testpublic void testSimpleController() throws Exception{SimpleController sc = new SimpleController();System.out.println(sc.simpleGet());}
}
这个其实什么也没有做,仅仅是处理了创建了这么一个类,然后调用相关方法,输出返回值。
其实我们可以启动整个项目,然后通过浏览器发起请求。
2.2 定义类级别的请求处理
我们不可能把所有的请求都放在一个方法上。
在web开发中,一般是有好几个请求类型的,分别是GET,POST,PUT,DELETE
requestMapping可以分给其他类进行处理。
@Controller
@RequestMapping(value="/")
public class SimpleController {@RequestMapping(method=RequestMethod.GET)public String simpleGet() {return "simple";}
}
我们在类的上方写了一个代码,在类中的方法又写了一个,看看两行代码做了什么。
在类的上方写这个,说明我们将/路径的请求都放在这个类里面进行处理,然后下面的simpleGet方法用来处理这个路径下的GET请求。@RequestMappping注解有一个value参数,类型为String数组,每一个元素代表一个可以接收的请求路径。
2.3 传递模型数据到视图
我们不会把所有的代码都写在一个方法里面,也不会让一个模块处理所有的事情,比如控制器模块就只会接收请求,如果需要访问数据库,那么我们还需要一个新的模块来处理请求数据的问题。控制器模块就只需要把请求需要的必要参数发送过来即可。关于数据处理的模块,我们一般称之为Repository。
然后每次我们查询数据的时候,就会将查询到的数据返回给前端,前端解析数据,显示再页面上。实际上,我们返回的数据应该经过一次处理,也就是model,这个实际上并不是我们需要关心的事情。