【小家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。

相关文章
|
15天前
|
数据采集 前端开发 Java
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
23 3
|
15天前
|
存储 前端开发 Java
会话锦囊:揭示Spring MVC如何巧妙使用@SessionAttributes
会话锦囊:揭示Spring MVC如何巧妙使用@SessionAttributes
14 1
|
15天前
|
前端开发 Java Spring
数据之桥:深入Spring MVC中传递数据给视图的实用指南
数据之桥:深入Spring MVC中传递数据给视图的实用指南
31 3
|
25天前
|
前端开发 安全 Java
使用Java Web框架:Spring MVC的全面指南
【4月更文挑战第3天】Spring MVC是Spring框架的一部分,用于构建高效、模块化的Web应用。它基于MVC模式,支持多种视图技术。核心概念包括DispatcherServlet(前端控制器)、HandlerMapping(请求映射)、Controller(处理请求)、ViewResolver(视图解析)和ModelAndView(模型和视图容器)。开发流程涉及配置DispatcherServlet、定义Controller、创建View、处理数据、绑定模型和异常处理。
使用Java Web框架:Spring MVC的全面指南
|
XML Java 数据格式
[Spring实战系列](19)Servlet不同版本之间的区别
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/51076823 1.
1168 0
|
30天前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
44 0
|
2月前
|
缓存 Java Maven
Spring Boot自动配置原理
Spring Boot自动配置原理
48 0
|
1月前
|
缓存 安全 Java
Spring Boot 面试题及答案整理,最新面试题
Spring Boot 面试题及答案整理,最新面试题
113 0
|
1月前
|
前端开发 搜索推荐 Java
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革
|
18天前
|
前端开发 Java 应用服务中间件
Springboot对MVC、tomcat扩展配置
Springboot对MVC、tomcat扩展配置