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.mzph.cn/diannao/65877.shtml

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

相关文章

前端-动画库Lottie 3分钟学会使用

目录 1. Lottie地址 2. 使用html实操 3. 也可以选择其他的语言 1. Lottie地址 LottieFiles: Download Free lightweight animations for website & apps.Effortlessly bring the smallest, free, ready-to-use motion graphics for the web, app, social, and designs.…

在Ubuntu 18.04.6 LTS安装OpenFace流程

一、修改配置:将gcc8&#xff0c;g8作为默认选项 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100 sudo update-alternatives --config gcc 选择版本&#xff0c;再查看gcc --version sudo update-alternatives --install /usr/bin/g g /usr/bin/g-…

Flink源码解析之:如何根据JobGraph生成ExecutionGraph

Flink源码解析之&#xff1a;如何根据JobGraph生成ExecutionGraph 在上一篇Flink源码解析中&#xff0c;我们介绍了Flink如何根据StreamGraph生成JobGraph的流程&#xff0c;并着重分析了其算子链的合并过程和JobGraph的构造流程。 对于StreamGraph和JobGraph的生成来说&…

生成式AI与RAG架构:如何选择合适的向量数据库?

大规模语言模型和情境感知的AI应用程序推动了检索增强生成&#xff08;RAG&#xff09;架构的发展&#xff0c;使其成为关注的焦点。RAG将生成模型的力量与外部知识相结合&#xff0c;允许系统生成更加具体且与情境相关的回应。 向量数据库构成了RAG系统的基石。选择正确的向量…

电脑找不到mfc110.dll文件要如何解决?Windows缺失mfc110.dll文件快速解决方法

一、mfc110.dll文件的重要性 mfc110.dll&#xff0c;全称Microsoft Foundation Class Library 110&#xff0c;是Microsoft Visual C Redistributable for Visual Studio 2012的一部分。这个动态链接库&#xff08;DLL&#xff09;文件对于支持基于MFC&#xff08;Microsoft F…

大模型Weekly 03|OpenAI o3发布;DeepSeek-V3上线即开源!

大模型Weekly 03&#xff5c;OpenAI o3发布&#xff1b;DeepSeek-V3上线即开源&#xff01;DeepSeek-V3上线即开源&#xff1b;OpenAI 发布高级推理模型 o3https://mp.weixin.qq.com/s/9qU_zzIv9ibFdJZ5cTocOw?token47960959&langzh_CN 「青稞大模型Weekly」&#xff0c;持…

4、上一个接口返回值,作为下一个方法(接口)的变量

import requestsclass TestCase:# 设置1个类变量B "初始值"def test1(self):url "**这里是接口url**"params {"type": "json"}resp1 requests.get(urlurl, paramsparams)# .json()用于将服务器返回的 JSON 格式的响应内容解析为 P…

USB 中断传输的 PID 序列

中断传输的 PID 序列 端点在初始化后&#xff0c;从 DATA0 开始&#xff0c;每成功执行一个事务&#xff0c;数据包序列翻转一次&#xff08;从 DATA0 变为DATA1 或从 DATA1 变为 DATA0)。 数据翻转和传输的个数没有直接关系&#xff0c;只由端点在初始化后处理的总数决定。 …

SAP财务凭证的更改、冲销的方式

文章目录 一、财务凭证更改二、财务凭证冲销 【SAP系统研究】 #SAP #FICO #SAP财务 一、财务凭证更改 &#xff08;1&#xff09;已经过账的财务凭证 FB02&#xff1a;过完帐的允许更改的地方有限&#xff0c;只有凭证抬头文本、参照、分配、文本、原因代码等。 &#xff0…

OpenCV的人脸检测模型FaceDetectorYN

OpenCV的人脸检测模型FaceDetectorYN 1. 官网地址2. 如何使用2.1.到opencv_zoo下载模型文件和代码2.2. 下载文件展示2.3. 修改了demo支持读取视频文件&#xff0c;默认是图片和摄像头## 2.4 效果展示 1. 官网地址 https://docs.opencv.org/4.x/df/d20/classcv_1_1FaceDetector…

vue使用el-select下拉框自定义复选框

在 Vue 开发中&#xff0c;高效且美观的组件能极大地提升用户体验和开发效率。在vue中使用elementplus 的 el-select下拉框实现了一个自定义的多选下拉框组件。 一、代码功能概述 这段代码创建了一个可多选的下拉框组件&#xff0c;通过el-select和el-checkbox-group结合的方…

01-英语准备

首先是自我介绍&#xff0c;中英文都可以&#xff0c;建议提前打好草稿然后开始背&#xff0c;模板网上有很多&#xff0c;可以自行查找&#xff0c;主要就是个人的一些基本情况&#xff0c;竞赛获奖经历&#xff0c;感兴趣的方向等等。接下来就是老师问的一些问题了。 做个英文…

亚信科技研发智能化实践之路

作者&#xff1a;亚信科技高级研发经理史伟星 亚信科技是一家专注于 To B 业务的公司。公司 1993 年成立&#xff0c;于 2000 年成为纳斯达克首批上市的高科技企业。2010 年&#xff0c;通过持续深耕&#xff0c;成为中国领先的通信软件产品服务商。2014 年&#xff0c;完成私…

==和===的区别,被坑的一天

在 JavaScript 中&#xff0c; 和 都用于比较两个值&#xff0c;但它们有一个重要的区别&#xff1a; 1. (宽松相等运算符) 进行比较时&#xff0c;会 自动类型转换&#xff08;也叫做强制类型转换&#xff09;&#xff0c;即如果比较的两个值的类型不同&#xff0c;JavaScr…

如何不修改模型参数来强化大语言模型 (LLM) 能力?

前言 如果你对这篇文章感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 大语言模型 (Large Language Model, LLM, e.g. ChatGPT) 的参数量少则几十亿&#xff0c;多则上千亿&#xff0c;对其的训…

使用Python和OpenCV进行视觉图像分割

简介&#x1f381; 在图像处理领域&#xff0c;图像分割是一项基础且关键的技术&#xff0c;它涉及到将图像划分为若干个具有特定属性的区域。本文将通过一个实践项目&#xff0c;展示如何使用Python编程语言&#xff0c;结合OpenCV库&#xff0c;对一张玫瑰花的图片进行图像分…

代码解析:安卓VHAL的AIDL参考实现

以下内容基于安卓14的VHAL代码。 总体架构 参考实现采用双层架构。上层是 DefaultVehicleHal&#xff0c;实现了 VHAL AIDL 接口&#xff0c;并提供适用于所有硬件设备的通用 VHAL 逻辑。下层是 FakeVehicleHardware&#xff0c;实现了 IVehicleHardware 接口。此类可模拟与实…

vLLM结构化输出(Guided Decoding)

简介 vLLM 的结构化输出特性是通过“引导式解码”&#xff08;Guided Decoding&#xff09;实现的&#xff0c;这一功能允许模型在生成文本时遵循特定的格式约束&#xff0c;例如 JSON 模式或正则表达式&#xff0c;从而确保生成的内容符合预期的结构化要求。 后端引擎 启动…

部署SenseVoice

依赖 Conda cuda pythor 查看GPU版本-CSDN博客 创建虚拟conda环境 conda create --name deeplearn python3.10 conda activate deeplearn git clone https://github.com/FunAudioLLM/SenseVoice.git cd SenseVoice pip install -r requirements.txt pip install gradio pip …

基于51单片机(STC32G12K128)和8X8彩色点阵屏(WS2812B驱动)的小游戏《贪吃蛇》

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、定时器02、矩阵按键模块3、8X8彩色点阵屏 四、主函数总结 系列文章目录 前言 《贪吃蛇》&#xff0c;一款经典的、怀旧的小游戏&#xff0c;单片机入门必写程序。 以《贪吃蛇》为载体&#xff0c;熟悉各种屏幕…