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

JavaWeb综合案例-Servlet优化

在这里插入图片描述

将WebServlet的访问路径不要写死,写成通配符的形式

1. 反射笔记(后续代码会用到该机制)

1.1 基础概念

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

言简意赅的说法就是:反射就是将Java类中各个成分映射成为一个个的Java对象

  1. 成员变量
  2. 方法、构造方法
  3. 包等等

但在此之前,先要把class类以及类的加载机制,在此基础上再探讨如何通过反射获取class类以及类的成员变量等等

1.1.1 Class类

Class类是一个实实在在的类,存在于java.lang包中;
Class类的实例标识java应用运行时的类或接口;
数组同样也被映射为class对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象;
手动编写的类被编译后会产生一个Class对象,其表示的是创建的类的类型信息,而且这个Class对象保存在同名.class的文件中(字节码文件);
每个通过关键字class标识的类,在内存中有且只有一个与之对应的Class对象来描述其类型信息,无论创建多少个实例对象,其依据的都是用一个Class对象;
Class类只存私有构造函数,因此对应Class对象只能有JVM创建和加载
Class类的对象作用是运行时提供或获得某个对象的类型信息,这点对于反射技术很重要

1.1.2 类加载

在这里插入图片描述

1.1.3 反射的使用

我们如何通过反射获取Class类对象以及类中的成员变量、方法、构造方法?

在类加载的时候,jvm会创建一个class对象;
在Java中,Class类与java.lang.reflect类库一起对反射技术进行了全力的支持;
常用的类主要有Constructor类:表示的是Class 对象所表示的类的构造方法,利用它可以在运行时动态创建对象;
Field类:表示Class对象所表示的类的成员变量,通过它可以在运行时动态修改成员变量的属性值(包含private);
Method类:表示Class对象所表示的类的成员方法,通过它可以动态调用对象的方法(包含private)

1.1.4 反射机制的执行流程

在这里插入图片描述

1.1.5 反射小结

反射类及反射方法的获取,都是通过从列表中搜寻查找匹配的方法,所以查找性能会随类的大小方法多少而变化;
每个类都会有一个与之对应的Class实例,从而每个类都可以获取method反射方法,并作用到其他实例身上;
反射也是考虑了线程安全的,放心使用;
反射使用软引用relectionData缓存class信息,避免每次重新从jvm获取带来的开销;
反射调用多次生成新代理Accessor, 而通过字节码生存的则考虑了卸载功能,所以会使用独立的类加载器;
当找到需要的方法,都会copy一份出来,而不是使用原来的实例,从而保证数据隔离;
调度反射方法,最终是由jvm执行invoke0()执行;

2. Servlet优化

在这里插入图片描述

问题一:之前在servlet中写WebServlet资源路径固定,如何解决?
路径不要写成固定,写成通配符形式
如:/brand/*

问题二:获取最后一段路径,也就是方法名称,获取了方法名称怎样执行方法?
通过反射机制,获取BrandServlet的字节码文件,获取其方法的method对象,method.invoke()就可以调用方法了

问题三:BrandServlet extends HttpServlet,而HttpServlet在对应的service方法中通过request的请求方式做了方法分发,例如post请求就是采用doPost(),那么在之前的servlet中我们只能执行doGet()doPost()方法,但现在不写这两个方法,而是写自定义方法,这时就不能继承HTTPServlet了,方法分发的功能也不采用了
而是采用自定义的Servlet,使用请求路径进行方法分发,替换HttpServlet的根据请求方式进行方法分发

针对问题三

不再采用请求方式进行方法分发,而是采用请求路径进行方法分发,所以这里重写service方法

下面代码思想非常关键

/**
 * 替换HttpServlet,根据请求的最后一段路径来进行方法分发
 */

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? selectAll?

        //3. 执行方法

        // 谁调用我(this),我代表谁
        // BrandServlet会被Tomcat服务器调用,而它继承了BaseServlet
        // 其中BaseServlet的service方法也是由Tomcat服务器调用,由BrandServlet调用
        // 所以this指代的是BrandServlet
        //System.out.println(this);

        //3.1 获取BrandServlet /UserServlet 字节码对象 Class
        Class<? extends BaseServlet> cls = this.getClass();
        //3.2 获取方法 Method对象
        try {
            // 获取方法名,参数
            Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //3.3 执行方法
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}

最后

修改前端页面的URL路径即可


http://www.kler.cn/a/18222.html

相关文章:

  • python高效处理大数据:将Excel10万数据分批插入MySQL数据库的实战代码
  • ArcGIS Pro属性表乱码与字段名3个汉字解决方案大总结
  • 灰狼优化算法
  • 应用程序部署(IIS的相关使用,sql server的相关使用)
  • unity基础,点乘叉乘。
  • 【学习笔记】数据结构(七)
  • Selenium:三种等待方式
  • 【C++学习】文件操作
  • c++ cuda加速学习笔记
  • cookie和session的简单介绍(lnh25)
  • OJ练习第93题——数青蛙
  • Docker启动多个mysql容器
  • (六)【平衡小车制作】位置式PID、直立环与速度环编程
  • CompletableFutrue异步处理
  • React 第三方插件 —— Cron 表达式生成器(qnn-react-cron)
  • Java 多线程知识
  • K8S:K8S自动化运维容器化(Docker)集群程序
  • 《python爬虫练习》之随机的User-Agent请求头
  • SOFA Weekly|开源之夏 MOSN 与 Layotto 项目简介、社区会议预告、社区本周贡献
  • java计算矩形的面积和周长的方法
  • OpenFeign详解
  • 前端基于uniapp[uniPush]实现APP消息推送(安卓、IOS)
  • 为什么选择云计算
  • 什么是镜像?阿里云服务器镜像是什么?镜像怎么选?
  • 时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比)
  • 全网最火,Web自动化测试驱动模型详全,一语点通超实用...