JavaWeb Servlet的getInitParameter、业务层、控制反转IOC和依赖注入DI

目录

  • 1. Servlet的getInitParameter
  • 2. 业务层
  • 3. 控制反转IOC和依赖注入DI
    • 3.1 背景
    • 3.2 实现如下
    • 3.3 原理

1. Servlet的getInitParameter

Servlet有两个getInitParameter

  1. 一个是servletContext.getInitParameter,获取context-param的全局参数
  2. 一个是servletConfig.getInitParameter,取init-param的servlet参数
    示例如下:

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><context-param><param-name>global-name</param-name><param-value>global-value</param-value></context-param><servlet><servlet-name>Demo01Servlet</servlet-name><servlet-class>com.hh.javaWebTest.demo.Demo01Servlet</servlet-class><init-param><param-name>servlet-name1</param-name><param-value>servlet-value1</param-value></init-param><init-param><param-name>servlet-name2</param-name><param-value>servlet-value2</param-value></init-param></servlet><servlet-mapping><servlet-name>Demo01Servlet</servlet-name><url-pattern>/demo01</url-pattern></servlet-mapping></web-app>

Demo01.java

package com.hh.javaWebTest.demo;import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;/*
// web.xml和注解选择一种
@WebServlet(urlPatterns = {"/demo01"} ,initParams = {@WebInitParam(name="servlet-name1",value="servlet-value1"),@WebInitParam(name="servlet-name2",value="servlet-value2")}
)*/
public class Demo01Servlet extends HttpServlet {@Overridepublic void init() throws ServletException {// 获取context-param的全局参数// request.getServletContext();// request.getSession().getServletContext();ServletContext servletContext = getServletContext();String globalValue = servletContext.getInitParameter("global-name");System.out.println("globalValue = " + globalValue);    // globalValue = global-value// 获取init-param的servlet参数ServletConfig servletConfig = getServletConfig();String servletValue1 = servletConfig.getInitParameter("servlet-name1");System.out.println("servletValue1 = " + servletValue1);    // servletValue1 = servlet-value1}
}

2. 业务层

Model1介绍:典型的就是JSP,用HTML(CSS、JS) + Java代码(将数据提供给页面的代码,加上和数据库通信的代码)。这样的Java代码显得很乱

Model2,即MVC: Model(模型) + View(视图) + Controller(控制器)

  • 视图层:用于做数据展示以及和用户交互的一个界面
  • 控制层:能够接受客户端的请求,具体的业务功能还是需要借助于模型组件来完成
  • 模型层:模型分为很多种:有比较简单的pojo/vo(value object),有业务模型组件(BO业务对象),有数据访问层组件(DAO数据访问对象)、有Service传输给Controller的组件(DTO数据传输对象,一般用于前后端分离)

区分业务对象和数据访问对象:

  1. DAO中的方法都是细粒度方法。一个方法只考虑一个操作,比如insert添加
  2. BO中的方法属于业务方法,粒度是比较粗的,对应复杂的业务逻辑处理,如注册新用户,需要调用很多DAO,和做很多逻辑操作

3. 控制反转IOC和依赖注入DI

3.1 背景

在软件系统中,层与层之间是存在依赖的。我们也称之为耦合。但我们系统架构设计的一个原则是: 高内聚低耦合。即层内部的组成应该是高度聚合的,而层与层之间的关系应该是低耦合的,最理想的情况0耦合。我们可以通过控制反转IOC和依赖注入DI来实现高内聚低耦合

3.2 实现如下

FruitService.java

package com.hh.javaWebTest.service;public interface FruitService {
}

FruitServiceImpl.java

package com.hh.javaWebTest.service.impl;import com.hh.javaWebTest.service.FruitService;public class FruitServiceImpl implements FruitService {
}

FruitController.java。里面有一个FruitService类型的属性

package com.hh.javaWebTest.controller;import com.hh.javaWebTest.service.FruitService;
......省略部分......public class FruitController {private FruitService fruitService = null;......省略部分......}

applicationContext.xml。定义了两个bean,同时定义了fruitService是FruitController的属性

<?xml version="1.0" encoding="utf-8"?><beans><bean id="fruitService" class="com.hh.javaWebTest.service.impl.FruitServiceImpl"/><!--Node节点:Element元素节点Text文本节点--><!-- 子节点总共有5个。空白Text、注释Text、空白Text、property元素节点、空白Text--><bean id="fruit" class="com.hh.javaWebTest.controller.FruitController"><!-- property标签用来表示属性;name表示属性名;ref表示引用其他bean的id值 --><property name="fruitService" ref="fruitService"/></bean>
</beans>

BeanFactory.java

package com.hh.javaWebTest.ioc;public interface BeanFactory {Object getBean(String id);
}

ClassPathXmlApplicationContext.java。解析applicationContext.xml,将bean放到beanMap中,然后给各个bean设置property属性

package com.hh.javaWebTest.ioc;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.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;public class ClassPathXmlApplicationContext implements BeanFactory {private Map<String, Object> beanMap = new HashMap<>();public ClassPathXmlApplicationContext() {try {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);}}// 组装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");// 获取子节点NodeList beanChildNodeList = beanElement.getChildNodes();for (int j = 0; j < beanChildNodeList.getLength(); j++) {Node beanChildNode = beanChildNodeList.item(j);// 从子节点找到property节点if (beanChildNode.getNodeType() == Node.ELEMENT_NODE && "property".equals(beanChildNode.getNodeName())) {Element propertyElement = (Element) beanChildNode;String propertyName = propertyElement.getAttribute("name");String propertyRef = propertyElement.getAttribute("ref");// 获取属性的值Object refObj = beanMap.get(propertyRef);// 获取到主节点的beanObject beanObj = beanMap.get(beanId);Class beanClazz = beanObj.getClass();// 获取到主节点的bean的属性Field propertyField = beanClazz.getDeclaredField(propertyName);propertyField.setAccessible(true);// 设置属性的值propertyField.set(beanObj, refObj);}}}}} catch (Exception e) {e.printStackTrace();}}@Overridepublic Object getBean(String id) {return beanMap.get(id);}
}

DispatcherServlet.java。不在DispatcherServlet进行applicationContext.xml的解析,而是直接从BeanFactory获取bean

package com.hh.javaWebTest.servlet;import com.hh.javaWebTest.ioc.BeanFactory;
import com.hh.javaWebTest.ioc.ClassPathXmlApplicationContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
......省略部分......@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {private BeanFactory beanFactory;@Overridepublic void init() throws ServletException {// 手动进行ViewBaseServlet的初始化super.init();beanFactory = new ClassPathXmlApplicationContext();}@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {......省略部分......// 获取fruit对应的classObject controllerBeanObj = beanFactory.getBean(servletPath);......省略部分......}
}

3.3 原理

控制反转:

  1. 之前在FruitController中,我们创建Service属性, FruitService fruitService = new FruitServiceImpl()。fruitService的作用域(生命周期)是FruitController实例级别
  2. 之后我们在applicationContext.xml中定义了这个fruitService。然后通过解析XML,产生fruitService实例。所有bean都存放在beanMap中,这个beanMap在一个BeanFactory中
  3. 因此,我们改变了之前的service实例等他们的作用域(生命周期)。控制权从程序员转移到BeanFactory。这个现象我们称之为控制反转

依赖注入:

  1. 之前在FruitController中,我们创建Service属性, FruitService fruitService = new FruitServiceImpl()。那么,FruitController和FruitService存在耦合
  2. 之后,我们将代码修改成FruitService fruitService = null;
  3. 然后,在配置文件中给FruitController这个bean定义了属性fruitService的值,解析配置文件,就可以将fruitService变量注入到FruitController的属性中,实现了解耦

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32 SPI读取SD卡

七个响应类型&#xff1a; R1 Response (Normal Response): R1响应是最基本的响应&#xff0c;包含一个字节的状态位&#xff0c;用于指示命令是否成功执行。常用。最高位为0。最低位为1表示是空闲状态。其他位是各种错误提示。 R1b Response (Normal with Busy): 类似于R1&a…

深入浅出 Spring (二)| 依赖注入(DI)、自动装配

3. 依赖注入&#xff08;DI&#xff09; 3.1 概念 依赖注入&#xff08;Dependency Injection,DI&#xff09;。 依赖&#xff1a;bean对象的创建依赖于容器&#xff01;注入&#xff1a;bean对象中的所有属性&#xff0c;由容器来注入&#xff01; 创建子项目 spring04-DI…

线性代数期末复习 [基础篇]

关于第六点: AXB 在期末考试中一般A都是可逆的 我们可以先把A的逆求出来,X A − 1 B A^-1B A−1B,或者 (A,B) -> r (E, A − 1 B A^-1B A−1B) 如果A矩阵不可逆,转变为方程组求解问题,假设都是二维矩阵 A(x1,x2) (b1,b2) Ax1 b1,Ax2 b2 XAB 如果A可逆,直接XB A − 1 A^-…

V90伺服PN版组态配置<一>

1、添加PLC之后&#xff0c;继续博图中网络视图中添加新设备&#xff0c;添加伺服驱动器组态设备 2、SINAMICS V90 PN V1.0 3、修改驱动器的IP地址。 【注意】 在项目中提前做好项目规划&#xff0c;如PLC设备从192.168.0.1开始&#xff0c;顺序递增------个位数都是CPU设备…

深度学习笔记(12)——深度学习概论

深度学习概论 深度学习关系&#xff1a; 为什么机器人有一部分不在人工智能里面&#xff1a;机器人技术是一个跨学科的领域&#xff0c;它结合了机械工程、电子工程、计算机科学以及人工智能&#xff08;AI&#xff09;等多个领域的知识。 并不是所有的机器人都依赖于人工智能…

TCP-UDP调试工具推荐:Socket通信测试教程(附详细图解)

前言 在网络编程与应用开发中&#xff0c;调试始终是一项不可忽视的重要环节。尤其是在涉及TCP/IP、UDP等底层网络通信协议时&#xff0c;如何确保数据能够准确无误地在不同节点间传输&#xff0c;是许多开发者关注的核心问题。 调试的难点不仅在于定位连接建立、数据流控制及…

使用three.js 实现vr全景图展示,复制即可用

1.实现效果 2.代码 1.npm安装three.js npm install three 2.引入three.js import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls 3.初始化模型 init(val) {this.container document.querySelector(.container)// 初始…

1月第二讲:WxPython跨平台开发框架之图标选择界面

1、图标分类介绍 这里图标我们分为两类&#xff0c;一类是wxPython内置的图标资源&#xff0c;以wx.Art_开始。wx.ART_ 是 wxPython 提供的艺术资源&#xff08;Art Resource&#xff09;常量&#xff0c;用于在界面中快速访问通用的图标或位图资源。这些资源可以通过 wx.ArtP…

C语言优化技巧--达夫设备(Duff‘s Device)解析

1983年&#xff0c;一位程序员TomDuff&#xff08;曾在贝尔实验室和星球大战母公司卢卡斯影业就职过&#xff09;&#xff0c;在参与图形渲染的软件中尝试优化图像数据传输到帧缓冲区的过程中遇到了性能瓶颈&#xff0c;写下了一段奇怪的代码&#xff1a; void send( int * to…

[硬件] DELL BIOS 相关注意事项

前言 前段时间重装系统. DELL BIOS属实资料少, 又难用. 这里给出相关的注意事项, 并且配上图片. BIOS相关注意事项 进入BIOS ESC/F2/ F12. 都可以进入BIOS, 当进U盘的入Win PE系统时, 使用F12 效果更佳. 关闭安全模式 切换到Boot Configuration选项,将Secure Boot选项off选…

一个完美的自动化测试框架应该怎么写?

一、什么是自动化测试框架&#xff1f; 自动化测试框架是为自动化测试用例或者脚本提供执行环境而搭建的基础设施。自动化测试框架有助于有效地开发、执行和报告自动化测试用例。 优点&#xff1a; 代码复用 提高测试效率 更高的测试覆盖率 维护成本低 更早发现和记…

从0开始的docker镜像制作-ubuntu22.04

从0开始的docker镜像制作-ubuntu22.04 一、拉取基础ubuntu22.04镜像二、进入拉取的docker镜像中&#xff0c;下载自己需要的安装包三、安装需要的系统软件四、打包现有镜像为一个新的镜像五、推送打包的镜像到私有docker服务器1.编辑docker文件&#xff0c;使其允许http传输和对…

使用exe4j将jar转成exe、java打包exe

1、maven打包 需要配置以下插件&#xff0c;注意skip为false 插件配置中设置 <skip>true</skip> 时&#xff0c;实际上是告诉 Maven 在构建过程中跳过 spring-boot-maven-plugin 插件的执行。也就是说&#xff0c;Maven 在打包时不会将项目打包成可执行的 JAR 文…

微信小程序调用 WebAssembly 烹饪指南

我们都是在夜里崩溃过的俗人&#xff0c;所幸终会天亮。明天就是新的开始&#xff0c;我们会变得与昨天不同。 一、Rust 导出 wasm 参考 wasm-bindgen 官方指南 https://wasm.rust-lang.net.cn/wasm-bindgen/introduction.html wasm-bindgen&#xff0c;这是一个 Rust 库和 CLI…

Cherno C++学习笔记 P48 如何让vector运行的更快

这一篇文章当中我们会讲到有关于vector的使用优化问题&#xff0c;如何能够让vector运行得更快。C优化是一个非常非常复杂的问题&#xff0c;最重要的是要了解环境&#xff0c;要知道事情是如何发生的&#xff0c;以及我们应该怎么做。当然我们今天会做的事情其实只是触及表面。…

MyBatis执行一条sql语句的流程(源码解析)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MyBatis执行一条sql语句的流程&#xff08;源码解析&#xff09; MyBatis执行sql语句的流程加载配置文件加载配置文件的流程 创建sqlsessionFactory对象解析Mapper创建sqlses…

淺談Cocos2djs逆向

前言 簡單聊一下cocos2djs手遊的逆向&#xff0c;有任何相關想法歡迎和我討論^^ 一些概念 列出一些個人認為比較有用的概念&#xff1a; Cocos遊戲的兩大開發工具分別是CocosCreator和CocosStudio&#xff0c;區別是前者是cocos2djs專用的開發工具&#xff0c;後者則是coco…

吊舱激光测距核心技术详解!

一、核心技术 吊舱激光测距的核心技术主要体现在激光发射与接收、信号处理与距离计算、以及数据校正与优化等方面。 激光发射与接收&#xff1a; 激光发射器&#xff1a;产生经过调制的激光束&#xff0c;该激光束具有特定的频率和波形。这些激光束被投射到目标物体上。 光…

SpringAI从入门到熟练

学习SpringAI的记录情况 文章目录 前言 因公司需要故而学习SpringAI文档&#xff0c;故将自己所见所想写成文章&#xff0c;供大佬们参考 主要是为什么这么写呢&#xff0c;为何不抽出来呢&#xff0c;还是希望可以用的时候更加方便一点&#xff0c;如果大家有需求可以自行去…

如何使用大语言模型进行事件抽取与关系抽取

诸神缄默不语-个人CSDN博文目录 文章目录 1. 什么是事件抽取与关系抽取&#xff1f;2. 示例&#xff1a;使用大语言模型进行事件抽取与关系抽取 1. 什么是事件抽取与关系抽取&#xff1f; 事件抽取是指从文本中识别出与某些“事件”相关的信息。这些事件通常包括动作、参与者、…