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

本文深入探讨了SpringMVC框架的运作机制,详细讲解了请求如何从浏览器出发,经过DispatcherServlet,通过处理器映射到达控制器,再由控制器处理请求并将模型数据发送至视图展示的过程。同时,文章介绍了如何配置DispatcherServlet,包括使用Java配置方式替代传统的web.xml配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringMVC起步

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

对请求的工作描述就像是快递投送员。请求是一个非常繁忙的家伙。从离开浏览器开始到获取响应返回,它会经历好多站。在每站会留下一些信息的同时,也会带上其他信息。
在这里插入图片描述

在请求离开浏览器时①,会带有用户所请求内容的信息,至少会包含请求的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

电动汽车数据集:2025年3K+记录 真实电动汽车数据:特斯拉、宝马、日产车型,含2025年电池规格和销售数据 关于数据集 电动汽车数据集 这个合成数据集包含许多品牌和年份的电动汽车和插电式车型的记录,捕捉技术规格、性能、定价、制造来源、销售和安全相关属性。每一行代表由vehicle_ID标识的唯一车辆列表。 关键特性 覆盖范围:全球制造商和车型组合,包括纯电动汽车和插电式混合动力汽车。 范围:电池化学成分、容量、续航里程、充电标准和速度、价格、产地、自主水平、排放、安全等级、销售和保修。 时间跨度:模型跨度多年(包括传统和即将推出的)。 数据质量说明: 某些行可能缺少某些字段(空白)。 几个分类字段包含不同的、特定于供应商的值(例如,Charging_Type、Battery_Type)。 各列中的单位混合在一起;注意kWh、km、hr、USD、g/km和额定值。 列 列类型描述示例 Vehicle_ID整数每个车辆记录的唯一标识符。1 制造商分类汽车品牌或OEM。特斯拉 型号类别特定型号名称/变体。型号Y 与记录关联的年份整数模型。2024 电池_类型分类使用的电池化学/技术。磷酸铁锂 Battery_Capacity_kWh浮充电池标称容量,单位为千瓦时。75.0 Range_km整数表示充满电后的行驶里程(公里)。505 充电类型主要充电接口或功能。CCS、NACS、CHAdeMO、DCFC、V2G、V2H、V2L Charge_Time_hr浮动充电的大致时间(小时),上下文因充电方法而异。7.5 价格_USD浮动参考车辆价格(美元).85000.00 颜色类别主要外观颜色或饰面。午夜黑 制造国_制造类别车辆制造/组装的国家。美国 Autonomous_Level浮点自动化能力级别(例如0-5),可能包括子级别的小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值