Spring MVC之HandlerAdapter

1. 前言

Spring MVC没有限制Handler的类型,Handler可以以任何形式存在,内置的Handler就有四种类型:

  • HandlerMethod
  • Controller
  • HttpRequestHandler
  • Servlet

开发者还可以自定义Handler,面对各种各样类型的Handler,Spring MVC再也不能简单直接的面向接口编程了。于是Spring MVC采用了适配器模式,通过不同的适配器去协调不同的Handler工作,适配器本身是很容易抽象成接口的,所以Spring MVC又可以愉快的面向接口编程了。

2. HandlerAdapter

public interface HandlerAdapter {/*** 适配器是否支持给定的Handler?*/boolean supports(Object handler);/*** 协调Handler处理请求,返回结果*/@NullableModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;/*** 获取资源最后修改的时间戳,以确定是否返回304让浏览器使用缓存*/long getLastModified(HttpServletRequest request, Object handler);}

HandlerAdapter接口定义很简单,Spring MVC首先会遍历所有的HandlerAdapter,依次通过supports()判断当前适配器是否支持处理给定的Handler?如果支持,那么就调用handle()让适配器去协调Handler处理请求,返回结果。

DispatcherServlet获取Handler对应的适配器:

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {if (this.handlerAdapters != null) {for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(handler)) {return adapter;}}}throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

让适配器去处理请求,返回ModelAndView:

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

3. 内置适配器

Spring MVC内置了四种类型的Handler,对应的也就存在四种HandlerAdapter**。**

HandlerHandlerAdapter
HandlerMethodRequestMappingHandlerAdapter
ControllerSimpleControllerHandlerAdapter
HttpRequestHandlerHttpRequestHandlerAdapter
ServletSimpleServletHandlerAdapter

对于后面三个适配器,实现上都很简单,因为只需要把HttpServletRequestHttpServletResponse对象透传下去,让子类自己去处理请求就好了,适配器本身并不需要处理过多复杂的事情。以SimpleControllerHandlerAdapter为例:

public class SimpleControllerHandlerAdapter implements HandlerAdapter {@Overridepublic boolean supports(Object handler) {// 只要Handler是Controller类型,就支持处理return (handler instanceof Controller);}@Override@Nullablepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 转换类型,把request和response透传给Handler处理即可return ((Controller) handler).handleRequest(request, response);}@Overridepublic long getLastModified(HttpServletRequest request, Object handler) {if (handler instanceof LastModified) {return ((LastModified) handler).getLastModified(request);}return -1L;}
}
  • supports()判断很简单,只要Handler属于Controller类型即可。
  • handle()更简单了,把request和response透传给Handler处理即可。

真正复杂的是RequestMappingHandlerAdapter,也就是被@RequestMapping注解标记的方法,Handler对应的类是org.springframework.web.method.HandlerMethod。它的处理过程主要有三步:

  1. 准备HandlerMethod需要的参数。
  2. 反射调用目标方法,处理请求。
  3. 将返回结果封装成ModelAndView。

都使用Spring MVC了,相信大家也不会自己去操作HttpServletRequest获取请求参数了,更多的是使用@RequestParam@PathVariable@RequestHeader@RequestBody等注解让Spring MVC绑定参数,所以光是第一步准备参数就非常复杂,值得另起篇幅单独记录;第二步反而是最简单的,直接反射调用目标方法即可;第三步将返回结果封装成ModelAndView,现在基本都前后端分离了,一般通过@ResponseBody直接响应JSON即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/595028.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

18、BLIP

简介 github BLIP提出了一种基于预训练的方法,通过联合训练视觉和语言模型来提升多模态任务的性能。 BLIP(Bootstrapping Language-Image Pretraining)是salesforce在2022年提出的多模态框架,是理解和生成的统一,引入了跨模态的编码器和解码…

Linux嵌入式配置/etc/profile文件

Linux嵌入式配置/etc/profile文件 void mountMouse() {QFile profile("/etc/profile");if (profile.exists()) {if (profile.open(QIODevice::ReadWrite)) {QByteArray fileData(profile.readAll());if (!fileData.contains("tslib:/dev/input/event0 intellim…

词嵌入位置编码的实现(基于pytorch)

背景介绍 在transformers架构当中,对于词向量的输入需要加上原本词对应的位置信息,作为输入到模型中训练的input,那具体的位置编码如何实现呢?本篇博客就跟大家一起分享一下对应的步骤 位置编码的公式 对于词向量的位置编码的方…

数据结构复杂

顺序存储与链式存储优缺点 顺序存储: 优点: 顺序存储结构利用一段连续的存储单元依次存储线性表的数据元素,使得线性表的数据元素在内存中是紧凑排列的,从而减少了存取时间。顺序存储结构在内存中占用的空间是连续的&#xff0c…

十进制转二进制、八进制、十

❤ 厾罗 十进制转二进制、八进制、十 以下代码用于实现十进制转二进制、八进制、十六进制: 实例(Python 3.0) # -*- coding: UTF-8 -*- # Filename : test.py # author by : www.dida100.com # 获取用户输入十进制数 dec int(input("输入数字&…

西电期末1017.有序序列插值

一.题目 二.分析与思路 简单题。主要考察简单的排序&#xff0c;最后的插入数据同样不用具体实现&#xff0c;只需在输出时多输出一下即可&#xff0c;注意顺序&#xff01;&#xff01; 三.代码实现 #include<bits/stdc.h>//万能头 int main() {int n;scanf("%d…

HTML5+CSS3+Vue小实例:彩色圆环溶解加载动画

实例:彩色圆环溶解加载动画 技术栈:HTML+CSS+Vue.js 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge&…

95 快慢指针解决环形链表

问题描述&#xff1a;给定一个链表&#xff0c;判断表中是否有环&#xff0c;为了表示给定链表中的环&#xff0c;我们使用整数pos来表示链表尾链接到链表中的位置&#xff0c;如果pos是-1表示没有环。 快慢指针求解&#xff1a;定义一个慢指针和一个快指针&#xff0c;若两者…

【已解决】Invalid bound statement (not found)

报错讯息 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.casey.mapper.SysRoleMapper.getUserRoleCode at org.apache.ibatis.binding.MapperMethod S q l C o m m a n d . < i n i t > ( M a p p e r M e t h o d . j a v a :…

springboot整合websocket实现聊天室对话

要实现Spring Boot整合WebSocket实现聊天室对话&#xff0c;你需要遵循以下步骤&#xff1a; 1. 添加依赖 在你的pom.xml文件中添加以下依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter…

Springcloud 微服务实战笔记 Ribbon

使用 Configurationpublic class CustomConfiguration {BeanLoadBalanced // 开启负载均衡能力public RestTemplate restTemplate() {return new RestTemplate();}}可看到使用Ribbon&#xff0c;非常简单&#xff0c;只需将LoadBalanced注解加在RestTemplate的Bean上&#xff0…

视频通话录制 方案 教程

一些基本概要 1 市面流行的音视频产品&#xff0c;都包含一对一、一对多、多对多通话&#xff0c;云端录制等这些基本功能&#xff0c;有些厂商支持本地服务录制。 2 本地服务录制&#xff0c;云端录制区别 两个录制区别在于&#xff0c;本地服务端录制的 SDK 要求部署在 …

绑定方法与非绑定方法介绍

【 一 】绑定方法 绑定给谁&#xff0c;谁来调用就自动将它本身当作第一个参数传入 【 1 】绑定到类的方法 绑定到类的方法是指与类本身关联的方法&#xff0c;而不是与实例对象关联的方法。这些方法在类级别上操作数据&#xff0c;而不需要访问或修改特定实例对象的属性。 在…

【Proteus仿真】【Arduino单片机】电蒸锅温度控制系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶、按键开关、蜂鸣器、DS18B20温度传感器&#xff0c;液位传感器、继电器控制加热保温装置等。 主要功能&#xff1a; 系统运行后&…

C++-模板与容器

1、模板 模板可以让类或者函数支持一种通用类型&#xff0c;这种通用类型在实际运行过程中可以使用任何数据类型。因此程序员可以写出一些与类型无关的代码。这种编程方式也叫“泛型编程”。 通常有两种形式&#xff1a; 函数模板类模板 1.1 函数模板 //模板类型声明 template&…

第十四章 创建Callout Library - 故障排除和错误处理

文章目录 第十四章 创建Callout Library - 故障排除和错误处理最糟糕的做法 第十四章 创建Callout Library - 故障排除和错误处理 最糟糕的做法 — 列出一些可能导致严重问题的做法。处理 UNIX 信号处理错误 — 描述了一些函数&#xff0c;可帮助从进程接收信号时可能发生的失…

中文自然语言处理库(SnowNLP)的简单使用

snownlp 是一个简单易用的 Python 库&#xff0c;专为处理中文文本而设计。它基于自然语言处理技术&#xff0c;提供了多种功能&#xff0c;包括分词、词性标注、情感分析、文本转换&#xff08;简繁转换&#xff09;等。这个库的核心优势在于对中文文本的处理能力&#xff0c;…

Navicat 技术干货 | 聚合查询的介绍

基础 SQL 查询可以检索、插入、更新和删除记录&#xff0c;而聚合查询可通过提供求和、平均值或最大/最小值等的大型结果集&#xff0c;将数据库交互提升到一个新的水平。本文中&#xff0c;我们将探索聚合 SQL 查询的基础知识&#xff0c;并研究如何有效的利用他们来分析和汇总…

C++类和对象介绍

介绍 在C语言中&#xff0c;类和对象是面向对象编程&#xff08;OOP&#xff09;的核心概念。类定义了对象的模板或蓝图&#xff0c;而对象则是根据类的定义创建的实例。 看了定义&#xff0c;是不是感觉还是感觉不清楚&#xff0c;想学编程的都想看着代码学习&#xff0c;那就…

复试 || 就业day08(2024.01.03)算法篇

文章目录 前言亲密字符串两句话中的不常见单词公平的糖果交换卡牌分组独特的电子邮件地址 前言 &#x1f4ab;你好&#xff0c;我是辰chen&#xff0c;本文旨在准备考研复试或就业 &#x1f4ab;文章题目大多来自于 leetcode&#xff0c;当然也可能来自洛谷或其他刷题平台 &…