《Spring实战》学习笔记-第五章:构建Spring web应用

本文详细介绍了Spring MVC的运作原理,包括DispatcherServlet、控制器、模型数据与视图解析。通过示例展示了如何配置DispatcherServlet、编写控制器、处理输入请求以及表单数据。此外,还涉及了控制器测试、类层级的请求处理和模型数据传递。文章以Spring实战第四版为依据,讲解了Spring MVC的基础知识和实践技巧。
摘要由CSDN通过智能技术生成

之前一直在看《Spring实战》第三版,看到第五章时发现很多东西已经过时被废弃了,于是现在开始读《Spring实战》第四版了,章节安排与之前不同了,里面应用的应该是最新的技术。

本章中,将会接触到Spring MVC基础,以及如何编写控制器来处理web请求,如何通明地绑定请求参数到业务对象上,同时还可以提供数据校验和错误处理的功能。

Spring MVC初探

跟踪Spring MVC请求

请求会由DispatcherServlet分配给控制器(根据处理器映射来确定),在控制器完成处理后,接着请求会被发送给一个视图来呈现结果

在请求离开浏览器时,会带有用户所请求内容的信息,例如请求的URL、用户提交的表单信息。

请求旅程的第一站是Spring的DispatcherServlet。Spring MVC所有的请求都会通过一个前端控制器Servlet。前端控制器是常用的Web应用程序模式,在这里一个单实例的Servlet将请求委托给应用程序的其他组件来执行实际的处理。在Spring MVC中,DispatcherServlet 就是前端控制器。

DispatcherServlet的任务是将请求发送给Spring MVC**控制器。控制器是一个用于处理请求的Spring组件。在典型的应用程序中可能会有多个控制器, Dispatcher Servlet需要知道应该将请求发送给哪个控制器。所以DispatcherServlet会查询一个或多个处理器映射来确定请求的下一站在哪里。处理器映射**会根据请求所携带的URL信息来进行决策。

一旦选择了合适的控制器,DispatcherServlet会将请求发送给选中的控制器。到达了控制器,请求会卸下其负载(用户提交的信息)并等待控制器处理这些信息(实际上,设计良好的控制器本身只处理很少甚至不处理工作,而是将业务逻辑委托给个或多个服务对象)。

控制器在完成逻辑处理后通常会产生一些信息,这些信息需要返回给用户并在浏览器上显示。这些信息被称为模型(Model)。不过仅仅给用户返回原始的信息是不够的–这些信息需要以用户友好的方式进行格式化,一般是HTML。所以,信息需要发送给—个视图(View),通常会是JSP。

控制器所做的最后一件事是将模型数据打包,并且标示出用于渲染输出的视图名称。它接下来会将请求连同模型和视图名称发送回DispatcherServlet。

这样,控制器就不会与特定的视图相耦合,传递给DispatcherServlet的视图名称并不直接表示某个特定的JSP。它仅仅传递了一个逻辑名,这个名字将会用来查找用来产生结果的真正视图。DispatcherServlet将会使用视图解析器来将逻辑视图名匹配为一个特定的视图实现。

既然DispatcherServlet已经知道由哪个视图渲染结果,那么请求的任务基本上也就完成了。它的最后一站是视图的实现(可能是JSP),在这里它交付模型数据。请求的任务就完成了。视图将使用模型数据渲染输出,并通过这个输出将响应对象传递给客户端。

搭建Spring MVC

配置DispatcherServlet

DispatcherServlet是Spring MVC的核心,它负责将请求分发到其他各个组件。

在旧版本中,DispatcherServlet之类的servlet一般在web.xml文件中配置,该文件一般会打包进最后的war包种;但是Spring3引入了注解,我们在这一章将展示如何基于注解配置Spring MVC。

注意:
在使用maven构建web工程时,由于缺少web.xml文件,可能会出现web.xml is missing and <failOnMissingWebXml> is set to true这样的错误,那么可以通过在pom.xml文件中添加如下配置来避免这种错误:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
    </plugins>
</build>

既然不适用web.xml文件,你需要在servlet容器中使用Java配置DispatcherServlet,具体的代码列举如下:

package spittr.config;

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

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
   

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

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

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

}

任意继承自AbstractAnnotationConfigDispatcherServletInitializer的类都会被自动用来配置DispatcherServlet,这个类负责配置DispatcherServlet初始化Spring MVC容器和Spring容器

SpittrWebAppInitializer重写了三个方法,getRootConfigClasses()方法用于获取Spring应用容器的配置文件,这里我们给定预先定义的RootConfig.class;getServletConfigClasses()负责获取SpringMVC应用容器,这里传入预先定义好的WebConfig.class;getServletMappings()方法负责指定需要由DispatcherServlet映射的路径,这里给定的是”/”,意思是由DispatcherServlet处理所有向该应用发起的请求。

两种应用上下文

当DispatcherServlet启动时,会创建一个Spring应用上下文并且会加载配置文件中声明的bean,通过getServletConfigClasses()方法,DispatcherServlet会加载WebConfig配置类中所配置的bean。

在Spring web应用中,通常还有另外一种应用上下文:ContextLoaderListener

DispatcherServlet用来加载web组件bean,如控制器(controllers)、视图解析器(view resolvers)以及处理器映射(handler mappings)等。而ContextLoaderListener则用来加载应用中的其他bean,如运行在应用后台的中间层和数据层组件。

AbstractAnnotationConfigDispatcherServletInitializer会同时创建DispatcherServlet和ContextLoaderListener。getServletConfigClasses()方法返回的@Configuration类会定义DispatcherServlet应用上下文的bean。同时,getRootConfigClasses()返回的@Configuration类用来配置ContextLoaderListener上下文创建的bean。

相对于传统的web.xml文件配置的方式,通过AbstractAnnotationConfigDispatcherServletInitializer来配置DispatcherServlet是一种替代方案。需要注意的是,这种配置只适用于Servlet 3.0,例如Apache Tomcat 7或者更高。

激活Spring MVC

正如有多种方式可以配置DispatcherServlet,激活Spring MVC组件也有不止一种方法。一般的,都会通过XML配置文件的方式来配置Spring,例如可以通过<mvc:annotation-driven>来激活基于注解的Spring MVC。

最简单的配置Spring MVC的一种方式是通过@EnableWebMvc注解:

package spittr.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
public class WebConfig {
   

}

@Configuration表示这是Java配置类;@EnableWebMvc注解用于启动Spring MVC特性。

这样就可以激活Spring MVC了,但是还有其他一些问题:
- 没有配置视图解析器(view resolvers),这种情况下,Spring会默认使用BeanNameViewResolver,它会通过寻找那些与视图id匹配的bean以及实现了View接口的类进行视图解析;
- 没有激活组件扫描:这样Spring会寻找配置中明确声明的任意控制器;
- DispatcherServlet会处理所有的请求,包括静态资源请求,如图片和样式(这些往往不是我们想要的)。

因此,需要为WebConfig增加一些配置:

package spittr.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.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan("spitter.web") // 激活Spring MVC
public class WebConfig extends WebMvcConfigurerAdapter {
   

    // 配置一个JSP视图解析器
    @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();
    }
}

首先需要注意的是,WebConfig使用了@ComponentScan注解,因此会在spitter.web包下扫描寻找组件,这些组件包括使用@Controller进行注解的控制器。这样就不再需要在配置类中显式地声明其他控制器。

接下来,添加了一个ViewResolverbean,即InternalResourceViewResolver。它通过匹配符合设置的前缀和后缀的视图来用来寻找对应的JSP文件,比如视图home会被解析为/WEB-INF/views/home.jsp。这里的三个函数的含义依次是:setPrefix()方法用于设置视图路径的前缀;setSuffix()用于设置视图路径的后缀,即如果给定一个逻辑视图名称——”home”,则会被解析成”/WEB-INF/views/home.jsp”; setE

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值