当前位置: 首页 > news >正文

JavaWeb Servlet的反射优化、Dispatcher优化、视图(重定向)优化、方法参数值获取优化

目录

  • 1. 背景
  • 2. 实现
    • 2.1 pom.xml
    • 2.2 FruitController.java
    • 2.3 DispatcherServlet.java
    • 2.4 applicationContext.xml
  • 3. 测试

1. 背景

前面我们做了Servlet的一个案例。但是存在很多问题,现在我们要做优化,优化的步骤如下:

  1. 每个Fruit请求都需要一个Servlet来处理,这样就会产生大量的Servlet。我们可以只用一个FruitServlet来处理,然后通过一个operate变量来区分请求FruitServlet的哪个方法
  2. 除了有Fruit的请求,可能还有很多其它类型的请求。可以用一个DispatcherServlet来处理所有的请求,然后定义一个applicationContext.xml来让一个请求和其处理的类对应
  3. 不在FruitController中做重定向,FruitController只返回要重定向的路径,统一由DispatcherServlet来做重定向
  4. 不在FruitController的方法中获取参数。由DispatcherServlet统一获取参数,然后传递给FruitController的方法

2. 实现

2.1 pom.xml

编译的时候保留方法的参数名,而不是擦除。注意删除target,不然不会生效

            <!-- 编译的时候保留方法的参数名,而不是擦除。注意删除target,不然不会生效 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.10.1</version><configuration><source>11</source><target>11</target><compilerArgument>-parameters</compilerArgument></configuration></plugin>

2.2 FruitController.java

只负责具体的业务逻辑处理。重定向、参数获取全部由DispatcherServlet处理

package com.hh.javaWebTest.servlet;import com.hh.javaWebTest.bean.Fruit;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;// 只负责具体的业务逻辑处理。重定向、参数获取全部由DispatcherServlet处理
public class FruitController {protected String index(Integer paramId, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 不通过req.getParameter(paramName)获取参数值,而是通过在dispatcher统一获取,再传入进来// 测试是否能获取到参数System.out.println("paramId: " + paramId);System.out.println(req.getRequestURI());    // /javaWebTest/fruit.doSystem.out.println(req.getQueryString());   // paramId=1List<Fruit> fruitList = new ArrayList<Fruit>();fruitList.add(new Fruit("苹果", 5));fruitList.add(new Fruit("香蕉", 3));HttpSession session = req.getSession();session.setAttribute("fruitList", fruitList);// 由DispatcherServlet调用super.processTemplate("index", request, response);return "index";}}

2.3 DispatcherServlet.java

接受所有的请求,然后进行分发

package com.hh.javaWebTest.servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;// 接受所有的请求,然后进行分发
@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {private Map<String, Object> beanMap = new HashMap<>();@Overridepublic void init() throws ServletException {// 手动进行ViewBaseServlet的初始化super.init();// 解析applicationContext.xml,形成id:class形式的beanMaptry {InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();Document document = documentBuilder.parse(inputStream);NodeList beanNodeList = document.getElementsByTagName("bean");for (int i = 0; i < beanNodeList.getLength(); i++) {Node beanNode = beanNodeList.item(i);if (beanNode.getNodeType() == Node.ELEMENT_NODE) {Element beanElement = (Element) beanNode;String beanId = beanElement.getAttribute("id");String className = beanElement.getAttribute("class");Class controllerBeanClass = Class.forName(className);Object beanObj = controllerBeanClass.getDeclaredConstructor().newInstance();beanMap.put(beanId, beanObj);}}} catch (Exception e) {e.printStackTrace();}}@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// servletPath: /fruit.do => fruitString servletPath = request.getServletPath();servletPath = servletPath.substring(1);int lastDotIndex = servletPath.lastIndexOf(".do");servletPath = servletPath.substring(0, lastDotIndex);// 获取fruit对应的classObject controllerBeanObj = beanMap.get(servletPath);// 获取operateString operate = request.getParameter("operate");if (StringUtils.isEmpty(operate)) {operate = "index";}try {Method[] methods = controllerBeanObj.getClass().getDeclaredMethods();for (Method method : methods) {// 匹配operate对应的类方法if (operate.equals(method.getName())) {Parameter[] parameters = method.getParameters();// 将类方法的值,保存到parameterValuesObject[] parameterValues = new Object[parameters.length];for (int i = 0; i < parameters.length; i++) {Parameter parameter = parameters[i];String parameterName = parameter.getName();if ("req".equals(parameterName)) {parameterValues[i] = request;} else if ("resp".equals(parameterName)) {parameterValues[i] = response;} else if ("session".equals(parameterName)) {parameterValues[i] = request.getSession();} else {// 从请求中获取参数值String parameterValue = request.getParameter(parameterName);String typeName = parameter.getType().getName();Object parameterObj = parameterValue;if (parameterObj != null) {if ("java.lang.Integer".equals(typeName)) {parameterObj = Integer.parseInt(parameterValue);}}parameterValues[i] = parameterObj;}}// 调用方法,返回值。根据返回值判断是否需要做重定向method.setAccessible(true);Object returnObj = method.invoke(controllerBeanObj, parameterValues);// 视图处理(重定向处理)String methodReturnStr = (String) returnObj;if (methodReturnStr.startsWith("redirect:")) {  // 比如: redirect:fruit.doString redirectStr = methodReturnStr.substring("redirect:".length());response.sendRedirect(redirectStr);} else if (methodReturnStr != "") {         // 比如: "index"super.processTemplate(methodReturnStr, request, response);return;} else {return;}}}} catch (Exception e) {e.printStackTrace();}throw new RuntimeException("operate值非法!");}
}

2.4 applicationContext.xml

定义java bean的id,和其对应的处理类

<?xml version="1.0" encoding="utf-8"?><!--
XML包含三个部分:
1. XML声明, 而且声明这一行代码必须在XML文件的第一行
2. DTD: 文档类型定义
3. XML正文--><!-- 该标签告知XML文档所使用的XML beans规范 -->
<!DOCTYPE beans [<!ELEMENT beans (bean*)><!ELEMENT bean (property*)><!ELEMENT property (#PCDATA)><!ATTLIST bean id ID #REQUIRED><!ATTLIST bean class CDATA #IMPLIED><!ATTLIST property name CDATA #IMPLIED><!ATTLIST property ref IDREF #IMPLIED>]><beans><!-- 说明这是一个java bean。id是fruit,其对应的处理类是FruitController --><bean id="fruit" class="com.hh.javaWebTest.servlet.FruitController"/>
</beans>

3. 测试

请求http://localhost:8080/javaWebTest/fruit.do?paramId=1,web页面显示和之前的一样

web页面显示效果

控制台输出如下:

paramId: 1

相关文章:

JavaWeb Servlet的反射优化、Dispatcher优化、视图(重定向)优化、方法参数值获取优化

目录 1. 背景2. 实现2.1 pom.xml2.2 FruitController.java2.3 DispatcherServlet.java2.4 applicationContext.xml 3. 测试 1. 背景 前面我们做了Servlet的一个案例。但是存在很多问题&#xff0c;现在我们要做优化&#xff0c;优化的步骤如下&#xff1a; 每个Fruit请求都需…...

备忘一个FDBatchMove数据转存的问题

使用FDBatchMove的SQL导入excel表到sql表&#xff0c;设置条件时一头雾水&#xff0c;函数不遵守sql的规则。 比如替换字段的TAB键值为空&#xff0c;replace(字段名,char(9),)竟然提示错误&#xff0c;百思不得其解。 试遍了几乎所有的函数&#xff0c;竟然是chr(9)。 这个…...

CEF127 编译指南 MacOS 篇 - 编译 CEF(六)

1. 引言 经过前面的准备工作&#xff0c;我们已经完成了所有必要的环境配置。本文将详细介绍如何在 macOS 系统上编译 CEF127。通过正确的编译命令和参数配置&#xff0c;我们将完成 CEF 的构建工作&#xff0c;最终生成可用的二进制文件。 2. 编译前准备 2.1 确认环境变量 …...

【更新】LLM Interview

课程链接&#xff1a;BV1o217YeELo 文章目录 LLM基础相关1. LLMs概述2. 大语言模型尺寸3. LLMs的优势与劣势4. 常见的大模型分类5. 目前主流的LLMs开源模型体系有哪些&#xff08;Prefix Decoder&#xff0c;Causal Decoder&#xff0c;Encoder-Decoder的区别是什么&#xff09…...

Django 视图中使用 Redis 缓存优化查询性能

在 Web 应用程序开发中,查询数据库是一个常见的操作,但如果查询过于频繁或耗时,就会影响应用程序的性能。为了解决这个问题,我们可以使用缓存技术,将查询结果暂时存储在内存中,从而减少对数据库的访问。本文将介绍如何在 Django 视图中使用 Redis 缓存来优化查询性能。 © …...

正则表达式解析与功能说明

正则表达式解析与功能说明 表达式说明 String regex "\\#\\{TOASRTRINNG\\((.*?)((.*?))\\)(\\})";该正则表达式的作用是匹配形如 #{TOASRTRINNG(...)} 的字符串格式。以下是正则表达式的详细解析&#xff1a; 拆解与解析 1. \\# 匹配&#xff1a;# 字符。说明…...

STUN服务器实现NAT穿透

NAT穿透的问题 在现代网络环境中&#xff0c;大多数设备都位于NAT(网络地址转换)设备后面。这给点对点(P2P)通信带来了挑战&#xff0c;因为NAT会阻止外部网络直接访问内部设备。STUN(Session Traversal Utilities for NAT)服务器就是为了解决这个问题而设计的。 STUN是什么?…...

音视频入门基础:MPEG2-TS专题(19)——FFmpeg源码中,解析TS流中的PES流的实现

一、引言 FFmpeg源码在解析完PMT表后&#xff0c;会得到该节目包含的视频和音频信息&#xff0c;从而找到音视频流。TS流的音视频流包含在PES流中。FFmpeg源码通过调用函数指针tss->u.pes_filter.pes_cb指向的回调函数解析PES流的PES packet&#xff1a; /* handle one TS…...

tomcat的安装以及配置(基于linuxOS)

目录 安装jdk环境 yum安装 验证JDK环境 安装tomcat应用 yum安装 ​编辑 使用yum工具进行安装 配置tomcat应用 关闭防火墙和selinux 查看端口开启情况 ​编辑 访问tomcat服务 安装扩展包 重启服务 查看服务 源码安装 进入tomcat官网进行下载 查找自己要用的to…...

因子分解(递归)

1.素分解式(简单版) 任务描述 编写函数&#xff0c;输出一个正整数的素数分解式。主函数的功能为输入若干正整数&#xff08;大于1&#xff09;&#xff0c;输出每一个数的素分解式。素数分解式是指将整数写成若干素数(从小到大)乘积的形式。例如&#xff1a; 202*2*5 362*2*…...

【Python】pandas库---数据分析

大学毕业那年&#xff0c;你成了社会底层群众里&#xff0c;受教育程度最高的一批人。 前言 这是我自己学习Python的第四篇博客总结。后期我会继续把Python学习笔记开源至博客上。 上一期笔记有关Python的NumPy数据分析&#xff0c;没看过的同学可以去看看&#xff1a;【Pyt…...

RabbitMQ 的7种工作模式

RabbitMQ 共提供了7种⼯作模式,进⾏消息传递,. 官⽅⽂档:RabbitMQ Tutorials | RabbitMQ 1.Simple(简单模式) P:⽣产者,也就是要发送消息的程序 C:消费者,消息的接收者 Queue:消息队列,图中⻩⾊背景部分.类似⼀个邮箱,可以缓存消息;⽣产者向其中投递消息,消费者从其中取出消息…...

负载均衡式在线OJ

文章目录 项目介绍所用技术与开发环境所用技术开发环境 项目框架compiler_server模块compiler编译功能comm/util.hpp 编译时的临时文件comm/log.hpp 日志comm/util.hpp 时间戳comm/util.hpp 检查文件是否存在compile_server/compiler.hpp 编译功能总体编写 runner运行功能资源设…...

【3D打印机】启庞KP3S热床加热失败报错err6

最近天冷&#xff0c;打印机预热突然失败&#xff0c;热床无法加热&#xff0c;过了一段时间报错err6&#xff0c;查看另一篇资料说是天气冷原因&#xff0c;导致代码的PID控温部分达不到预期加热效果&#xff0c;从而自检报错&#xff0c;然后资料通过修改3D打印机代码的方式进…...

基于 MATLAB 的图像增强技术分享

一、引言 图像增强是数字图像处理中的重要环节&#xff0c;其目的在于改善图像的视觉效果&#xff0c;使图像更清晰、细节更丰富、对比度更高&#xff0c;以便于后续的分析、识别与理解等任务。MATLAB 作为一款功能强大的科学计算软件&#xff0c;提供了丰富的图像处理工具和函…...

前端知识补充—HTML

1. HTML 1.1 什么是HTML HTML(Hyper Text Markup Language), 超⽂本标记语⾔ 超⽂本: ⽐⽂本要强⼤. 通过链接和交互式⽅式来组织和呈现信息的⽂本形式. 不仅仅有⽂本, 还可能包含图⽚, ⾳频, 或者⾃已经审阅过它的学者所加的评注、补充或脚注等等 标记语⾔: 由标签构成的语⾔…...

安卓从Excel文件导入数据到SQLite数据库的实现

在现代的移动应用开发中&#xff0c;数据的处理和管理是至关重要的一环。有时候&#xff0c;我们需要从外部文件&#xff08;如Excel文件&#xff09;中导入数据&#xff0c;以便在应用程序中使用。本文将介绍如何在Android应用中使用Java代码从一个Excel文件中导入数据到SQLit…...

C/C++基础知识复习(44)

1) C 中多态性在实际项目中的应用场景 多态性是面向对象编程&#xff08;OOP&#xff09;中的一个重要特性&#xff0c;指的是不同的对象可以通过相同的接口来表现不同的行为。在 C 中&#xff0c;多态通常通过虚函数&#xff08;virtual&#xff09;和继承机制来实现。实际项…...

【day13】深入面向对象编程

【day12】回顾 在正文开始之前&#xff0c;先让我们回顾一下【day12】中的关键内容&#xff1a; 接口&#xff08;Interface&#xff09;&#xff1a; interface关键字用于定义接口。implements关键字用于实现接口。 接口成员&#xff1a; 抽象方法&#xff1a;需要在实现类中…...

《 火星人 》

题目描述 人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言&#xff0c;但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的&#xff0c;首先&#xff0c;火星人把一个非常大的数字告诉人类科学家&#xff0c;科学家破解这…...

终极scan4all安全扫描工具:如何生成专业日志分析与安全评估报告

终极scan4all安全扫描工具&#xff1a;如何生成专业日志分析与安全评估报告 【免费下载链接】scan4all 项目地址: https://gitcode.com/gh_mirrors/sc/scan4all scan4all是一款功能强大的自动化安全扫描工具&#xff0c;它集成了vscan、nuclei、ksubdomain、subfinder等…...

RWKV7-1.5B-g1a入门必看:轻量中文问答/文案续写/摘要生成快速上手指南

RWKV7-1.5B-g1a入门必看&#xff1a;轻量中文问答/文案续写/摘要生成快速上手指南 1. 模型简介 RWKV7-1.5B-g1a是一个基于RWKV-7架构的多语言文本生成模型&#xff0c;特别适合中文场景下的基础问答、文案续写、简短总结和轻量对话任务。这个1.5B参数的版本在保持良好生成质量…...

Cherry Studio容器化部署实战指南:从环境搭建到生产运维

Cherry Studio容器化部署实战指南&#xff1a;从环境搭建到生产运维 【免费下载链接】cherry-studio &#x1f352; Cherry Studio is a desktop client that supports for multiple LLM providers. Support deepseek-r1 项目地址: https://gitcode.com/GitHub_Trending/ch/c…...

俄罗斯莫斯科电子烟展:跟团公司高性价比选择策略拆解

对于想开拓俄罗斯市场的电子烟企业来说&#xff0c;俄罗斯莫斯科电子烟展是不可错过的出海窗口&#xff0c;但行业信息杂乱、代理鱼龙混杂的现状&#xff0c;让很多企业陷入“选便宜还是选靠谱”的两难。选对跟团公司&#xff0c;不仅能节省成本&#xff0c;更能直接决定参展效…...

教培人必看!那些好用到哭的网课平台大盘点

一、引言&#xff1a;网课平台&#xff0c;教培行业的新战场 在互联网浪潮的席卷下&#xff0c;教培行业正经历着前所未有的变革。曾经&#xff0c;学生们只能在固定的时间和地点&#xff0c;坐在教室里听老师授课。而如今&#xff0c;随着网课平台的兴起&#xff0c;学习的时…...

SuperSplat:零安装的浏览器端3D高斯点云编辑器,重塑三维数据处理体验

SuperSplat&#xff1a;零安装的浏览器端3D高斯点云编辑器&#xff0c;重塑三维数据处理体验 【免费下载链接】super-splat 3D Gaussian Splat Editor 项目地址: https://gitcode.com/gh_mirrors/su/super-splat 在当今三维重建和计算机视觉领域&#xff0c;处理大规模3…...

3D Slicer隐藏技巧:这样玩转医学影像分割与3D建模(含DICOM处理)

3D Slicer隐藏技巧&#xff1a;这样玩转医学影像分割与3D建模&#xff08;含DICOM处理&#xff09; 在医学影像分析和三维建模领域&#xff0c;3D Slicer作为一款开源工具已经赢得了专业用户的广泛认可。但对于那些已经掌握基础操作的用户来说&#xff0c;如何真正发挥这款软件…...

RuoYi-Vue-Plus:现代化企业级开发框架的架构演进与分布式多租户解决方案

RuoYi-Vue-Plus&#xff1a;现代化企业级开发框架的架构演进与分布式多租户解决方案 【免费下载链接】RuoYi-Vue-Plus 项目地址: https://gitcode.com/GitHub_Trending/ru/RuoYi-Vue-Plus 面对企业应用开发中普遍存在的分布式架构复杂性、多租户数据隔离难题以及传统框…...

【内存心法】别用玄学猜栈大小了!撕碎 RTOS 堆栈溢出的遮羞布,用 ARM MPU 构筑硬件级“死亡红区”与绝对沙箱

摘要&#xff1a;在错综复杂的多任务 RTOS 环境中&#xff0c;一个微小的局部数组越界&#xff0c;就能像癌细胞一样悄无声息地摧毁整个系统的内存空间。无数开发者迷信 FreeRTOS 的 vApplicationStackOverflowHook&#xff0c;却不知道它在真正的“跳跃式内存踩踏”面前形同虚…...

HarmonyOS6 ArkTS List 子元素对齐

文章目录一、组件概述二、官方核心对齐 APIalignListItem(value: ListItemAlign)ListItemAlign 枚举值三、完整可运行代码四、代码功能说明1. 多列网格布局2. 统一子项对齐3. 动态切换对齐方式总结一、组件概述 List 是 HarmonyOS6 中支持多列网格布局的列表容器&#xff0c;通…...