实现SpringMVC底层机制(三)

news2024/11/17 21:43:20

文章目录

    • 1.封装请求数据
        • 1.将方法的httpservletrequest和httpservletresponse参数封装到参数数组进行反射调用
          • 1.修改SunDispatcherServlet.java的executeDispatch方法
          • 2.debug测试
        • 2.封装http请求参数
          • 1.需求分析
          • 2.自定义注解RequestsParam
          • 3.修改MonsterService接口,添加方法
          • 4.修改MonsterServiceImpl.java添加方法
          • 5.修改SunDispatcherServlet.java编写方法根据请求参数的名字判断对应于形参列表的哪个位置
          • 6.修改SunDispatcherServlet.java的executeDispatch方法
          • 7.单元测试
          • 8.通过参数名匹配
            • 1.修改SunDispatcherServlet.java的executeDispatch方法
            • 2.添加方法
            • 3.引入插件pom.xml否则getName得到的形参列表是下面的[arg0, arg1, arg2]
            • 4.单元测试
    • 2.完成视图解析
        • 1.需求分析
        • 2.框架搭建
          • 1.编写Service
            • 1.MonsterService.java
            • 2.MonsterServiceImpl.java添加方法
          • 2.编写MonsterController.java添加方法
          • 3.编写login.jsp
          • 4.login_ok.jsp
          • 5.login_error.jsp
          • 6.修改SunDispatcherServlet.java解决中文乱码问题
    • 3.完成基本视图解析器
        • 1.修改SunDispatcherServlet.java
        • 2.单元测试
    • 4.自定义ResponseBody注解
        • 1.需求分析
        • 2.编写注解ResponseBody.java
        • 3.编写Controller,MonsterController.java
        • 4.引入Json格式转换工具jackjson
        • 5.修改SunDispatcherServlet.java,在executeDispatch方法添加逻辑
        • 6.单元测试
    • 5.SpringMVC框架总结

1.封装请求数据

1.将方法的httpservletrequest和httpservletresponse参数封装到参数数组进行反射调用
1.修改SunDispatcherServlet.java的executeDispatch方法
    //请求分发
    private void executeDispatch(HttpServletRequest request, HttpServletResponse response) {
        //获取映射对象
        SunHandler sunHandler = getSunHandler(request);
        //映射对象不等于空则反射调用controller的方法
        if (sunHandler != null) {
            try {
                /**
                 * 1.这里的的方法调用方式只支持有两个参数的方法
                 * 2.将实参放到参数数组,然后给这个invoke方法设置可变参数
                 */
                //1.获取目标方法的形参列表
                Class<?>[] parameterTypes = sunHandler.getMethod().getParameterTypes();
                //2.创建实参列表
                Object[] objects = new Object[parameterTypes.length];
                //3.遍历形参列表,将实参的类型跟形参匹配并填充到实参列表中
                for (int i = 0; i < parameterTypes.length; i++) {
                    //封装HttpServletRequest request, HttpServletResponse response
                    if ("HttpServletRequest".equals(parameterTypes[i].getSimpleName())) {
                        objects[i] = request;
                    }
                    if ("HttpServletResponse".equals(parameterTypes[i].getSimpleName())) {
                        objects[i] = response;
                    }
                }

                sunHandler.getMethod().invoke(sunHandler.getController(),objects);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        } else {
            //当映射对象是空的时候,返回404
            try {
                response.getWriter().write("<h1>404 not found!</h1>");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }
    }
2.debug测试

image-20240228085704021

2.封装http请求参数
1.需求分析

image-20240228090008585

2.自定义注解RequestsParam
package com.Sun.sunspringmvc.annotation;

import java.lang.annotation.*;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Target(ElementType.PARAMETER) //作用于方法中的参数
@Retention(RetentionPolicy.RUNTIME) //作用范围
@Documented
public @interface RequestsParam {
    String value() default "";
}
3.修改MonsterService接口,添加方法

image-20240228091016103

4.修改MonsterServiceImpl.java添加方法
    //根据姓名返回妖怪对象数组
    public List<Monster> findMonstersByName(String name) {
        ArrayList<Monster> monsters = new ArrayList<Monster>();
        monsters.add(new Monster(1, "牛魔王", "芭蕉扇", 500));
        monsters.add(new Monster(2, "蜘蛛精", "吐口水", 200));
        monsters.add(new Monster(3, "蜘蛛精", "吐口水", 200));
        monsters.add(new Monster(4, "蜘蛛精", "吐口水", 200));
        monsters.add(new Monster(5, "蜘蛛精", "吐口水", 200));
        //根据姓名查找
        //存放结果
        ArrayList<Monster> monsters1 = new ArrayList<Monster>();
        for (Monster monster : monsters) {
            if (monster.getName().equals(name)) {
                monsters1.add(monster);
            }
        }
        return monsters1;
    }
5.修改SunDispatcherServlet.java编写方法根据请求参数的名字判断对应于形参列表的哪个位置
    //根据请求参数的名字判断对应于形参列表的哪个位置,如果没有对应的则返回-1
    public int getIndexRequestParameterIndex(Method method, String name) {
        //遍历方法的参数列表
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            //获取参数对象,查看是否有注解RequestParam
            Parameter parameter = parameters[i];
            if (parameter.isAnnotationPresent(RequestsParam.class)) { //如果有这个注解
                //得到这个注解
                RequestsParam annotation = parameter.getAnnotation(RequestsParam.class);
                //如果这个注解的值和请求的参数相同,则返回这个位置
                if (annotation.value().equals(name)) {
                    return i;
                }
            }
        }
        //遍历之后如果没有找到对应位置返回-1
        return -1;
    }
6.修改SunDispatcherServlet.java的executeDispatch方法

image-20240228110914763

7.单元测试

image-20240228111004071

image-20240228111013000

8.通过参数名匹配
1.修改SunDispatcherServlet.java的executeDispatch方法

image-20240228114551992

2.添加方法
    //获取目标方法所有形参名并以列表的形式返回
    public List<String> getParameterNames(Method method) {
        List<String> parNames = new ArrayList<String>();
        Parameter[] parameters = method.getParameters();
        for (Parameter parameter : parameters) {
            String name = parameter.getName();
            parNames.add(name);
        }
        return parNames;
    }
3.引入插件pom.xml否则getName得到的形参列表是下面的[arg0, arg1, arg2]
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.7.0</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
            <compilerArgs>
              <arg>-parameters</arg>
            </compilerArgs>
            <encoding>utf-8</encoding>
          </configuration>
        </plugin>

image-20240228112738174

image-20240228113550948

image-20240228113723947

4.单元测试

image-20240228114816356

image-20240228114837564

2.完成视图解析

1.需求分析

image-20240228134346434

2.框架搭建
1.编写Service
1.MonsterService.java

image-20240228141801980

2.MonsterServiceImpl.java添加方法
    //处理登录的方法
    @Override
    public boolean login(String name) {
        if ("sun".equals(name)) {
            return true;
        }
        return false;
    }
2.编写MonsterController.java添加方法
    @RequestMapping("monster/login")
    public String login(String mName) {
        System.out.println("接收到的名字=" + mName);
        boolean login = monsterService.login(mName);
        if (login) {
            //返回给视图解析器
            return "forward:/login_ok.jsp";
        } else {
            return "forward:/login_error.jsp";
        }
    }
3.编写login.jsp
<%--
  Date: 2024/2/28
  Time: 13:54
  User: 孙显圣
  Version:1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form method="get" action="monster/login">
    姓名:<input name="mName" type="text"><br>
    <input type="submit" value="登录">
</form>
</body>
</html>

4.login_ok.jsp
<%--
  Date: 2024/2/28
  Time: 13:56
  User: 孙显圣
  Version:1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
欢迎你:${?}
</body>
</html>

5.login_error.jsp
<%--
  Date: 2024/2/28
  Time: 13:56
  User: 孙显圣
  Version:1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>Title</title>
</head>
<body>
<h1>登录失败</h1>
欢迎你:${?}
</body>
</html>

6.修改SunDispatcherServlet.java解决中文乱码问题

image-20240228142751871

3.完成基本视图解析器

1.修改SunDispatcherServlet.java

image-20240228150049613

                //以下是视图解析器
                //1.判断是否是字符串
                if (result instanceof String) {
                    //判断是否包含:
                    if (((String) result).contains(":")) {
                        //根据冒号分割
                        String[] split = ((String) result).split(":");
                        String type = split[0];
                        String name = split[1];
                        if (type.equals("forward")) {
//                            /login_ok.jsp
                            try {
                                //请求转发
                                request.getRequestDispatcher(name).forward(request, response);
                            } catch (ServletException e) {
                                throw new RuntimeException(e);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        } else if (type.equals("redirect")) {
                            //重定向
                            String fill = "/sun_springmvc";
                            try {
                                response.sendRedirect(fill + name);
                            } catch (IOException e) {
                               throw new RuntimeException(e);
                            }
                        }
                    } else {
                        //没有冒号比如login.jsp, 默认请求转发
                        try {
                            request.getRequestDispatcher("/" + result).forward(request, response);
                        } catch (ServletException e) {
                            throw new RuntimeException(e);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
2.单元测试

image-20240228155017707

image-20240228155027623

4.自定义ResponseBody注解

1.需求分析

image-20240228162053567

2.编写注解ResponseBody.java
package com.Sun.sunspringmvc.annotation;

import java.lang.annotation.*;

/**
 * 用于标识一个要返回json数据的方法
 *
 * @author 孙显圣
 * @version 1.0
 */
@Target(ElementType.METHOD) //作用目标是方法
@Retention(RetentionPolicy.RUNTIME) //作用范围
@Documented
public @interface ResponseBody {
}

3.编写Controller,MonsterController.java
    //编写一个方法,添加ResponseBody注解,返回json数据
    @ResponseBody
    @RequestMapping(value = "monster/list/json")
    public List<Monster> listMonsterByJson(HttpServletRequest request, HttpServletResponse response) {
        List<Monster> monsters = monsterService.listMonsters();
        return monsters;
    }
4.引入Json格式转换工具jackjson
    <!--引入jackson 使用它的工具可以进行json类型转换-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.12.4</version>
    </dependency>
5.修改SunDispatcherServlet.java,在executeDispatch方法添加逻辑

image-20240228163356879

 else if (result instanceof ArrayList) { //如果结果类型是ArrayList则表明可能要求返回的是Json形式
                    //得到这个目标方法对象
                    Method method = sunHandler.getMethod();
                    //判断是否含有ResponseBody注解
                    if (method.isAnnotationPresent(ResponseBody.class)) { //如果有,则以json形式返回数据
                        //把返回的结果转换成json格式的数据
                        ObjectMapper objectMapper = new ObjectMapper();
                        String json = objectMapper.writeValueAsString(result);
                        //返回给浏览器
                        //注意设置字符编码
                        response.setContentType("text/html;charset=utf-8");
                        PrintWriter writer = response.getWriter();
                        writer.write(json);
                        //刷新和关闭
                        writer.flush();
                        writer.close();
                    }
                }
6.单元测试

image-20240228163504379

5.SpringMVC框架总结

image-20240228185746708

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

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

相关文章

Python PyTorch 获取 MNIST 数据

Python PyTorch 获取 MNIST 数据 1 PyTorch 获取 MNIST 数据2 PyTorch 保存 MNIST 数据3 PyTorch 显示 MNIST 数据 1 PyTorch 获取 MNIST 数据 import torch import numpy as np import matplotlib.pyplot as plt # type: ignore from torchvision import datasets, transform…

Rust 实战练习 - 12. Axum Web 简单demo

Rust Web 历程 Rust 的异步框架tokio非他莫属&#xff0c;而web框架一直是悬而未决&#xff0c;说到底还是因为没有官方成熟的方案指引&#xff0c;大家各玩各的&#xff0c;互不兼容&#xff0c;白白浪费精力。 这个事情一直等到半官方组织tokio推出axum有了改善。但是市场上…

【神经网络结构可视化】PlotNeuralNet的安装、测试及创建自己的神经网络结构可视化图形

文章目录 前提准备1、下载MikTeX2、下载Git bash3、下载PlotNeuralNet 进行测试1、解压PlotNeuralNet-master.zip2、打开Git bash3、 在my_project中查看生成的pdf文件 创建自己的神经网络结构可视化图形 前提准备 1、下载MikTeX 下载链接&#xff1a; MikTeX ( https://mikt…

RestfulApi RestTemplate代码规范介绍

1.介绍 1.1 RestfulApi Restful API 是一种设计风格&#xff0c;代表了使用 HTTP 协议构建 web 服务的一种架构原则。REST&#xff08;Representational State Transfer&#xff09;的核心思想是&#xff0c;通过 URL 定位资源&#xff0c;使用 HTTP 方法&#xff08;GET, POS…

【多维动态规划】Leetcode 62. 不同路径【中等】

不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1…

Vue3+Vite开发的项目进行加密打包

本文主要介绍Vue3+Vite开发的项目如何进行加密打包。 目录 一、vite简介二、混淆工具三、使用方法1. 安装插件:2. 配置插件:3. 运行构建:4. 自定义混淆选项:5. 排除文件:下面是Vue 3+Vite开发的项目进行加密打包的方法。 一、vite简介 Vite 是一个由 Evan You 创造的现代…

【Python从入门到进阶】53、Scrapy日志信息及日志级别

接上篇《52、CrawlSpider链接提取器的使用》 上一篇我们学习了基于规则进行跟踪和自动爬取网页数据的“特殊爬虫”CrawlSpider。本篇我们来学习Scrapy的日志信息及日志级别。 一、引言 1、日志在Scrapy中的重要性 在Scrapy框架中&#xff0c;日志扮演着至关重要的角色。日志…

JAVA面试八股文之JVM

JVM JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f;你能详细说一下 JVM 运行时数据区吗&#xff1f;详细介绍一下程序计数器的作用&#xff1f;你能给我详细的介绍Java堆吗?什么是虚拟机栈&#xff1f;栈内存溢出情况&#xff1f;堆栈的区别是什么吗&#xff1f;解…

2024 年最好的免费数据恢复软件,您可以尝试的几个数据恢复软件

由于系统崩溃而丢失数据可能会给用户带来麻烦。我们将重要的宝贵数据和个人数据保存在我们的 PC、笔记本电脑和其他数字设备上。您可能会因分区丢失、意外删除文件和文件夹、格式化硬盘驱动器而丢失数据。数据丢失是不幸的&#xff0c;如果您不小心从系统中删除了文件或数据&am…

护眼台灯是不是智商税,专业护眼台灯的四大好处需牢记!

在现代社会&#xff0c;电子产品的普及和长时间的屏幕使用已经成为日常生活的一部分&#xff0c;这无疑对我们的视力健康提出了挑战。为了保护眼睛&#xff0c;市场上出现了各种声称能够减轻眼睛疲劳、预防近视等功效的护眼台灯。然而&#xff0c;关于护眼台灯是否真的具有这些…

C#基础:WPF中常见控件的布局基础

一、用ViewBox实现放缩控件不变 二、布局代码 <Window x:Class"WpfApp1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"Title"MainWindow"…

传统过程自动化工厂的智能扩展

一 通过NOA概念&#xff0c;公开、安全地迈向未来 随着数字化转型在过程自动化工业中的不断深入&#xff0c;许多公司都面临着同一挑战——如何平衡创新和传统。放眼望去&#xff0c;过程自动化工业和信息技术似乎在以不同的速度发展。虽然过程自动化工厂通过使用传统的自动化…

自动化爬虫工具:you-get安装与使用

Windows下的安装命令&#xff1a; pip install you-get linux下的安装命令&#xff1a; pip3 install you-get 下载完成后&#xff0c;我们可以看到如下的警告&#xff0c;意思就是这个工具并未被添加到环境变量中&#xff0c;如果我们想在命令行中直接调用&#xff0c;需要…

Docker Machine 入门实践@FreeBSD

在这篇文档里&#xff0c;我们安装了docker machine&#xff1a;FreeBSD安装Docker记录-CSDN博客 在这篇文档里&#xff0c;我们启动虚拟主机myvm并进入虚拟主机&#xff1a;boot2docker实践FreeBSD-CSDN博客 现在开始更深入的进行 docker的实战演练。参考Docker Machine官方…

Git--多人协作

目录 一、多人协作一二、多人协作二三、 远程分⽀删除后&#xff0c;本地git branch -a依然能看到的解决办法 一、多人协作一 ⽬前&#xff0c;我们所完成的⼯作如下&#xff1a; 1.基本完成Git的所有本地库的相关操作&#xff0c;git基本操作&#xff0c;分⽀理解&#xff0c;…

Java面试八股文-2024

面试指南 TMD&#xff0c;一个后端为什么要了解那么多的知识&#xff0c;真是服了。啥啥都得了解 MySQL MySQL索引可能在以下几种情况下失效&#xff1a; 不遵循最左匹配原则&#xff1a;在联合索引中&#xff0c;如果没有使用索引的最左前缀&#xff0c;即查询条件中没有包含…

RK3568平台开发系列讲解(Linux系统篇)芯片手册的使用:GPIO的寄存器说明

🚀返回专栏总目录 文章目录 一、查找复用寄存器二、查找方向寄存器三、查找数据寄存器沉淀、分享、成长,让自己和他人都能有所收获!😄 📢寄存器GPIO 进行配置, 一般情况下需要对 GPIO 的复用寄存器, 方向寄存器, 数据寄存器进行配置。 GPIO0_B0 配置为例: 一、查…

BTCOIN发布WEB3.0论坛:生态与金融的双重叙事热点驱动自由创新意识

在数字时代&#xff0c;信息的自由流动和透明度是推动经济发展和社会进步的关键。尤其在加密货币和区块链领域&#xff0c;这一点尤为重要。BTCOIN的最新创举——一个基于WEB3.0理念的信息论坛&#xff0c;不仅标志着信息传递自由化的新篇章&#xff0c;也为数字货币市场的信息…

上位机图像处理和嵌入式模块部署(树莓派4b中的软件调试)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 说到软件调试&#xff0c;有一点大家相信都有体会。那就是编写软件的时候&#xff0c;功能本身还是不算太复杂的。只需要前面流程、算法都设计好了…

STM32学习和实践笔记(20):定时器

1.定时器介绍 STM32F1的定时器一共有8个&#xff0c;由2个基本定时器&#xff08;TIM6、TIM7&#xff09;、4个通用定时器&#xff08;TIM2-TIM5&#xff09;和2个高级定时器&#xff08;TIM1、TIM8&#xff09;组成。 基本定时器的功能最为简单&#xff0c;类似于51单片机内定…