servlet运用自定义分发优化servlet泛滥

news2024/11/19 10:46:00

servlet优化

Web 层的 Servlet 个数太多了,不利于管理和编写

我们发现每一个功能都需要定义一个 servlet,一个模块需要实现增删改查功能,就需要4个 servlet,模块一多就会造成servlet 泛滥。此时我们就想 servlet 能不能像 service 一样,一个模块只定义一个 servlet,而每一个功能只需要在该 servlet 中定义对应的方法。例如下面代码:

@WebServlet("/brand/*")
public class BrandServlet {
    //查询所有
	public void selectAll(...) {}
    
    //添加数据
    public void add(...) {}
    
     //修改数据
    public void update(...) {}
    
    //删除删除
    public void delete(...) {}
}

而我们知道发送请求 servlettomcat 会自动的调用 service() 方法,之前我们在自定义的 servlet 中重写 doGet() 方法和 doPost() 方法,当我们访问该 servlet 时会根据请求方式将请求分发给 doGet() 或者 doPost() 方法,如下图
在这里插入图片描述

那么我们也可以仿照这样请求分发的思想,在 service() 方法中根据具体的操作调用对应的方法,如:查询所有就调用 selectAll() 方法,添加企业信息就调用 add() 方法。

为了做到通用,我们定义一个通用的 servlet 类,在定义其他的 servlet 是不需要继承 HttpServlet,而继承我们定义的 BaseServlet,在 BaseServlet 中调用具体 servlet(如BrandServlet)中的对应方法。

public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //进行请求的分发
    }
}

BrandServlet 定义就需要修改为如下:

@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet {
    //用户实现分页查询
	public void selectAll(...) {} 
    
    //添加企业信息
    public void add(...) {}
    
    //修改企业信息
    public void update(...) {}
    
    //删除企业信息
    public void delete(...) {}
}

那么如何在 BaseServlet 中调用对应的方法呢?比如查询所有就调用 selectAll() 方法。

可以规定在发送请求时,请求资源的二级路径(/brandServlet/selectAll)和需要调用的方法名相同,如:

查询所有数据的路径以后就需要写成: http://localhost:8080/brand-case/brandServlet/selectAll

添加数据的路径以后就需要写成: http://localhost:8080/brand-case/brandServlet/add

修改数据的路径以后就需要写成: http://localhost:8080/brand-case/brandServlet/update

删除数据的路径以后就需要写成: http://localhost:8080/brand-case/brandServlet/delete

这样的话,在 BaseServlet 中就需要获取到资源的二级路径作为方法名,然后调用该方法

public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取请求路径
        String uri = req.getRequestURI(); // 例如路径为:/brand-case/brand/selectAll
        //2. 获取最后一段路径,方法名
        int index = uri.lastIndexOf('/');
        String methodName = uri.substring(index + 1); //  获取到资源的二级路径  selectAll

        //2. 执行方法
        //2.1 获取BrandServlet /UserServlet 字节码对象 Class
        //System.out.println(this);

        Class<? extends BaseServlet> cls = this.getClass();
        //2.2 获取方法 Method对象
        try {
            Method method = cls.getMethod(methodName,???);
            //4,调用该方法
            method.invoke(this,???);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

通过上面代码发现根据方法名获取对应方法的 Method 对象时需要指定方法参数的字节码对象。解决这个问题,可以将方法的参数类型规定死,而方法中可能需要用到 request 对象和 response 对象,所以指定方法的参数为 HttpServletRequestHttpServletResponse,那么 BrandServlet 代码就可以改进为:

@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet {
    //用户实现分页查询
	public void selectAll(HttpServletRequest req, HttpServletResponse resp) {}
    
    //添加企业信息
    public void add(HttpServletRequest req, HttpServletResponse resp) {}
    
    //修改企业信息
    public void update(HttpServletRequest req, HttpServletResponse resp) {}
    
    //删除企业信息
    public void delete(HttpServletRequest req, HttpServletResponse resp) {}
}

BaseServlet代码可以改进为:

public class BaseServlet extends HttpServlet {

    //根据请求的最后一段路径来进行方法分发
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取请求路径
        String uri = req.getRequestURI(); // 例如路径为:/brand-case/brand/selectAll
        //2. 获取最后一段路径,方法名
        int index = uri.lastIndexOf('/');
        String methodName = uri.substring(index + 1); //  获取到资源的二级路径  selectAll   

        //2. 执行方法
        //2.1 获取BrandServlet /UserServlet 字节码对象 Class
        //System.out.println(this);

        Class<? extends BaseServlet> cls = this.getClass();
        //2.2 获取方法 Method对象
        try {   
            Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //2.3 执行方法
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

定义了 BaseServlet 后,针对品牌模块我们定义一个 BrandServlet 的 Servlet,并使其继承 BaseServlet 。在BrandServlet中定义 以下功能的方法:

  • 查询所有 功能:方法名声明为 selectAll ,并将之前的 SelectAllServlet 中的逻辑代码拷贝到该方法中
  • 添加数据 功能:方法名声明为 add ,并将之前的 AddServlet 中的逻辑代码拷贝到该方法中

具体代码如下:

@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet{
    private BrandService brandService = new BrandServiceImpl();

    public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 调用service查询
        List<Brand> brands = brandService.selectAll();

        //2. 转为JSON
        String jsonString = JSON.toJSONString(brands);
        //3. 写数据
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(jsonString);
    }

    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1. 接收品牌数据
        BufferedReader br = request.getReader();
        String params = br.readLine();//json字符串

        //转为Brand对象
        Brand brand = JSON.parseObject(params, Brand.class);

        //2. 调用service添加
        brandService.add(brand);

        //3. 响应成功的标识
        response.getWriter().write("success");
    }
}

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

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

相关文章

YOLOv6 训练自己的数据集

项目地址&#xff1a;https://github.com/meituan/YOLOv6 论文地址&#xff1a;https://arxiv.org/abs/2209.02976 论文解析&#xff1a;http://t.csdn.cn/0ZQbV YOLOv6 是一种专为工业应用设计的单级对象检测框架&#xff0c;具有硬件友好的高效设计和高性能。YOLOv6-N 在 NVI…

【windows】docker与docker-compose部署spring boot项目

看完不会用&#xff0c;我倒立**&#xff0c;保姆级教学 docker部署项目 采用Dockerfile部署 docker-compose部署项目 docker-compose部署&#xff0c;实际上是对容器的编排&#xff0c;以及容器间的一些依赖 比如一个springboot项目&#xff0c;需要使用redis&#xff0c;…

深入 Redis sds

文末有视频讲解 在上一个模块中&#xff0c;我和小伙伴们一起学习了 Redis 最核心的命令&#xff0c;主要涉及 String、List、Hash、Set、Sorted Set 五种数据结构的命令&#xff0c;同时&#xff0c;我们还介绍了每种数据结构的实战场景&#xff0c;并带领小伙伴们使用 Java 语…

11、ThingsBoard-租户配置

1、概述 租户配置(tenant profile)如其名是租户相关的配置,通俗一点就是给你这个租户的功能增加一些限制,如果你加钱,我就给你把限制设置高一点,thingsboard官方那个收费的版本不就是这样的吗?租户配置在系统层,系统管理员可以创建租户配置,然后使用租户配置为多个租…

centos7安装kubeadm

centos7安装kubeadm 一、基础设置 1、设置主机名 hostnamectl set-hostname master hostnamectl set-hostname node01vim /etc/hosts 192.168.198.169 master 192.168.198.170 note01hostnamectl hostnamectl 是在 centos7 中新增加的命令&#xff0c;它是是用来管理给定主机…

2023年我花费数小时整理的Java常用类进阶学习文档,你学会了吗?

文章目录1. 基本类型的包装类1.1 概念1.2 常用的属性1.3 常用的方法1.4 自动装箱和自动拆箱2. 字符串类2.1 String 类2.2 StringBuilder类2.3 StringBuffer类2.4 StringBuilder 的扩容机制3. 数字常用类3.1 Math 类3.2 Radom 类4. 枚举类5. 日期类5.1 Date 类5.2 DateFormat 类…

基于微信小程序的小区租拼车管理信息系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

学习理解10G Ethernet Subsystem之IEEE1588

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 学习理解10G Ethernet Subsystem之IEEE1588前言原理简介one step/two step1PPSIP 设置前言 1588大多是走在报文中&#xff0c;主要通过一些报文交互来完成同步过程&#xff…

在Docker中安装Gitea

目录在Docker中安装Gitea1、拉取最新Gitea官方镜像2、实例化一个Gitea容器3、Gitea需要数据源&#xff0c;因此使用mysql作为后端数据库4、在mysql中创建一个新数据库&#xff0c;起名gitea5、访问Gitea主页http://host:3000&#xff0c;进入初始配置页在Docker中安装Gitea 1、…

【自学Python】Python位运算符

Python位运算符 Python位运算符教程 在 Python 中&#xff0c;位运算符主要是用于 数值类型 的二进制的运算。 Python位运算符语法 位运算符说 明案例备注&按位与a & b返回 a 和 b 相与的结果|按位或a | b返回 a 和 b 相或的结果^按位异或a ^ b返回 a 和 b 相异或的…

FFMpeg 实现视频编码、解码

FFMpeg 作为音视频领域的开源工具&#xff0c;它几乎可以实现所有针对音视频的处理&#xff0c;本文主要利用 FFMpeg 官方提供的 SDK 实现音视频最简单的几个实例&#xff1a;编码、解码、封装、解封装、转码、缩放以及添加水印。 接下来会由发现问题&#xff0d;&#xff1e;…

Java中的equals()方法和hashCode的关系

文章目录1.Java中equals()方法比较的是什么&#xff1f;2.equals方法和hashcode的关系3.什么是hashCode3.1 hashcode有什么作用呢&#xff1f;4.关于重写equals()方法的两条规范5.代码实例1.Java中equals()方法比较的是什么&#xff1f; 最直接的回答就是看调用equals()方法的…

联合评测 DapuStor Roealsen5 NVMe SSD在GreatSQL数据据库中的应用探索

1、合作背景 万里开源软件有限公司 ​ 北京万里开源软件有限公司&#xff0c;是专注于国产自主可控数据库产品研发超 20年的国家高新技术企业&#xff0c;参与多个国家级的数据库行业标准制定工作。本次用于测试的 GreatSQL 开源数据库是适用于金融级应用的国内自主 MySQL 版…

Redis 的基础数据结构(一) 可变字符串、链表、字典

这周开始学习 Redis&#xff0c;看看Redis是怎么实现的。所以会写一系列关于 Redis的文章。这篇文章关于 Redis 的基础数据。阅读这篇文章你可以了解&#xff1a; 动态字符串&#xff08;SDS&#xff09;链表字典 三个数据结构 Redis 是怎么实现的。 SDS SDS &#xff08;S…

从0到1完成一个Node后端(express)项目(二、下载数据库、navicat、express连接数据库)

往期 从0到1完成一个Node后端&#xff08;express&#xff09;项目&#xff08;一、初始化项目、安装nodemon&#xff09; 下载MySQL数据库&#xff08;PHPstudy&#xff09; 我们这里不采用官网下载MySQL的方式、因为启动不方便&#xff0c;而且多版本的MySQL大家也不好去管…

【MyBatis】| MyBatis概述、MyBatis⼊⻔程序

一、MyBatis概述1. 框架在⽂献中framework被翻译为框架。Java常⽤框架&#xff1a;SSM三⼤框架&#xff1a;Spring SpringMVC MyBatisSpringBootSpringCloud等。。。。框架其实就是对通⽤代码的封装&#xff0c;提前写好了⼀堆接⼝和类&#xff0c;我们可以在做项⽬的时候直接…

Frida零基础入门教程

阅读这篇文章,不仅能了解frida是什么,还能知道如何搭建Frida运行换以及学会用frida进行简单的java/native hook实战。 Xposed大家不陌生,在手机上运行的Hook框架,Xposed插件编写完成并在手机上通过hook框架加载,打开指定应用就能实现代码注入,也就是说Xposed插件的代码是…

FFmpeg进行笔记本摄像头+麦克风实现流媒体直播服务,展示在浏览器上。

0、本文中所用软件下载包 1、前置工作 1.1 下载 ffmpeg&#xff0c;Download FFmpeg&#xff0c; 1.1.1配置ffmpeg如下图 1.1.2测试ffmpeg 安装成功&#xff1a;ffmpeg -version 1.1.3 使用FFmpeg获取本地摄像头设备 ffmpeg -list_devices true -f dshow -i dummy video和aud…

【JavaSE】Java到底是值传递还是引用传递?

【JavaSE】Java到底是值传递还是引用传递&#xff1f; 文章目录【JavaSE】Java到底是值传递还是引用传递&#xff1f;一&#xff1a;基本数据类型和引用数据类型区别二&#xff1a;案例1&#xff1a;传递基本类型2&#xff1a;传递引用类型三&#xff1a;引用传递是怎么样的&am…

【Linux】进程信号万字详解(下)

&#x1f387;Linux&#xff1a; 博客主页&#xff1a;一起去看日落吗分享博主的在Linux中学习到的知识和遇到的问题博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 看似不起波澜的日复一日&#xff0c;一定会在某一天让你看见坚持…