SpringMvc in Action——构建Sprig Web应用程序

SpringMVC起步

跟踪Spring MVC请求
每当用户在Web浏览器中点击链接或者提交表单的时候,请求就开始工作了。

对请求的工作描述就像是快递投送员。请求是一个非常繁忙的家伙。从离开浏览器开始到获取响应返回,它会经历好多站。在每站会留下一些信息的同时,也会带上其他信息。
SpringMvc in Action——构建Sprig Web应用程序_第1张图片

在请求离开浏览器时①,会带有用户所请求内容的信息,至少会包含请求的URL。还可能带有其他信息,如用户提交的表单信息。
请求的第一站是Spring的DispatcherServlet。与大多数基于Java的Web框架一样,SpringMVC所有请求会通过前端控制器(front controller)Servlet。在这里一个单实例的Servlet将请求委托给应用程序的其他组件来执行实际的处理。
DispatcherSevlet的任务是将请求发送给Spring MVC 控制器。控制器controller是用于处理请求的Spring组件。在典型的应用程序中可能有多个控制器。DispatcherServlet需要知道应该将请求发送给哪个控制器。所以DispatcherServlet以会查询一个或多个处理器映射②来确定请求的下一站在哪里。处理器映射会根据请求所携带的URL信息来进行决策。
一旦选择了合适的控制器,DispatcherServlet会将请求发送给选中的控制器③。到了控制器,请求会卸下其负载(用户提交的信息)并耐心等待控制器处理这些信息。(实际上,设计良好的控制器本身只会处理很少的工作甚至不处理工作,而是将业务逻辑委托给一个或多个服务对象进行处理。
控制器在完成逻辑处理后,通常会产生一些信息,这些信息需要返回给用户并在浏览器上显示。这些信息被成为模型model。不过仅仅返回原始信息是不够的,这些信息需要以HTML的形式返回。所以信息需要发送给一个识图view,通常会是JSP。
控制器所做的最后一件事就是将模型数据打包,并且表示出用于渲染输出的识图名。它接下来会将请求连通模型和视图名发送回DispatcherServlet④。
这样控制器就不会与特定的识图相耦合,传递给DispatcherServlet的视图名并不直接表示某个特定的JSP。实际上,它甚至不能确定识图就是JSP。它仅仅传递了一个逻辑名称,这个名称会用来查找真正的识图。DispatcherServlet会使用视图解析器⑤来将视图名匹配为一个特定的视图实现

配置DispatcherServlet

DispatcherServlet是Spring MVC的核心。在这里请求会第一次接触到框架,它要负责将请求路由到其他的组件之中。

按照传统的方式,像DispatcherServlet这样的Servlet会配置在web.xml文件中,这个文件会放到应用的war包里。当然这是其中的方法之一。
另一个方法是使用Java将DispatcherServlet配置在Servlet容器中,而不会使用web.xml文件:

package spittr.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/*
 * 在Servlet3.0环境以后,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类;
 * Spring提供了这个接口的实现类SpringServletContainerInitializer,
 * 反过来这个类又去查找实现WebApplicationInitializer接口的类,并将配置任务交给他完成。
 * 而Spring3.2引入了WebApplicationInitializer的实现类AbstractAnnotationConfigDispatcherServletInitializer;
 * 而我们的SpitterWebInitializer继承了AbstractAnnotationConfigDispatcherServletInitializer,
 * 因此我们部署到Servlet3.0容器中的时候,容器会自动发现他,并用它来配置Servlet上下文。
 */

public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    /*
     * getServletMappings(),它会将一个或者多个路径映射到DispatcherServlet,
     * 本例中,他映射的是"/",这表示他会是应用默认的Servlet。他会处理进入该应用的所有请求。
     */
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
    /*
     * DispatcherServlet启动时,他会创建Spring应用的上下文,并加载配置文件或配置类中的所有生命的bean,
     * 我们要求DispatcherServlet加载应用上下文时,加载我们在WebConfig中的配置bean。
     */

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    /*
     * 但是在Spring Web中应用中,通常还会有另一个上下文,他是由ContextLoaderListener创建的,
     * 我们希望DispatcherServlet加载Web组件的bean,如控制器,视图解析器以及处理器映射,
     * ContextLoaderListener要加载应用中的其他bean,即RootConfig来实现。
     */

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

}

各个方法的作用已经在注释中写的非常清楚了。
那么WebConfig.class是怎么样的呢:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {}

当然这个赤裸裸的程序可以运行,它的确也能启动SpringMVC,但是还有不少问题要解决:

  • 没有配置视图解析器,这样的话Spring会默认查找ID与视图名称匹配的bean。
  • 没有启动组件扫描,这样的话Spring只能显示声明在这个控制器。
  • Dispatcher会映射为应用的默认Servlet,所有请求都会通过它,事实上如静态的资源请求(如图片或样式表)不需要通过它。

所以,我们需要如下修改:

package spittr.config;

import org.springframework.context.annotation.Bean;
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;

@Configuration
@EnableWebMvc
@ComponentScan("spittr.web")
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public ViewResolver viewResolver() {
    //此处配置视图解析器,用bean进行依赖注入
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    //配置静态资源的处理
        configurer.enable();
    }
}

目前我们还没彻底了解RootConfig.class(因为本章聚焦于Web开发),所以现在的RootConfig很简单:

package spittr.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;


@Configuration
@ComponentScan(basePackages = {"spittr"},
    excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION)})
public class RootConfig {

}

我们暂且不用知道excludeFilters里面到底是什么意思。
此时最大的问题是,我们要构建的应用到底是什么。

Spittr应用简介

这个Spittr可不是一个开发术语,而是我们希望构建的应用的名字,这个应用和微博Twitter很类似,我们使用Spring来构建这个应用。
Spittr应用有两个基本的领域概念:Spitter(用户)和Spittle(用户的微博消息)。

现在我们已经配置了DispatcherServlet,启用了基本的Spring MVC组件并确定了目标应用。让我们进入下一个内容,使用Spring MVC控制器处理。

搭建结果:
https://github.com/BonjourMondo/SpringMvcBaseSetting

你可能感兴趣的:(SpringMvc in Action——构建Sprig Web应用程序)