分布式项目 09.服务器之间的通信和三个工具类

news2024/11/28 2:28:36

在这里插入图片描述
项目的结构:1.通过Nginx首先把访问首页的请求发送到前端web服务器,2.web服务器会根据请求的url中的一些细节,来把相关的请求发送到相关的服务器中,3.相关的服务器会处理业务,并且返回结果到web服务器中,最后在web服务器中去显示。

步骤:
01.在Nginx中配置首页的web服务器:(因为域名之前在hosts文件中已经配置过了,所以这次就没有配置hosts文件)
首页的配置服务器如下:

#配置前台管理服务器
server {
listen 80;
server_name www.jt.com;
location / {
#实现http请求的转发
proxy_pass http://localhost:8092;
}
}

02.在总项目jt中去再次声明一个新的子系统web服务器,专门用来处理web请求,并进行相关的分类转发。
第一步:先创建一个新的maven module
在这里插入图片描述
第二步:
写出相关项目的名称 web
打包方式是war,因为有静态资源需要管理。
在这里插入图片描述
在这里插入图片描述
第三步:在新创建的web项目中添加相关依赖:

添加总项目的common依赖,可以使用common中的工具包

<dependencies>
<dependency>
<groupId>com.jt</groupId>
<artifactId>jt-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

插件:

<build>
<plugins>
<!--跳过测试类打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

02.配置伪静态html页面:
以京东为例,京东的主页面有很多的html文件。但是这样子的html文件都是伪静态的html,本质上不是html文件,是开发人员为了好看做的修饰。

伪静态是相对真实静态来讲的,通常我们为了增强搜索引擎的友好面,都将文章内容生成静态页
面,但是有时为了实时的显示一些信息,或者还想运用动态脚本解决一些问题,不能用静态的方式来展示网站内容。这就损失了对搜索引擎的友好面。怎么样在两者之间找个中间方法呢,这就产生了伪静态技术。伪静态技术是指展示出来的是以html一类的静态页面形式,但其实是用ASP一类的动态脚本来处理的。
总结: 以html结尾展现的动态页面。
配置一个专门的类,用来修饰伪静态html文件。

@Configuration
public class MvcConfigurer implements WebMvcConfigurer{
//开启匹配后缀型配置 后缀任意.
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(true);
}
}

03.使用httpclient来实现服务器与服务器之间的通信

HTTP 协议是现在 Internet 上使用得最多、最重要的协议,越来越多的 Java 应用程序需要直接通过HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是
对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache JakartaCommon 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在HttpClient最新版本为HttpClient 4.5.6(2015-09-11)。

以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。
(1)实现了所有 HTTP 的方法(GET,POST,PUT,Delete 等)
(2)支持自动转向
(3)支持 HTTPS 协议
(4)支持代理服务器等

第一步:导入依赖jar包

<!--添加httpClient jar包 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency

第二步:测试入门案例

@Test
public void doGet() throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
String url = "http://www.baidu.com";
HttpGet get = new HttpGet(url);
HttpResponse response = httpClient.execute(get);
if(200 == response.getStatusLine().getStatusCode()) {
System.out.println("请求正确!!!!!!");
// HttpEntity封装返回值信息
HttpEntity entity = response.getEntity();
//将entity中携带的信息转化为字符串
String result = EntityUtils.toString(entity,"utf-8");
System.out.println(result);
}else {
System.out.println("请求异常!!!!!");
}
}

第三步:封装需要使用到的对象,三个工具类
HttpClientService:封装服务器之间通信的方法,get,post,其中就包括返回结果的状态state

package com.jt.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
public class HttpClientService {
	@Autowired
	private CloseableHttpClient httpClient;
	@Autowired
	private RequestConfig requestConfig;

	public String doGet(String url,Map<String,String> params,String charset){
		String result = null;
		//1.判断字符集编码是否为空 如果为空则给定默认值utf-8
		if(StringUtils.isEmpty(charset)){

			charset = "UTF-8";
		}
		//2.判断用户是否需要传递参数
		if(params != null){
			try {
				URIBuilder uriBuilder = new URIBuilder(url);
				for (Map.Entry<String,String> entry : params.entrySet()) {

					uriBuilder.addParameter(entry.getKey(), entry.getValue());
				}
				//url?id=1&name=tom
				url = uriBuilder.build().toString();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		//3.定义参数提交对象
		HttpGet get = new HttpGet(url);

		//4.为请求设定超时时间
		get.setConfig(requestConfig);

		//5.通过httpClient发送请求
		try {
			CloseableHttpResponse response = 
					httpClient.execute(get);
			if(response.getStatusLine().getStatusCode() == 200){
				//表示程序调用成功
				result = EntityUtils.toString(response.getEntity(),charset);
			}else{
				System.out.println("调用异常:状态信息:"+response.getStatusLine().getStatusCode());
				throw new RuntimeException();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	public String doGet(String url){

		return doGet(url, null, null);
	}

	public String doGet(String url,Map<String,String> params){

		return doGet(url, params, null);
	}

	public String doGet(String url,String charset){

		return doGet(url, null, charset);
	}

	//实现httpClient POST提交
	public String doPost(String url,Map<String,String> params,String charset){
		String result = null;

		//1.定义请求类型
		HttpPost post = new HttpPost(url);
		post.setConfig(requestConfig);  	//定义超时时间

		//2.判断字符集是否为null
		if(StringUtils.isEmpty(charset)){

			charset = "UTF-8";
		}

		//3.判断用户是否传递参数
		if(params !=null){
			//3.2准备List集合信息
			List<NameValuePair> parameters = 
					new ArrayList<>();

			//3.3将数据封装到List集合中
			for (Map.Entry<String,String> entry : params.entrySet()) {

				parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}

			//3.1模拟表单提交
			try {
				UrlEncodedFormEntity formEntity = 
						new UrlEncodedFormEntity(parameters,charset); //采用u8编码

				//3.4将实体对象封装到请求对象中
				post.setEntity(formEntity);
			} catch (UnsupportedEncodingException e) {

				e.printStackTrace();
			}
		}

		//4.发送请求
		try {
			CloseableHttpResponse response = 
					httpClient.execute(post);

			//4.1判断返回值状态
			if(response.getStatusLine().getStatusCode() == 200) {

				//4.2表示请求成功
				result = EntityUtils.toString(response.getEntity(),charset);
			}else{
				System.out.println("获取状态码信息:"+response.getStatusLine().getStatusCode());
				throw new RuntimeException();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return result;
	}



	public String doPost(String url){

		return doPost(url, null, null);
	}

	public String doPost(String url,Map<String,String> params){

		return doPost(url, params, null);
	}

	public String doPost(String url,String charset){

		return doPost(url, null, charset);
	}
}

HttpClientConfig ,这里获取到上文提到案例中的CloseableHttpClient 对象,使用注解@Bean来将对象的管理权限交给spring容器进行管理。

package com.jt.config;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource(value="classpath:/properties/httpClient.properties")
public class HttpClientConfig {
	@Value("${http.maxTotal}")
	private Integer maxTotal;						//最大连接数

	@Value("${http.defaultMaxPerRoute}")
	private Integer defaultMaxPerRoute;				//最大并发链接数

	@Value("${http.connectTimeout}")
	private Integer connectTimeout;					//创建链接的最大时间

	@Value("${http.connectionRequestTimeout}") 
	private Integer connectionRequestTimeout;		//链接获取超时时间

	@Value("${http.socketTimeout}")
	private Integer socketTimeout;			  		//数据传输最长时间

	@Value("${http.staleConnectionCheckEnabled}")
	private boolean staleConnectionCheckEnabled; 	//提交时检查链接是否可用

	//定义httpClient链接池
	@Bean(name="httpClientConnectionManager")
	public PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager() {
		PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
		manager.setMaxTotal(maxTotal);  //设定最大链接数
		manager.setDefaultMaxPerRoute(defaultMaxPerRoute);  //设定并发链接数
		return manager;
	}

	//定义HttpClient
	/**
	 * 实例化连接池,设置连接池管理器。
	 * 这里需要以参数形式注入上面实例化的连接池管理器
      @Qualifier 指定bean标签进行注入
	 */
	@Bean(name = "httpClientBuilder")
	public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager")PoolingHttpClientConnectionManager httpClientConnectionManager){

		//HttpClientBuilder中的构造方法被protected修饰,所以这里不能直接使用new来实例化一个HttpClientBuilder,可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
		httpClientBuilder.setConnectionManager(httpClientConnectionManager);
		return httpClientBuilder;
	}

	/**
	 * 	注入连接池,用于获取httpClient
	 * @param httpClientBuilder
	 * @return
	 */
	@Bean
	public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder){

		return httpClientBuilder.build();
	}

	/**
	 * Builder是RequestConfig的一个内部类
	  * 通过RequestConfig的custom方法来获取到一个Builder对象
	  * 设置builder的连接信息
	 * @return
	 */
	@Bean(name = "builder")
	public RequestConfig.Builder getBuilder(){
		RequestConfig.Builder builder = RequestConfig.custom();
		return builder.setConnectTimeout(connectTimeout)
				.setConnectionRequestTimeout(connectionRequestTimeout)
				.setSocketTimeout(socketTimeout)
				.setStaleConnectionCheckEnabled(staleConnectionCheckEnabled);
	}

	/**
	 * 使用builder构建一个RequestConfig对象
	 * @param builder
	 * @return
	 */
	@Bean
	public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder){
		return builder.build();
	}
}

HttpClientClose

package com.jt.config;

import javax.annotation.PreDestroy;

import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.pool.PoolStats;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component	//交给spring容器管理
public class HttpClientClose extends Thread{
	@Autowired
	private PoolingHttpClientConnectionManager manage;
	private volatile boolean shutdown;	//开关 volatitle表示多线程可变数据,一个线程修改,其他线程立即修改
	
	public HttpClientClose() {
		///System.out.println("执行构造方法,实例化对象");
		//线程开启启动
		this.start();
	}
	
	
	@Override
	public void run() {
		try {
			//如果服务没有关闭,执行线程
			while(!shutdown) {
				synchronized (this) {
					wait(5000);			//等待5秒
					//System.out.println("线程开始执行,关闭超时链接");
					//关闭超时的链接
					PoolStats stats = manage.getTotalStats();
					int av = stats.getAvailable();	//获取可用的线程数量
					int pend = stats.getPending();	//获取阻塞的线程数量
					int lea = stats.getLeased();    //获取当前正在使用的链接数量
					int max = stats.getMax();
					//System.out.println("max/"+max+":	av/"+av+":  pend/"+pend+":   lea/"+lea);
					manage.closeExpiredConnections();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}

		super.run();
	}

	//关闭清理无效连接的线程
	@PreDestroy	//容器关闭时执行该方法.
	public void shutdown() {
		shutdown = true;
		synchronized (this) {
			//System.out.println("关闭全部链接!!");
			notifyAll(); //全部从等待中唤醒.执行关闭操作;
		}
	}
}

利用HttpClient实现远程商品及商品详情查询
案例运行时候的示意图:www.jt.com 是访问前端web服务器的url,由Nginx完成代理,manage.jt.com是后端处理数据的服务器。在这里插入图片描述
第一步:在web服务器中,写一个controller类,处理发送过来的前端http请求。
这里是item界面的http请求。

@Controller //如果需要跳转页面.则使用Controller注解
@RequestMapping("/items")
public class ItemController {
@Autowired
private ItemService itemService;
/**
* 请求:http://www.jt.com/items/56237
* 请求分析: 通过jt-web服务器 访问后台商品信息,其中562379表示商品的ID号
* 根据商品id号,之后查询后台数据库,获取商品信息之后进行数据的页面展现
* 参数接收: 需要动态的接收url中的参数 利用restFul风格实现数据的动态获取
*页面展现数据要求:
* <h1>${item.title}</h1>
<strong>${item.sellPoint}</strong>
需要查询后台数据之后.将数据保存到域中,之后利用el表达式完成数据的动态取值.
*/
@RequestMapping("/{itemId}")
public String findItemById(@PathVariable Long itemId,Model model) {
//1.根据商品id查询数据库
Item item = itemService.findItemById(itemId);
//2.将item对象保存到域中
model.addAttribute("item", item);
//查询数据之后跳转页面;
return "item";
}
}

第二步:在web服务器中,写相关的接口service

public interface ItemService {
Item findItemById(Long itemId);
}

第三步:在web服务器中,写service的实现类,这里需要使用到httpclient

@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private HttpClientService httpClientService;
/*
* 业务分析:
* 就是根据接收到的商品的id然后查询商品的数据,封装在Item对象
* 如何查询呢?
* jt-web是前台系统,不能直接连接数据库,如何查询数据呢?
* 查询方式:由前台系统jt-web发起请求去调用具体的后台系统jt-manage去查询商品数据
*/
@Override
@CacheFind//使用到了自定义的缓存注解
public Item findItemById(Long itemId) {
String url="http://manage.jt.com/web/item/findItemById/"+itemId;
String itemJSON=httpClientService.doGet(url);
//将json转换成java对象
return ObjectMapperUtil.toObject(itemJSON, Item.class);
}
}

第四步:
manage.jt.com来接受web服务器的service接口实现类中使用的httpclient的httpclientservice的get方法。
写一个controller类,转过来的也是url

@RestController
@RequestMapping("/web/item")
public class WebItemController {
@Autowired
private ItemService itemService;
/**
* 从前台向后台发起请求:
* http://manage.jt.com:80/web/item/findItemById/562379
* http://manage.jt.com:80是根目录,不用在requestmapping中写出来。因为现在就在manage.jt.com服务器中。
* 
*/
@RequestMapping("/findItemById/{itemId}")
public Item findItemById(@PathVariable Long itemId) {
return itemService.findItemById(itemId);
}
}

再去写接口的中方法和方法在接口实现类中的重写:

public interface ItemService {
Item findItemById(Long itemId);
}
@Override
public Item findItemById(Long itemId) {
return itemMapper.selectById(itemId);//利用MP实现查询
}

在这里插入图片描述
在这里插入图片描述
查询商品详情信息数据
第一步:业务分析
说明:如果需要展现商品详情信息,则需要将商品详情信息添加到域中,之后动态获取数据信息.
在item.jsp:

<div class="detail-content">
${itemDesc.itemDesc }
</div>

第二步:编辑jt-web项目的ItemController

@RequestMapping("/{itemId}")
public String findItemById(@PathVariable Long itemId,Model model) {
//1.根据商品id查询数据库
Item item = itemService.findItemById(itemId);
//2.将item对象保存到域中
model.addAttribute("item", item);
//3.查询商品详情信息
ItemDesc itemDesc = itemService.findItemDescById(itemId);
model.addAttribute("itemDesc", itemDesc);
//查询数据之后跳转页面;
return "item";
}

第三步:编辑jt-web项目的下的ItemService接口

public interface ItemService {
Item findItemById(Long itemId);
ItemDesc findItemDescById(Long itemId);
}

第四步:编辑jt-web的ItemServiceImpl实现类

@Override
public ItemDesc findItemDescById(Long itemId) {
String url = "http://manage.jt.com/web/item/findItemDescById/"+itemId;
String itemDescJSON = httpClientService.doGet(url);
return ObjectMapperUtil.toObject(itemDescJSON, ItemDesc.class);
}

第五步:编辑jt-manage项目下的WebItemController

/**
* 根据商品Id号动态查询商品详情信息
* http://manage.jt.com/web/item/findItemDescById/562379
*/
@RequestMapping("/findItemDescById/{itemId}")
public ItemDesc findItemDescById(@PathVariable Long itemId) {
return itemService.findItemDescById(itemId);
}

在这里插入图片描述

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

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

相关文章

Godot引擎 4.0 文档 - 循序渐进教程 - 节点和场景

本文为Google Translate英译中结果&#xff0c;DrGraph在此基础上加了一些校正。英文原版页面&#xff1a; Nodes and Scenes — Godot Engine (stable) documentation in English 节点和场景 在Godot 关键概念概述中&#xff0c;我们看到 Godot 游戏是一棵场景树&#xff0…

算法训练-二分查找

这里写目录标题 34. 在排序数组中查找元素的第一个和最后一个位置162. 寻找峰值153. 寻找旋转排序数组中的最小值33. 搜索旋转排序数组 34. 在排序数组中查找元素的第一个和最后一个位置 题目链接 vector<int> searchRange(vector<int>& nums, int target) {i…

集合 集合

目录 ArraryList 引用基本类型 案例1&#xff1a;定义一个集合添加学生姓名年龄 案例2&#xff1a;查看是否存在这个id 案例3&#xff1a;手机 案例4&#xff1a;学生管理系统&#xff08;不完整&#xff09; Collection collection遍历方式 迭代遍历&#xff08;不依赖…

深度学习用于医学预后-第二课第四周13-15节-使用生存数的非线性风险评估模型

使用生存数的非线性风险评估模型 在这堂课中&#xff0c;你将学习关于生存树的知识。你将学习如何将患者的变量纳入考虑&#xff0c;比较不同患者的风险。 你将看到生存树与二叉决策树相似&#xff0c;可以让你构建模型来捕捉患者数据中的非线性关系。 在这堂课中&#xff0…

分布式运用之rsync远程同步

1.rsync的相关知识 1.1 rsync简介 rsync&#xff08;Remote Sync&#xff0c;远程同步&#xff09;是一个开源的快速备份工具&#xff0c;可以在不同主机之间镜像同步整个目录树&#xff0c;支持增量备份&#xff0c;并保持链接和权限&#xff0c;且采用优化的同步算法&#…

怎么使用树莓派总要了解一点它的软硬件吧。什么模块有什么用,需要什么准备才能安全的看到树莓派的开机界面

Raspberry Pi(中文名为“树莓派”,简写为 RPi&#xff0c;(或者 RasPi / RPI)只有信用卡大小的微型电脑&#xff0c;其系统基于 Linux。随着 Windows 10 IoT 的发布&#xff0c;我们也将可以用上运行 Windows IoT 的树莓派。别看其外表“娇小”&#xff0c;内“心”却很强大&am…

Doxygen 源码分析: SymbolMap类

2023-05-21 10:59:35 ChrisZZ imzhuofoxmailcom Hompage https://github.com/zchrissirhcz 文章目录 1. Doxygen 版本2. SymbolMap 类概要3. 添加符号: SymbolMap<T>::add()4. 删除符号: SymbolMap<T>::remove()5. 符号查找: SymbolMap<T>::find()6. 哪里用了…

1.golang的介绍、环境安装和编译器安装

一、Go的介绍 Go语言其实是Golanguage的简称&#xff0c;Go&#xff08;又称 Golang&#xff09;是 Google 的 Robert Griesemer&#xff0c;Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译并发型语言。Go 语言语法与 C 相近&#xff0c;但功能上有&#xff1a;内存安全…

Doxygen 源码分析: Definition类

2023-05-21 13:05:28 ChrisZZ imzhuofoxmailcom Hompage https://github.com/zchrissirhcz Blog https://blog.csdn.net/baiyu33 文章目录 1. Doxygen 版本2. Definition 类和它的8个子类3. Definition 类的 Private 成员4. Definition 类的 Public 成员4.1 特殊成员函数4.2 获…

(学习日记)AD学习 #1

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

Linux基本操作指令2

目录 指令1&#xff1a;rmdir指令&#xff1a; 指令2&#xff1a;rm命令&#xff1a; 指令3&#xff1a;man指令&#xff1a; 指令4&#xff1a;cp指令&#xff1a; 指令5&#xff1a;mv指令&#xff1a;类似于Windows的剪贴 指令6&#xff1a;cat指令 指令7&#xff1a;…

QT5.15.0使用gcc-arm-8.2-2018.08-x86_64-arm-linux-gnueabihf交叉编译的问题总结

目录 一、交叉编译 二、操作中踩过的坑 1、环境变量未生效 2、交叉编译QT代码操作 3、烧录时报错缺少xcb问题 4、小白的细小错误 三、--platform命令 3、1 -platform linuxfb 详细文档请点击此处 我的文档在原文档的基础上添加了非常详细的提醒&#xff0c;可以少走弯路…

软件性能测试过程详解与案例剖析

软件性能测试是软件开发过程中至关重要的一环&#xff0c;它能够帮助我们确保软件在不同负载和使用情况下的表现。在软件性能测试中&#xff0c;我们通常会关注软件的响应时间、吞吐量、并发用户数等指标&#xff0c;以评估软件性能。 软件性能测试过程主要分为以下几个步骤&am…

leetcode:322. 零钱兑换(暴力dfs,记忆化dfs,动态规划(朴素+优化),bfs+贪心)

记录常规的完全背包问题模型 1.暴力dfs2.优化dfs&#xff0c;记忆化dfs3.动态规划4.bfs 1.由于每件物品可以无限取&#xff0c;那么可以发现这是一个完全背包问题模型。 1.暴力dfs 最后要求的是&#xff1a;n种硬币&#xff0c;凑成总金额为amount。每种硬币无限取&#xff0…

Java8 教你一行代码搞定:如何计算map中value值

大家好&#xff0c;我是三叔&#xff0c;很高兴这期又和大家见面了&#xff0c;一个奋斗在互联网的打工人。 这期给大家讲一下在Java编程中&#xff0c;如何使用Java8对map的值进行计算&#xff0c;在实际开发中&#xff0c;也是经常遇到统计map中的value值之和。 Map是一种常…

Web安全:文件上传漏洞测试.

Web安全&#xff1a;文件上传漏洞测试. 现在大多的网站和Web应用系统都会有上传功能&#xff08;比如&#xff1a;文档&#xff0c;图片&#xff0c;头像&#xff0c;视频上传等.&#xff09;&#xff0c;而程序员在开发文件上传功能时&#xff0c;没有对代码做严格校验上传文…

解决大文件传输难题的方法和技巧

传统的传输大文件的方式&#xff0c;如电子邮件附件或USB驱动器&#xff0c;由于文件大小的限制和安全问题&#xff0c;变得越来越不方便。大文件共享是现代商业通信的一个重要方面&#xff0c;组织需要安全可靠的方式来传输这些文件。 传统文件传输方式的不便 传统的文件传输方…

LabVIEWCompactRIO 开发指南27 创建模块化、可重复使用的子VI

LabVIEWCompactRIO 开发指南27 创建模块化、可重复使用的子VI 编写模块化代码几乎总是一个好主意&#xff0c;无论是为Windows、实时还是FPGA设备设计应用程序。子VI使代码更易于调试和故障排除&#xff0c;更易于记录和跟踪更改&#xff0c;并且通常更清晰&#xff0c;更易于…

一文读懂JVM架构解析

JVM 架构解析 Java 架构JVMJVM是如何工作的&#xff1f;类加载器子系统 运行时数据区执行引擎 每个 Java 开发人员都知道字节码经由 JRE&#xff08;Java运行时环境&#xff09;执行。但他们或许不知道 JRE 其实是由 Java虚拟机&#xff08;JVM&#xff09;实现&#xff0c;JVM…

css3 flex弹性布局学习

一、flex基本概念 当开启flex布局后&#xff0c;项目默认沿主轴排列。单个项目占据的主轴空间叫做main size&#xff0c;占据的交叉轴空间叫做cross size。 二、容器的属性 以下6个属性设置在容器上。 flex-direction flex-wrap flex-flow justify-content align-items align…