bean注入属性_摆脱困境:将属性值注入配置Bean

bean注入属性

Spring Framework对将从属性文件中找到的属性值注入到bean或@Configuration类中提供了很好的支持。 但是,如果将单个属性值注入这些类中,则会遇到一些问题。

这篇博客文章指出了这些问题,并描述了我们如何解决它们。

让我们开始吧。

如果使用Spring Boot,则应使用其Typesafe配置属性。 您可以从以下网页获取有关此的更多信息:

  • Spring Boot参考手册的23.7节Typesafe配置属性
  • @EnableConfigurationProperties批注的Javadoc
  • @ConfigurationProperties批注的Javadoc
  • 在Spring Boot中使用@ConfigurationProperties

很简单,但并非没有问题

如果将单个属性值注入到我们的bean类中,我们将面临以下问题:

1.注入多个属性值很麻烦

如果我们通过使用@Value批注注入单个属性值,或者通过使用Environment对象来获取属性值,则注入多个属性值会很麻烦。

假设我们必须向UrlBuilder对象注入一些属性值。 该对象需要三个属性值:

  • 服务器的主机( app.server.host
  • 服务器监听的端口( app.server.port
  • 使用的协议( app.server.protocol

UrlBuilder对象构建用于访问Web应用程序不同功能的URL地址时,将使用这些属性值。

如果我们使用构造函数注入和@Value注释注入这些属性值,则UrlBuilder类的源代码如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class UrlBuilder {private final String host;private final String port;private final String protocol;@Autowiredpublic UrlBuilder(@Value("${app.server.protocol}") String protocol,@Value("${app.server.host}") String serverHost,@Value("${app.server.port}") int serverPort) {this.protocol = protocol.toLowercase();this.serverHost = serverHost;this.serverPort = serverPort;}
}

补充阅读:

  • @Value注释的Javadoc

如果我们通过使用构造函数注入和Environment类注入这些属性值,则UrlBuilder类的源代码如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;@Component
public class UrlBuilder {private final String host;private final String port;private final String protocol;@Autowiredpublic UrlBuilder(Environment env) {this.protocol = env.getRequiredProperty("app.server.protocol").toLowercase();this.serverHost = env.getRequiredProperty("app.server.host");this.serverPort = env.getRequiredProperty("app.server.port", Integer.class);}
}

补充阅读:

  • 环境接口的Javadoc

我承认这看起来还不错。 但是,当所需属性值的数量增加和/或我们的类也具有其他依赖项时,将所有这些属性注入都是很麻烦的。

2.我们必须指定多个属性名称(或记住使用常量)

如果我们将单个属性值直接注入需要它们的bean中,并且多个bean(A和B)需要相同的属性值,那么我们想到的第一件事就是在两个bean类中都指定属性名称:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class A {private final String protocol;@Autowiredpublic A(@Value("${app.server.protocol}") String protocol) {this.protocol = protocol.toLowercase();}
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class B {private final String protocol;@Autowiredpublic B(@Value("${app.server.protocol}") String protocol) {this.protocol = protocol.toLowercase();}
}

这是一个问题,因为

  1. 因为我们是人类,所以我们会打错字 。 这不是一个大问题,因为在启动应用程序时我们会注意到它。 但是,它使我们放慢了速度。
  2. 这使维护更加困难 。 如果更改属性的名称,则必须对使用该属性的每个类进行此更改。

我们可以通过将属性名称移到常量类来解决此问题。 如果这样做,我们的源代码如下所示:

public final PropertyNames {private PropertyNames() {}public static final String PROTOCOL = "${app.server.protocol}";
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class A {private final String protocol;@Autowiredpublic A(@Value(PropertyNames.PROTOCOL) String protocol) {this.protocol = protocol.toLowercase();}
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class B {private final String protocol;@Autowiredpublic B(@Value(PropertyNames.PROTOCOL) String protocol) {this.protocol = protocol.toLowercase();}
}

这可以解决维护问题,但前提是所有开发人员都记得要使用它。 我们当然可以通过使用代码审阅来强制执行此操作,但这是审阅者必须记住要检查的另一件事。

3.添加验证逻辑成为问题

假设我们有两个类( AB ),它们需要app.server.protocol属性的值。 如果我们将此属性值直接注入到AB Bean中,并且想要确保该属性的值为'http'或'https',则必须

  1. 将验证逻辑添加到两个bean类中。
  2. 将验证逻辑添加到实用程序类中,并在需要验证是否给出了正确的协议时使用它。

如果我们将验证逻辑添加到两个bean类,则这些类的源代码如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class A {private final String protocol;@Autowiredpublic A(@Value("${app.server.protocol}") String protocol) {checkThatProtocolIsValid(protocol);this.protocol = protocol.toLowercase();}private void checkThatProtocolIsValid(String protocol) {if (!protocol.equalsIgnoreCase("http") && !protocol.equalsIgnoreCase("https")) {throw new IllegalArgumentException(String.format("Protocol: %s is not allowed. Allowed protocols are: http and https.",protocol));}}
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class B {private final String protocol;@Autowiredpublic B(@Value("${app.server.protocol}") String protocol) {checkThatProtocolIsValid(protocol);this.protocol = protocol.toLowercase();}private void checkThatProtocolIsValid(String protocol) {if (!protocol.equalsIgnoreCase("http") && !protocol.equalsIgnoreCase("https")) {throw new IllegalArgumentException(String.format("Protocol: %s is not allowed. Allowed protocols are: http and https.",protocol));}}
}

这是一个维护问题,因为AB类包含复制粘贴代码。 通过将验证逻辑移至实用程序类并在创建新的AB对象时使用它,可以稍微改善这种情况。

完成此操作后,我们的源代码如下所示:

public final class ProtocolValidator {private ProtocolValidator() {}public static void checkThatProtocolIsValid(String protocol) {if (!protocol.equalsIgnoreCase("http") && !protocol.equalsIgnoreCase("https")) {throw new IllegalArgumentException(String.format("Protocol: %s is not allowed. Allowed protocols are: http and https.",protocol));}}
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class A {private final String protocol;@Autowiredpublic A(@Value("${app.server.protocol}") String protocol) {ProtocolValidator.checkThatProtocolIsValid(protocol);this.protocol = protocol.toLowercase();}
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class B {private final String protocol;@Autowiredpublic B(@Value("${app.server.protocol}") String protocol) {ProtocolValidator.checkThatProtocolIsValid(protocol);this.protocol = protocol.toLowercase();}
}

问题在于,我们仍然必须记住要调用此实用程序方法。 我们当然可以通过使用代码审阅来强制执行此操作,但是再次重申,审阅者必须记住要检查的另一件事。

4.我们不能编写好的文档

我们无法编写描述应用程序配置的好的文档,因为我们必须将此文档添加到实际的属性文件中,使用Wiki或编写* gasp * Word文档。

这些选项中的每个选项都会引起问题,因为我们不能在编写需要从属性文件中找到属性值的代码时同时使用它们。 如果需要阅读文档,则必须打开“外部文档”,这会导致上下文切换非常昂贵 。

让我们继续前进,找出如何解决这些问题。

将属性值注入配置Bean

通过将属性值注入配置Bean中,我们可以解决前面提到的问题。 首先,为示例应用程序创建一个简单的属性文件。

创建属性文件

我们要做的第一件事是创建一个属性文件。 我们的示例应用程序的属性文件称为application.properties ,其外观如下:

app.name=Configuration Properties example
app.production.mode.enabled=falseapp.server.port=8080
app.server.protocol=http
app.server.host=localhost

让我们继续并配置示例应用程序的应用程序上下文。

配置应用程序上下文

我们的示例应用程序的应用程序上下文配置类有两个目标:

  1. 启用S​​pring MVC并导入其默认配置。
  2. 确保已读取从application.properties文件中找到的属性值,并且可以将其注入到Spring Bean中。

通过执行以下步骤,我们可以实现第二个目标:

  1. 配置Spring容器以扫描所有包含bean类的软件包。
  2. 确保从application.properties文件中找到的属性值已读取并添加到Spring Environment中
  3. 确保从@Value批注中找到的$ {…}占位符替换为从当前Spring Environment及其PropertySources中找到的属性值。

WebAppContext类的源代码如下所示:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;@Configuration
@ComponentScan({"net.petrikainulainen.spring.trenches.config","net.petrikainulainen.spring.trenches.web"
})
@EnableWebMvc
@PropertySource("classpath:application.properties")
public class WebAppContext {/*** Ensures that placeholders are replaced with property values*/@BeanPropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {return new PropertySourcesPlaceholderConfigurer();}
}

补充阅读:

  • @ComponentScan批注的Javadoc
  • @PropertySource批注的Javadoc
  • Spring框架参考手册的5.13.4 @PropertySource部分
  • PropertySourcesPlaceholderConfigurer类的Javadoc

下一步是创建配置Bean类,并将从属性文件中找到的属性值注入到它们中。 让我们找出如何做到这一点。

创建配置Bean类

让我们创建以下描述的两个配置bean类:

  • WebProperties类包含用于配置使用的协议,服务器的主机以及服务器侦听的端口的属性值。
  • ApplicationProperties类包含用于配置应用程序名称并标识是否启用生产模式的属性值。 它还具有对WebProperties对象的引用。

首先 ,我们必须创建WebProperties类。 我们可以按照以下步骤进行操作:

  1. 创建WebProperties类,并使用@Component注释对其进行注释。
  2. 将最终协议serverHostserverPort字段添加到创建的类中。
  3. 通过使用构造函数注入将属性值注入这些字段,并确保协议字段的值必须为“ http”或“ https”(忽略大小写)。
  4. 添加用于获取实际属性值的吸气剂。

WebProperties类的源代码如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public final class WebProperties {private final String protocol;private final String serverHost;private final int serverPort;@Autowiredpublic WebProperties(@Value("${app.server.protocol}") String protocol,@Value("${app.server.host}") String serverHost,@Value("${app.server.port}") int serverPort) {checkThatProtocolIsValid(protocol);this.protocol = protocol.toLowercase();this.serverHost = serverHost;this.serverPort = serverPort;}private void checkThatProtocolIsValid(String protocol) {if (!protocol.equalsIgnoreCase("http") && !protocol.equalsIgnoreCase("https")) {throw new IllegalArgumentException(String.format("Protocol: %s is not allowed. Allowed protocols are: http and https.",protocol));}}public String getProtocol() {return protocol;}public String getServerHost() {return serverHost;}public int getServerPort() {return serverPort;}
}

其次 ,我们必须实现ApplicationProperties类。 我们可以按照以下步骤进行操作:

  1. 创建ApplicationProperties类,并使用@Component注释对其进行注释。
  2. 将最终名称productionModeEnabledwebProperties字段添加到创建的类。
  3. 通过使用构造函数注入,将属性值和WebProperties Bean注入到ApplicationProperties Bean中。
  4. 添加用于获取字段值的吸气剂。

ApplicationProperties类的源代码如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public final class ApplicationProperties {private final String name;private final boolean productionModeEnabled;private final WebProperties webProperties;@Autowiredpublic ApplicationProperties(@Value("${app.name}") String name,@Value("${app.production.mode.enabled:false}") boolean productionModeEnabled,WebProperties webProperties) {this.name = name;this.productionModeEnabled = productionModeEnabled;this.webProperties = webProperties;}public String getName() {return name;}public boolean isProductionModeEnabled() {return productionModeEnabled;}public WebProperties getWebProperties() {return webProperties;}
}

让我们继续研究该解决方案的好处。

这对我们有什么帮助?

现在,我们创建了包含从application.properties文件中找到的属性值的Bean类。 该解决方案似乎是一项过度的工程设计,但与传统的简单方法相比,它具有以下优点:

1.我们只能注入一个Bean而不是多个属性值

如果我们将属性值注入配置Bean,然后通过使用构造函数注入将该配置Bean注入UrlBuilder类,则其源代码如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class UrlBuilder {private final WebProperties properties;@Autowiredpublic UrlBuilder(WebProperties properties) {this.properties = properties;}
}

如我们所见,这使我们的代码更整洁( 尤其是在使用构造函数注入的情况下 )。

2.我们只需指定一次属性名称

如果将属性值注入到配置Bean中,则只能在一个地方指定属性名称。 这意味着

  • 我们的代码遵循关注点分离原则。 可从配置Bean中找到属性名称,而其他需要此信息的Bean不知道其来源。 他们只是使用它。
  • 我们的代码遵循“ 不要重复自己”的原则。 因为属性名称仅在一个位置(在配置Bean中)指定,所以我们的代码更易于维护。

另外,(IMO)我们的代码看起来也更加简洁:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class A {private final String protocol;@Autowiredpublic A(WebProperties properties) {this.protocol = properties.getProtocol();}
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class B {private final String protocol;@Autowiredpublic B(WebProperties properties) {this.protocol = properties.getProtocol();}
}

3.我们只需要编写一次验证逻辑

如果将属性值注入到配置Bean中,则可以将验证逻辑添加到配置Bean中,而其他Bean不必知道它。 这种方法具有三个好处:

  • 我们的代码遵循关注点分离原则,因为可以从配置bean(它所属的地方)中找到验证逻辑。 其他的豆子不必知道。
  • 我们的代码遵循“不要重复自己”的原则,因为验证逻辑是从一个地方找到的。
  • 创建新的bean对象时,我们不必记住要调用验证逻辑,因为在创建配置bean时我们可以执行验证规则。

同样,我们的源代码看起来也更加干净:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class A {private final String protocol;@Autowiredpublic A(WebProperties properties) {this.protocol = properties.getProtocol();}
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class B {private final String protocol;@Autowiredpublic B(WebProperties properties) {this.protocol = properties.getProtocol();}
}

4.我们可以从IDE中访问文档

我们可以通过向配置bean中添加Javadoc注释来记录应用程序的配置。 完成此操作后,当我们编写需要这些属性值的代码时,可以从IDE中访问此文档。 我们不需要打开其他文件或阅读维基页面。 我们可以简单地继续编写代码并避免上下文切换的开销 。

让我们继续并总结从这篇博客文章中学到的知识。

摘要

这篇博客文章告诉我们将属性值注入配置Bean:

  • 帮助我们遵循关注点分离原则。 有关配置属性和属性值验证的内容封装在我们的配置Bean中。 这意味着使用这些配置bean的bean不知道属性值来自何处或如何验证它们。
  • 帮助我们遵循“不要重复自己”的原则,因为1)我们只需指定一次属性名称,然后2)可以将验证逻辑添加到配置bean。
  • 使我们的文档更易于访问。
  • 使我们的代码更易于编写,阅读和维护。

但是,这无助于我们弄清应用程序的运行时配置。 如果我们需要此信息,则必须读取从服务器中找到的属性文件。 这很麻烦。

我们将在我的下一篇博客文章中解决此问题。

  • PS:您可以从Github获得此博客文章的示例应用程序 。

翻译自: https://www.javacodegeeks.com/2015/04/spring-from-the-trenches-injecting-property-values-into-configuration-beans.html

bean注入属性

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

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

相关文章

php 浏览器 打印控件,JavaScript_JavaScript 实现打印,打印预览,打印设置,WebBrowser是IE内置的浏览器控件 - phpStudy...

JavaScript 实现打印,打印预览,打印设置WebBrowser是IE内置的浏览器控件,无需用户下载.一、WebBrowser控件二、WebBrowder控件的方法 //打印WebBrowser1.ExecWB(6,1);//打印设置WebBrowser1.ExecWB(8,1);//打印预览WebBrowser1.ExecWB(7,1);关于这个组件还有其他的用…

c语言中常规函数和指针函数区别

点击上方蓝字关注我&#xff0c;了解更多咨询1、在函数名前面多了一个*号&#xff0c;而这个函数就是一个指针函数。2、其返回值是一个int类型的指针&#xff0c;是一个地址。实例#include<stdio.h>int* fun1(int* x) //传入指针 {int* tmp x; //指针tmp指向xret…

jvm崩溃的原因_JVM崩溃时:如何调查最严重错误的根本原因

jvm崩溃的原因当应用程序崩溃时&#xff0c;您可以学到什么&#xff1f; 我认为&#xff0c;“后见之明是20 /”是最喜欢的短语之一托马斯罗梅尔 &#xff0c;工程ZeroTurnaround的副总裁。 好吧&#xff0c;我实际上不确定在他的短语中占什么位置&#xff0c;但是我已经听过他…

golang web php,GitHub - kai-xx/goWeb: golang web 接口实现 -- 类似PHP的laravel

goWebgorose ormdotweb框架实现接口 -- 类似PHP的laravel项目结构说明因为 gorose orm 和 dotweb 框架 都是基于独立的组件, 所以我们可以对项目的目录做出自由的规划.在这里, 我们便规划一个遵循一般的mvc结构的项目目录.为了项目的易维护性和高可用性, 我们尽量采取成熟的架构…

jboss项目导入idea_JBoss BPM Suite快速指南–将外部数据模型导入BPM项目

jboss项目导入idea您正在从事一个大项目&#xff0c;在企业中开发规则&#xff0c;事件和流程以满足关键业务需求。 部分要求指出&#xff0c;某个业务部门将提供您的数据模型供您利用。 不会在JBoss BPM Suite数据建模器中设计此数据模型&#xff0c;但是在从业务中心仪表板…

mysql协议重传,MySQL · 源码分析 · 网络通信模块浅析

MySQL 网络通信浅析MySQL的网络通信协议主要包含以下几个层次&#xff0c;从最上层的MySQL数据包协议层到最底层的socket传输&#xff1a;| THD| Protocol| NET| VIO| SOCKET本文主要扫一下相关的代码&#xff0c;以下分析基于MySQL5.7。创建会话在MySQL5.7中对会话协议层的代码…

C语言代码优化11种实用方法

点击蓝字关注我1、选择合适的算法和数据结构选择一种合适的数据结构很重要&#xff0c;如果在一堆随机存放的数中使用了大量的插入和删除指令&#xff0c;那使用链表要快得多。数组与指针语句具有十分密切的关系&#xff0c;一般来说&#xff0c;指针比较灵活简洁&#xff0c;而…

spring boot注释_使用Spring Boot和注释支持配置Spring JMS应用程序

spring boot注释1.简介 在以前的文章中&#xff0c;我们学习了如何使用Spring JMS配置项目。 如果查看有关使用Spring JMS进行消息传递的文章介绍 &#xff0c;您会注意到它是使用XML配置的。 本文将利用Spring 4.1版本中引入的改进 &#xff0c;并仅使用Java config配置JMS项目…

obendclean php命令,ob_end_clean

用户评论:[#1]Sam Yong - hellclanner at live dot com [2011-05-04 22:14:35]Take note that if you change zlib output compression setting in between ob_start and ob_end_clean or ob_end_flush, you will get an error: ob_end_flush() failed to delete buffer zlib o…

C语言 | 简单工厂方法模式实现例子

点击蓝字关注我们1、简介简单工厂方法定义一个用于创建对象的类&#xff0c;该类接受一个参数&#xff0c;通过参数决定创建不同的对象。GOF并没有把简单工厂方法定义为23种设计模式之一&#xff0c;可以认为简单工厂方法是工厂方法的简化形式。为了体现简单工厂方法和工厂方法…

grpc 流式传输_编写下载服务器。 第一部分:始终流式传输,永远不要完全保留在内存中...

grpc 流式传输下载各种文件&#xff08;文本或二进制文件&#xff09;是每个企业应用程序的生死攸关的事情。 PDF文档&#xff0c;附件&#xff0c;媒体&#xff0c;可执行文件&#xff0c;CSV&#xff0c;超大文件等。几乎每个应用程序迟早都必须提供某种形式的下载。 下载是通…

matlab plot errorbar,如何为MATLAB errorbar plot的点和垂直线设置不同的图例?

这建立在Jens Boldsen’s answer之上,它添加了以下内容&#xff1a;>可以旋转表示图例中错误栏的线条使其垂直,或保持默认的水平方向;>该行的末尾用短线“关闭”.该方法非常通用,因为它支持&#xff1a;>任意颜色,线型和标记作为错误栏的参数.请注意,实际条形图始终绘…

C语言 / C++基础面试知识大集合

点击蓝字关注我们相对而言&#xff0c;C语言和C相关的面试题比较少见&#xff0c;没有Java方向写的人那么多&#xff0c;这是一篇 C 语言与 C面试知识点总结的文章&#xff0c;个人感觉非常难得&#xff0c;希望能对大家有所帮助。const作用修饰变量&#xff0c;说明该变量不可…

input发送a.jax_Java REST JAX-RS 2.0 –如何处理日期,时间和时间戳记数据类型

input发送a.jax无论是X-Form-Urlencoded还是JSON HTTP发布到REST资源端点&#xff0c;对于与日期或时间相关的数据都没有特定的“数据类型”。 大多数开发人员会将这些数据发布为“字符串”&#xff0c;或者只是将它们转换为Unix时间戳值&#xff08;例如1435061152&#xff09…

php中is_int用法,php – is_int()和ctype_digit()之间有区别吗?

如果参数是整数类型&#xff0c;is_int()返回true&#xff0c;ctype_digit()采用字符串参数&#xff0c;如果字符串中的所有字符都是数字&#xff0c;则返回true。例&#xff1a;┌──────────┬───────────┬────────────────┐│ │ is_…

jooq sql_jOOQ星期二:Vlad Mihalcea深入了解SQL和Hibernate

jooq sql欢迎来到jOOQ Tuesdays系列。 在本系列文章中&#xff0c;我们每隔一个月的第三个星期二发布一篇文章&#xff0c;从jOOQ的角度采访我们发现该行业令人兴奋的人。 这包括从事SQL&#xff0c;Java&#xff0c;开放源代码以及各种其他相关主题的人员。 我们很高兴在第三…

C语言灵魂拷问:++i 为比 i++效率高?

点击蓝字关注我们相信很多人遇到过这样的问题&#xff1a;printf("%d,%d",i,i);也纠结过这个问题&#xff0c;到底答案是什么。确没有一个参考的资料。唯一知道的是&#xff0c;几乎所有C语言教材都这么讲&#xff1a;i就是先使用i的值再使i自身加一&#xff0c;而i则…

HibernateNONSTRICT_READ_WRITE CacheConcurrencyStrategy如何工作

介绍 在我以前的文章中 &#xff0c;我介绍了READ_ONLY CacheConcurrencyStrategy &#xff0c;这是不可变实体图的显而易见的选择。 当高速缓存的数据可变时&#xff0c;我们需要使用读写高速缓存策略&#xff0c;本文将介绍NONSTRICT_READ_WRITE二级高速缓存的工作方式。 内…

502无法解析服务器标头_编写下载服务器。 第三部分:标头:内容长度和范围...

502无法解析服务器标头这次&#xff0c;我们将探索更多HTTP请求和响应标头&#xff0c;以改善下载服务器的实现&#xff1a; Content-length和Range 。 前者表示下载量很大&#xff0c;后者允许部分下载文件&#xff0c;或者从我们开始的地方失败后继续下载。 Content-length响…

支付宝pc支付php,laravel框架下的pc支付宝支付接入

Time: 14:22*/return [//pc配置pcconfig>[partner >2088302186611, //这里是你在成功申请支付宝接口后获取到的PID&#xff1b;key >sxevk9h1vekjlx4y12arl6pryrz111, //这里是你在成功申请支付宝接口后获取到的Keyseller_id >208830211, //就是partnersign_type &…