【小家Spring】Spring MVC控制器中Handler的四种实现方式:Controller、HttpRequestHandler、Servlet、@RequestMapping(下)

简介: 【小家Spring】Spring MVC控制器中Handler的四种实现方式:Controller、HttpRequestHandler、Servlet、@RequestMapping(下)

Servlet方式


Servlet是我们很熟悉的一个类。Spring MVC也是对这种实现方式提供了支持,也把它能够当作一个Spring MVC的Bean,作为一个Handler来实现的~~


@Controller("/servletController")
public class ServletController extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("this my servlet controller");
    }
}


小细节:即使你使用了@EnableWebMvc,Spring MVC默认也不会给你注册SimpleServletHandlerAdapter这个适配器(其余三个都给注册了),因此此处我们自己注册一下即可。


@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
  // 让支持Servlet这种Handler的方式~~你 SpringMVC默认是不予支持的
    @Bean
    public SimpleServletHandlerAdapter simpleServletHandlerAdapter() {
        return new SimpleServletHandlerAdapter();
    } 
}


这样子是也是能够正常访问的,因为它就是个Handler了。

从Spring MVC的意图中我们也可以看出,Spring并不推荐我们再使用源生的Servlet来处理请求了~~~


@RequestMapping注解方式


是当下最为广泛使用的方式。

这种方式此处就不做介绍了,不介绍并不是它不重要,反而是它太重要了此处篇幅不够,比如它的数据绑定可以完全屏蔽Servlet源生的API,为后续的WebFlux做了充分的准备~后面还有大篇幅讲解它相关的内容


小知识


  1. Spring2.5之前,我们都是通过实现Controller接口或其实现来定义我们的处理器类。显然现在已经不推荐这么做了
  2. Spring2.5引入注解式处理器支持,通过@Controller 和 @RequestMapping注解定义我们的处理器类。并且有一批注解都是这个时候出来的:

      1. @RequestMapping:请求到处理器功能方法的映射规则;

      2. @RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;

      3. @ModelAttribute:请求参数到命令对象的绑定;

      4. @SessionAttributes:用于声明session级别存储的属性,放置在处理器类上,通常列出模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session中;

      5. @InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;

3.Spring3.0引入RESTful架构风格支持(通过@PathVariable注解和一些其他特性支持),且又引入了更多的注解支持:

      1. @CookieValue:cookie数据到处理器功能处理方法的方法参数上的绑定;

      2. @RequestHeader:请求头(header)数据到处理器功能处理方法的方法参数上的绑定;

      3. @RequestBody:请求的body体的绑定(通过HttpMessageConverter进行类型转换);

      4. @ResponseBody:处理器功能处理方法的返回值作为响应体(通过HttpMessageConverter进行类型转换);

      5. @ResponseStatus:定义处理器功能处理方法/异常处理器返回的状态码和原因;

      6. @ExceptionHandler:注解式声明异常处理器;

      7. @PathVariable:请求URI中的模板变量部分到处理器功能处理方法的方法参数上的绑定,从而支持RESTful架构风格的URI;


4.Spring3.1使用新的HandlerMapping 和 HandlerAdapter来支持@Contoller和@RequestMapping注解处理器。

      1. 处理器映射RequestMappingHandlerMapping 和 处理器适配器RequestMappingHandlerAdapter组合

      2. 对应代替了Spring2.5开始有的DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter


命令对象/模式:来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化。用于“行为请求者”与“行为实现者”解耦,可实现二者之间的松耦合,以便适应变化。分离变化与不变的因素。一般可以实现命令的执行和撤销操作。 比如:遥控器给灯可以发送命令:开灯

总结


在使用Spring MVC的开发过程中,Handler(就是Controller)是我们需要手动开发的主要内容(其余的都是Spring MVC自动去处理的,开发者基本不用关心~),注解的配置方式比较固定,可以限定请求方式,请求映射到方法级,基本可以满足我们的日常需求。


但是如果知道这些controller的模式,比如UrlFilenameViewController这种,可以不用开发或者非常少量开发的情况下,极其快速的定位到handler到页面的映射关系,也是大大的提升了我们的效率有木有~


附:

Spring MVC中对静态资源的访问


1.当静态资源放在webapp下面的时候,可直接通过浏览器访问,不需要配置映射,安全性略低,对应的访问效率就略高。


但是静态资源若很多,访问频率很高的话,强烈建议放在静态服务器或者CDN上,不要放在tomcat里,这不是它擅长的


2.WEB-INF是Java的WEB应用的安全目录。所谓安全就是客户端无法直接访问,只有服务端可以访问的目录(所以理论上必须经过controller)


对于第一点这里需要强调一下:其实这么说是有问题的。因为我们一般会把DispatcherServlet映射为 /从而拦截所有的请求(包括静态资源的请求),所以如果直接访问就找不到Handler还是会报404的。后面会解释原因~


那么现在问题就来了,Spring MVC下怎么让访问WEB-INF下面的静态资源呢?

比如现在我有如下静态资源:

image.png


通过浏览器直接访问肯定是会404的,但是因为它是html文件,我们也不能通过controller直接转发,那肿么办呢?


如果我们之前的Spring MVC项目是基于xml的,相信很多人都看到过如下的配置项:


<mvc:default-servlet-handler/>
...
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/html/**" location="/html/"/>
// 备注两种只需要配其一,其中<mvc:resources />是被推荐的方式


那么现在我们是java代码的方式,怎么弄呢?


DefaultServlet方式:DefaultServletHttpRequestHandler


对应xml的<mvc:default-servlet-handler/>方式。

此时会注册一个默认的Handler:DefaultServletHttpRequestHandler,这个Handler是用来处理静态文件的。(tomcat等容器里都一个名字为defaultServlet的Servlet来默认处理这些,当然默认名称各个容器都不一样,你可以自己指定)


当我们的请求倒带DispatcherServelt,当并没有找到合适的Handler来处理请求时,就会交给DefaultServletHttpRequestHandler来处理。


注意注意注意:这里的静态资源是放置在web根目录下,而非WEB-INF下,若在该目录下只能下面方案解决~


简单的举个例子描述下这个情况:

在webroot目录下有一个图片:1.png。我们知道的是:Servlet规范中web根目录(webapp目录)下的文件我们是可以直接访问的(不需要经过Servlet处理)。

但是但是但是由于DispatcherServlet配置了映射路径是:/ ,它几乎把所有的请求都拦截了,从而导致1.png 访问不到。这时注册一个DefaultServletHttpRequestHandler就可以解决这个问题。


DispatcherServlet破坏了Servlet的这个特性规范(根目录下的文件可以直接访问),DefaultServletHttpRequestHandler是帮助回归这个特性的。可谓也没啥损失(只是Spring MVC默认并没有开启哦~~)


因此若要开启此特性,我们只需要这么做即可:

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
        //configurer.enable("default");
    }
}

这样非WEB-INF下的静态资源就可以正常反问啦~


ResourceHandler方式:ResourceHttpRequestHandler


这种对应的是XML中的<mvc:resources />方式。

我们Java代码的方式一般都这么做:

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resource/**").addResourceLocations("/WEB-INF/static/");
        // 备注这里addResourceLocations(“file:D:/”)这样都是支持的~~~~~
    }
}

这样只要我们访问路径中是匹配/resource/**的,那就能够访问了。比如上面截图中的1.html我们这样访问:http://localhost:8080/demo_war_war/resource/1.html就能正常访问到了。(相当于路径中给加个/resource/)


那它的基本原理是什么呢?


它的原理也还行,就是向容器注册了一个ResourceHttpRequestHandler,它是一个HttpRequestHandler。关于HttpRequestHandler前面文章是有重点讲述的,具体参考:

【小家Spring】Spring MVC控制器中Handler的四种实现方式:Controller、HttpRequestHandler、Servlet、@RequestMapping


DefaultServletHttpRequestHandler它也是一个HttpRequestHandler


/ 和 /*有什么区别?


/会拦截除了jsp以外的所有url,/* 会拦截所有url,包括jsp。


例如:在webroot下面有一个test.jsp,当DispatcherServlet 配置映射/ 时,浏览器输入:http://localhost:8080/test.jsp 这个jsp是可以直接访问的,并且不经过DispatcherServlet ;而当DispatcherServlet 配置映射/* 时,这个请求就会被DispatcherServlet 拦截。


Spring Boot中静态资源的访问


它就比Spring稍微简单点,因为Boot已经做好了很多事。

在 Spring Boot 中,默认情况下,一共有5个位置可以放静态资源,五个路径分别是如下5个:


  1. classpath:/META-INF/resources/
  2. classpath:/resources/
  3. classpath:/static/
  4. classpath:/public/
  5. /


前四个目录好理解,分别对应了resources目录下不同的目录,第5个 / 是啥意思呢?稍微解释下:在 Spring Boot 项目中,默认是没有 webapp 这个目录的,当然我们也可以自己添加(例如在需要使用JSP的时候),这里第5个 / 其实就是表示 webapp 目录中的静态资源也不被拦截。如果同一个文件分别出现在五个目录下,那么优先级也是按照上面列出的顺序


所以在SpringBoot中问问静态资源默认情况下我们并不需要做什么。

具体原理参考类:ResourceProperties,它定义了这5个路径以及顺序~

WebMvcProperties.staticPathPattern属性值定义了访问的url的pattern。

相关文章
|
2月前
|
前端开发 Java Spring
Spring MVC核心:深入理解@RequestMapping注解
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的核心,它将HTTP请求映射到控制器的处理方法上。本文将深入探讨`@RequestMapping`注解的各个方面,包括其注解的使用方法、如何与Spring MVC的其他组件协同工作,以及在实际开发中的应用案例。
49 4
|
2月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
155 2
|
2月前
|
前端开发 Java 开发者
Spring MVC中的控制器:@Controller注解全解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序控制层的核心。它不仅简化了控制器的定义,还提供了灵活的请求映射和处理机制。本文将深入探讨`@Controller`注解的用法、特点以及在实际开发中的应用。
120 0
|
4月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
|
3月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
68 2
|
3月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
242 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
5月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
5月前
|
前端开发 Java Spring
Java 新手入门:Spring Boot 轻松整合 Spring 和 Spring MVC!
Java 新手入门:Spring Boot 轻松整合 Spring 和 Spring MVC!
84 0
|
6月前
|
前端开发 Java 应用服务中间件
Spring Boot 2.x 嵌入式 Servlet 容器
Spring Boot使用内嵌Tomcat,默认端口8080,可通过`application.properties`配置端口、上下文路径等。配置方式有两种:1) 直接在配置文件中添加`server.port`和`server.servlet.context-path`;2) 创建`WebServerFactoryCustomizer` Bean来自定义配置,如设置端口`factory.setPort(8083)`,这种方式优先级更高。
|
2天前
|
Java 测试技术 应用服务中间件
Spring Boot 如何测试打包部署
本文介绍了 Spring Boot 项目的开发、调试、打包及投产上线的全流程。主要内容包括: 1. **单元测试**:通过添加 `spring-boot-starter-test` 包,使用 `@RunWith(SpringRunner.class)` 和 `@SpringBootTest` 注解进行测试类开发。 2. **集成测试**:支持热部署,通过添加 `spring-boot-devtools` 实现代码修改后自动重启。 3. **投产上线**:提供两种部署方案,一是打包成 jar 包直接运行,二是打包成 war 包部署到 Tomcat 服务器。
24 10
下一篇
开通oss服务