Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • 手写Spring

  • SSM

  • SpringBoot

  • JavaWeb

    • 前端基础
    • 后端基础
    • Thymeleaf视图模板
    • session会话
    • Servlet
    • Servlet优化
      • 反射
      • Dispatcher控制器
      • 提取视图资源处理
      • 统一获取请求过程传的参数
    • 依赖注入
    • 过滤器
    • 监听器
    • 正则表达式
    • 项目经验
  • Spring
  • JavaWeb
phan
2023-05-15
目录

Servlet优化

# Servlet优化

# 反射

先前对应一个功能会请求一个servlet再找DAO,代码冗余。优化的做法是可以用一个统一的servlet处理,不同功能由这个servlet中的不同方法处理响应,在会话中存放一个操作字段,来通过swtich跳转对应方法。

上述方法switch过长时,可以使用反射技术获取方法名直接invoke调用。

Method[] methods = this.getClass().getDeclaredMethods();
	for (Method m : methods) {
        String methodname = m.getName();
        if (methodname.equals(operate)) {
            try {
            m.invoke(this, req, resp);
            }
          	catch (IllegalAccessException e) {
            throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
            }
        	return;
        }
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Dispatcher控制器

通过servletpath(add.do)=>截取到add=>把add对应上它的controller。好处在于当有多个实体的servlet时,不需要一个个单独写反射代码,全部由工厂生成。

  • 设置配置文件
  • t通过类加载器反射,解析加载配置文件
  • 获取一个个bean,并实例化对应controller对象,和key丢到map中
  • 通过servletpath获取key,然后从map中找到对应的对象。
protected void init(){
//通过类加载去读取资源文件
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
//创建工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//创建DocumentBuilder对象
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//创建document对象
Document document=documentBuilder.parse(inputStream);
//获取所有bean节点
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");
        //通过类名反射创建一个实例对象
        Object beanObj = forName(className).newInstance();
        //beanMap<controllerName,controllerObject>
        beanMap.put(beanId, beanObj);
    }
}
----------
protected void service(HttpServletRequest req, HttpServletResponse resp){
//通过ServletPath()可以获取页面请求url的路径
String servletpath = req.getServletPath();
String controllerName = servletpath.substring(1,servletpath.lastIndexOf(".do"));
Object controllerBeanobj = beanMap.get(servletPath);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

这里bean节点的集合NodeList分类两类节点,一类是文本节点,一类是元素节点。NodeList类似于数组,通过NodeList.item(i)遍历,NodeList.getLength()获取长度。然后把每个节点强转成Element类型,就可以通过getAttributr()来读取每一个bean标签里的属性值。

# 提取视图资源处理

把所有的重定向和使用Thymeleaf视图都交给Dispatcher进行处理,具体做法是:

  • 设置controller中所有的方法都会返回一个String,把对应要重定向的资源或者是视图资源以String的方式以为返回值输出。
  • 在DispatcherController中对于重定向处理,则使用中央控制器的HttpServletResponse来进行,对于视图资源请求则直接调用父类方法即可。
Object returnObj = method.invoke(controllerBeanobj, req);
String methodReturnStr = (String) returnObj;
//视图处理
if (methodReturnStr.startsWith("redirect:")) {
    String redirectStr=methodReturnStr.substring("redirect:".length());
    resp.sendRedirect(redirectStr);
}
else {
    super.processTemplate(methodReturnStr, req, resp);
}
1
2
3
4
5
6
7
8
9
10

# 统一获取请求过程传的参数

把所有业务方法中通过req.getParameter获取页面参数数据的部分都抽取出去,由Dispatcher控制器统一负责实现,要解决的问题:

  • 要知道每个DeclaredMethod方法的参数名,参数类型。在idea中java-compiler添加-parameters,编译时能够通过method.getParameters()获取到的参数包含名称信息。
  • 参数名称:parameter.getName()。参数类型:parameter.getType().getName()
for (int i = 0; i < parameters.length; i++) {
    Parameter parameter = parameters[i];
    if (parameter.getName().equals("req")) {
        parametersValues[i] = req;
    }else if(parameter.getName().equals("resp")){
        parametersValues[i] = resp;
    }else if(parameter.getName().equals("session")){
        parametersValues[i] = req.getSession();
    }else {
        Object paraValue;
        //针对类型名来初始化对应实参的类型
if (parameter.getType().getName().equals("java.lang.Integer")) {
  paraValue= Integer.parseInt(req.getParameter(parameter.getName()));
        }
        parametersValues[i] = req.getParameter(parameter.getName());
    }}
//将参数数组传入方法中
Object returnObj = method.invoke(controllerBeanobj, parametersValues);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
编辑 (opens new window)
#JavaWeb
上次更新: 2023/12/15, 15:49:57
Servlet
依赖注入

← Servlet 依赖注入→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式