springmvc 全局编码_JavaWeb技术(3):浅谈Servlet、SpringMVC与SpringBoot

2bd05a25dc88ce1c8cb74f83e8c1096e.png

Servlet项目与SSM项目

我们知道,Web项目在启动时会读取web.xml中的内容,为我们生成一些东西,

web.xml中有哪些主要内容呢:

<context-param></context-param>
<listener></listener>
<filter></filter>
<servlet></servlet>
  1. 启动WEB项目的时候,容器(这个时候容器还没创建完全)首先会去读取<context-param>紧接着,容器创建一个ServletContext(application),这个web项目的所有部分都将共享这个上下文,容器以<context-param></context-param>的name作为键,value作为值,将其转化为键值对,存入ServletContext
  2. 容器创建<listener></listener>中的类实例,根据配置的class类路径<listener-class>来创建监听,注册监听器,在监听中会有初始化方法,启动Web应用时,系统调用Listener的该方法 contextInitialized(ServletContextEvent args)
  3. 接着,容器会读取<filter></filter>,根据指定的类路径来实例化过滤器

以上都是在WEB项目还没有完全启动起来的时候就已经完成了的工作。如果系统中有Servlet,则Servlet是在第一次发起请求的时候被实例化的,而且一般不会被容器销毁,它可以服务于多个用户的请求。所以,Servlet的初始化都要比上面提到的那几个要迟。总的来说,web.xml的加载顺序是: <context-param>-> <listener> -> <filter> -> <servlet>。其中,如果web.xml中出现了相同的元素,则按照在配置文件中出现的先后顺序来加载。

说了这么多web.xml的东西,这和我要讲的Servlet项目与SSM项目有什么关系?

接下来慢慢说


在SSM项目中,我们在<context-param>中放入了Spring的配置文件Spring.xml:

    <!-- 加载Spring配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/spring.xml</param-value>
    </context-param>

前面说了<context-param>中的内容会被甩到ServletContext中,而基于ServletContext的特性,所以我们猜想Spring.xml中肯定配置了Web容器全局共享的东西,比如,数据库配置,这是不是我所有Servlet都需要的东西?

    <!-- 引入属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

接下来,我们发现SSM项目中多出了一个ContextLoaderListener:

    <!-- Spring监听器 -->
    <listener>
        <description>Spring监听器</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

ContextLoaderListener监听ServletContext的创建而做出一些操作:

  1. 创建一个空的IOC:this.context = createWebApplicationContext(servletContext)
  2. 根据ServletContext中的内容找到Spring配置文件,反射创建Bean注入到IOC:configureAndRefreshWebApplicationContext(cwac, servletContext),你看,传参我还传了个servletContext进去,这不正好对应前面将Spring配置文件的位置存放在ServletContext中?
  3. 将Spring上下文存入ServletContext:servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context)

因此,可以这么说:当读取web.xml中的<context-param>时,只是放了个建值对到ServletContext中,当ServletContext创建成功时会触发Listener,Listener会读取这个建值对,然后初始化建值对中的内容,也就是Spring.xml,这之后,Spring容器就诞生了,然后把Spring容器扔到ServletContext中(扔到Web容器这个大容器中)!

ContextLoaderListener这个Listener是Spring为我们写的哦,Servlet项目可没有这个!

好,我们接着往下看,发现Spring又为我们提供了写好的Filter:

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

不止这个,还有一大堆:

df35b4975d3c4a6db180496f7d505f9f.png

f2be1518094854142e84bc5fb869598d.gif

解决Filter全站编码问题大致有装饰者模式和动态代理模式,

而既然提供了一个写好的CharacterEncodingFilter,那就直接用喽~

在Servlet的项目中,我们通常是自定义一个类去继承HttpServlet,实现doget dopost service等方法,

这三个方法可以不写业务代码,而是去起到一个路由转发的作用,将请求映射到具体的业务方法上,

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String cmd = req.getParameter("cmd");
		if ("queryAll".equals(cmd)) {
			queryAll(req, resp);
		} else if ("del".equals(cmd)) {
			del(req, resp);
		} else if ("edit".equals(cmd)) {
			edit(req, resp);
		} else if ("add".equals(cmd)) {
			add(req, resp);
		} else if ("save".equals(cmd)) {
			save(req, resp);
		}
	}

写玩这个Servlet后,我们在web.xml中配置这个Servlet,包括映射,起动顺序这些,然后我们的请求就可以映射到具体的Servlet上了;

在SSM项目中,SpringMVC为我们提供了DispatchServlet,除开必要的业务逻辑,我们已经不用写请求分发这种东西了,只需要专注我们的业务代码,因为DispatchServlet已经为我们集成了请求分发的功能,我们只需要在我们的某个类上搭上注解@Controller,然后这个类中方法打上@RequestMapping(请求路径),然后在web.xml中配置DispatchServlet,接下来我们的项目就可以使用了,请求也能正确映射到我们想映射到的方法上,

  <!--配置编码过滤器-->
  <filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/ *</url-pattern>
  </filter-mapping>
  <!--配置spring核心文件监听器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!--springMvc的核心servlet-->
  <servlet>
    <servlet-name>springMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

看了上面的内容,现在你知道Servlet项目与SSM项目的区别与联系了吧:

本质没有任何区别,都是基于web.xml,而SSM在Web容器中创建Spring容器,这个Spring小容器为我们封装了许多可以直接用的组件,方便了开发!


你如果觉得xml配置繁琐,那么还有通过java类来配置的方式,

public class MyWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) {
        AnnotationConfigWebApplicationContext context
          = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation("classpath:spring-mvc.xml");
        container.addListener(new ContextLoaderListener(context));
        ServletRegistration.Dynamic dispatcher = container
          .addServlet("dispatcher", new DispatcherServlet(context));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

但是这个WebApplicationInitializer是web.xml的代替,所以抛弃了web.xml的SpringBoot用不上这玩意儿(除非你把SpringBoot项目打成war包,发布到外部Tomcat服务器中)!


关于SpringBoot的自动配置

在SpringBoot中,关于SpringMVC的东西包括DispatchServlet都会被自动装配,所以不需要我们初始化,也不需要spring-mvc.xml,这就是自动装配的好处,

d9cc0fc3724c94a7e482f23e49887f66.png

除此之外,SpringBoot对于SpringMVC的自动配置细节在WebMvcAutoConfiguration中,有兴趣的自行了解,

如果说Servlet项目很多东西比如编码、请求分发处理器DispatchServlet这些都要我们自己写,然后自己注册,

那SSM项目就是为我们提供了这些组件,我们不用自己写,只需要注册(比如在web.xml中进行注册),

而接下来的SpringBoot则将这些东西自动装配,我们连注册的操作都不需要!

所有框架的优化与发展都是围绕扩展性、低耦合、简化配置方便开发者集中于业务代码这三点!

下面用Filter来举个例子:

反正我手长:JavaWeb技术(6):SpringMVC和SpringBoot中使用Filter的一些问题​zhuanlan.zhihu.com
5eca583937d87d880ba8a66d30827433.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值