【小家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月前
|
XML 前端开发 Java
【Spring】@RequestMapping、@RestController和Postman
【Spring】@RequestMapping、@RestController和Postman
26 2
【Spring】@RequestMapping、@RestController和Postman
|
2月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
2月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
58 2
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
2月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
138 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
3月前
|
XML 缓存 前端开发
springMVC02,restful风格,请求转发和重定向
文章介绍了RESTful风格的基本概念和特点,并展示了如何使用SpringMVC实现RESTful风格的请求处理。同时,文章还讨论了SpringMVC中的请求转发和重定向的实现方式,并通过具体代码示例进行了说明。
springMVC02,restful风格,请求转发和重定向
|
前端开发 Java Spring
SpringMVC之Controller查找(Spring4.0.3/Spring5.0.4源码进化对比)
0 摘要 本文从源码层面简单讲解SpringMVC的处理器映射环节,也就是查找Controller详细过程 1 SpringMVC请求流程 Controller查找在上图中对应的步骤1至2的过程 SpringMVC详细运行流程图 2 SpringMVC初始化过程 2.1 先认识两个类 Handler 通常指用于处理request请求的实际对象,可以类比 XxxController。
1313 0
|
3月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
184 2
|
19天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
29 2
 SpringBoot入门(7)- 配置热部署devtools工具