MVC(Model-View-Controller)模式。

请求在Spring MVC 的一个过程

  1. 来自客户的请求,带有用户所要请求的内容信息。
  2. 第一站到达,DispatcherServlet(前端控制器),它去 查询处理器映射(handler mapping)。
  3. 通过 handler mapping 来确定 对应的控制器。处理器映射会根据请求所携带的URL信息来进行决策。把结果反馈给DispatcherServlet。
  4. 选择了适合的控制器(Controller),DispatcherServlet会将请求发送给选中的控制器,把所有携带的信息交给控制器 等待其处理结果。
  5. 控制器完成逻辑处理后,通常会产生一些信息,这些信息被称为模型
  6. 控制器所作的最后一件事就是将模型数据打包,并且标示出用于渲染输出的视图名。将将模型和视图名发送回DispacherServlet。
  7. dispatcherServlet 会使用 视图解析器(View resolver),把视图名与真正的视图进行匹配。
  8. 此时 dispatcherServlet 已经知道 视图 和 模型,最后一个站是 视图实现。
  9. 通过响应对象传递给 客户端。

搭建 Spring MVC

配置 DispatcherServlet

Sevlet 配置方式:一种是使用 web.xml。另一种是配置 DispatcherServlet。

public class SpittrWebAppInit extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    // 指定 配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        // 将 dispatcher Servlet 映射到 “/”
        return new String[]{"/"};
    }
}

扩展 AbstractAnnotationConfigDispatcherServletInitializer 的任意类都会自动配置 DispatcherServlet 和 Spring Application Context,Spring 的应用上下文会位于应用程序的Servlet上下文中。

了解 AbstractAnnotationConfigDispatcherServletInitializer 类:

  • getServletMappings(),将一个或多个路径映射到 DispatcherServlet 上

DispatcherServlet 和 Servlet监听器的关系。

  • DispatcherServlet 启动时,它会创建 Spring ApplicationContext ,并 加载配置文件或配置类中所声明的bean。
  • getServletConfigClasses()方法中,我们要求 DispatcherServlet 加载应用上下文时,使用定义在WebConfig配置类中的bean。
  • 在 web 应用中,还有另一个 应用上下文是由ContextLoaderListener 创建的。
  • DispatcherServlet 加载包含 Web组件的bean,如控制器、视图解析器以及处理器映射等
  • ContextLoaderListener 要加载应用中的其他 bean,通常是驱动应用后端的中间层和数据层组件。
  • getServletConfigClasses() 方法返回配置类 会用来定义DispatcherSevlet 应用上下文中的 bean。
  • getRootConfigClasses() 方法返回的配置类 会用来配置 ContextLoaderListener创建的应用上下文中的bean。
  • Tomcat 要求 7.0 或 更高的版本。

启用 Spring MVC

@Configuration
@EnableWebMvc
@ComponentScan("beans")
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();
    }
}
  • @EnableWebMvc 启用 Spring MVC。
  • InternalResourceViewResolver负责查找 JSP 文件,并在视图名称 上加一个特定的前缀和后缀。
  • DefaultServletHandlerConfigurerenable()方法,可以让 DispatcherServlet 将对 静态资源的请求转发到Servlet容器中默认的Servlet 上,而不是使用 DispatcherServlet 本身来处理此类请求。
@Configuration
@ComponentScan(basePackages = {"com.test"},excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)
})
public class RootConfig {
}

编写控制器

@Controller
@RequestMapping(value = "/")
public class HelloController {

    @RequestMapping(method = RequestMethod.GET)
    public String showView(){
        return "welcome";
    }

    @RequestMapping(value = "/hello", method = RequestMethod.POST)
    public ModelAndView handleRequest(HttpServletRequest request) throws UnsupportedEncodingException {
        request.setCharacterEncoding("utf-8");
        String name = request.getParameter("name");

        ModelAndView view = new ModelAndView("result","name",name);
        return view;
    }
}
  • @RequestMapping 注解,声明了它们所要处理的请求。
  • 在 类级别上时,会应用到类级别的所有处理方法上。
  • value 属性指明这个方法所要处理的路径。
  • method 属性细化了它所处理的 Http 方法。

传递模型数据 到视图中

@RequestMapping(method = RequestMethod.GET)
public String showView(Model model){
    model.addAttribute("title");
    return "welcome";
}
  • Model 实际是一个 map ,它会传递给视图。
  • 当调用 addAttribute() 方法并且不指定 key 的时候,那么 key 会根据值对象 进行推断确定。
  • 可以使用 Map 替换
@RequestMapping(value = "/test", method = RequestMethod.GET)
public List<String> show(){ 
    return Repository.findList();
}
  • 处理方法 返回 是对象 或 集合时,这个值会放到模型中,key 根据类型 推断。
  • 逻辑视图的名称 将会根据请求路径推断得出。

接受请求的输入

多种方式 将客户端数据传送给 控制器的处理方法:

  • 查询参数
  • 表单参数
  • 路径变量

处理查询参数

为了处理这样的请求:/spittles?max=23&count=3;

@RequestMapping(value = "/test", method = RequestMethod.GET)
public List<String> show(@RequestParam("max") int max,@RequestParam("count") int count){
}
  • @RequestParam() 把参数中对应值 赋给 对应的 变量
  • value 属性 设置 参数名,请求中的参数名。
  • defaultValue 属性:在请求中不存在 指定参数时 ,使用默认值。

通过路径参数接受输入

为了处理像:/results/123 的请求。

@RequestMapping(value = "/result/{id}", method = RequestMethod.GET)
public List<String> show(@PathVariable("id") int id){
    return null;
}
  • @PathVariable() 注解,表明 把占位符id 对应的值,传递给 变量 id。

处理表单

为了处理:<form> 里面的 内容。

  • 处理放的参数 可以是 封装的对象。
  • 也可以在 HttpServletRequest 中获得
@RequestMapping(value = "/hello", method = RequestMethod.POST)
public String handleRequest(HttpServletRequest request) throws UnsupportedEncodingException {
    String title = request.getParameter("title");// 通过 每个标签 对应 name 获取。
    return "redirect:/result/123";
}
  • 返回字符串中
  • 前缀是:redirect: 将其 解析为 重定向 规则。
  • 前缀是:forward: 请求将会前往 指定的URL路径,而不再是重定向。
  • 只是返回字符串 ,表示 视图名。