Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用Groovy实现Domain-Specific Languages 二

使用Groovy实现Domain-Specific Languages 二

作者头像
修改于 2022-07-10 04:53:11
修改于 2022-07-10 04:53:11
5660
举报

本文翻译自官方文档

上一篇地址

4. Adding properties to numbers 给数字添加属性

In Groovy number types are considered equal to any other types. As such, it is possible to enhance numbers by adding properties or methods to them. This can be very handy when dealing with measurable quantities for example. Details about how existing classes can be enhanced in Groovy are found in the extension modules section or the categories section.

在Groovy语言中,数字类型和其它所有类型地位相同,因此,可以通过为数字添加属性或者函数,来对数字类型进行增强。这个在你处理一个可测量的数据是非常有用。关于增强一个已有类型的内容可以参考这两个地方 extension modules section or the categories section。

An illustration of this can be found in Groovy using the TimeCategory:

下面以 TimeCategory为例:

代码语言:text
AI代码解释
复制
use(TimeCategory)  {
    println 1.minute.from.now       //1
    println 10.hours.ago

    def someDate = new Date()       //2
    println someDate - 3.months
}
  1. 通过TimeCategory,给Integer添加了一个minute属性。
  2. 类似的,months函数返回一个 groovy.time.DatumDependentDuration类型,支持计算。

Categories are lexically bound, making them a great fit for internal DSLs.

这个给人的感觉就是语言的一部分,用在DSL中就很赞。

5. @DelegatesTo

5.1. Explaining delegation strategy at compile time 什么是编译时委托策略

@groovy.lang.DelegatesTo is a documentation and compile-time annotation aimed at:

  • documenting APIs that use closures as arguments
  • providing type information for the static type checker and compiler

@groovy.lang.DelegatesTo 是一个注解,它的主要用途是:

  • 在将一个闭包作为参数使用时,记录它的API
  • 为静态类型检查以及编译器提供类型信息

The Groovy language is a platform of choice for building DSLs. Using closures, it’s quite easy to create custom control structures, as well as it is simple to create builders. Imagine that you have the following code:

Groovy 语言是构建 DSL 的首选平台。 使用闭包,可以很容易创建自定义控制结构,也很容易创建构建器。假设您有以下代码:

代码语言:text
AI代码解释
复制
email {
    from 'dsl-guru@mycompany.com'
    to 'john.doe@waitaminute.com'
    subject 'The pope has resigned!'
    body {
        p 'Really, the pope has resigned!'
    }
}

One way of implementing this is using the builder strategy, which implies a method, named email which accepts a closure as an argument. The method may delegate subsequent calls to an object that implements the from, to, subject and body methods. Again, body is a method which accepts a closure as an argument and that uses the builder strategy.

实现这种效果的一种方法是使用构造器策略,定义一个email的函数,它接受一个闭包作为参数。这个函数可以将后续调用委托给实现“from”、“to”、“subject”和“body”方法的对象。同样,body也是一个接受闭包作为参数并使用构建器策略的方法。

Implementing such a builder is usually done the following way:

通常通过一下方式实现构造器:

代码语言:text
AI代码解释
复制
def email(Closure cl) {
    def email = new EmailSpec()
    def code = cl.rehydrate(email, this, this)
    code.resolveStrategy = Closure.DELEGATE_ONLY
    code()
}

the EmailSpec class implements the from, to, … methods. By calling rehydrate, we’re creating a copy of the closure for which we set the delegate, owner and thisObject values. Setting the owner and the this object is not very important here since we will use the DELEGATE_ONLY strategy which says that the method calls will be resolved only against the delegate of the closure.

首先EmailSpec类实现了 from, to这些函数。接着,通过rehydrate函数,我们创建了原始闭包的一个副本,三个参数分别是: delegate, owner and thisObject,在这个例子中,后面两个参数不重要,只是随便赋个值,因为在第三行我们设置了 DELEGATE_ONLY 策略,它的效果是闭包里面的那些函数统统都在email中找:

代码语言:text
AI代码解释
复制
class EmailSpec {
    void from(String from) { println "From: $from"}
    void to(String... to) { println "To: $to"}
    void subject(String subject) { println "Subject: $subject"}
    void body(Closure body) {
        def bodySpec = new BodySpec()
        def code = body.rehydrate(bodySpec, this, this)
        code.resolveStrategy = Closure.DELEGATE_ONLY
        code()
    }
}

The EmailSpec class has itself a body method accepting a closure that is cloned and executed. This is what we call the builder pattern in Groovy.

EmailSpec 类本身有一个 body 函数,该函数接受闭包。 这就是我们在 Groovy 中所说的构建器模式。

One of the problems with the code that we’ve shown is that the user of the email method doesn’t have any information about the methods that he’s allowed to call inside the closure. The only possible information is from the method documentation. There are two issues with this: first of all, documentation is not always written, and if it is, it’s not always available (javadoc not downloaded, for example). Second, it doesn’t help IDEs. What would be really interesting, here, is for IDEs to help the developer by suggesting, once they are in the closure body, methods that exist on the email class.

但是这有个问题,就是如果写代码的人不看文档,或者没有文档,他就不知道他能用什么功能,另外就是对于IDE来说,他也没法提供代码提示功能。

Moreover, if the user calls a method in the closure which is not defined by the EmailSpec class, the IDE should at least issue a warning (because it’s very likely that it will break at runtime).

此外,如果用户在闭包中调用了 EmailSpec 类未定义的方法,IDE 至少应该发出警告(因为它很可能会在运行时中断)。

One more problem with the code above is that it is not compatible with static type checking. Type checking would let the user know if a method call is authorized at compile time instead of runtime, but if you try to perform type checking on this code:

上面代码的另一个问题是它与静态类型检查不兼容,类型检查可以让问题在编译时而不是运行时就暴露出来,但是如果您尝试对此代码执行类型检查:

代码语言:text
AI代码解释
复制
email {
    from 'dsl-guru@mycompany.com'
    to 'john.doe@waitaminute.com'
    subject 'The pope has resigned!'
    body {
        p 'Really, the pope has resigned!'
    }
}

Then the type checker will know that there’s an email method accepting a Closure, but it will complain for every method call inside the closure, because from, for example, is not a method which is defined in the class. Indeed, it’s defined in the EmailSpec class and it has absolutely no hint to help it knowing that the closure delegate will, at runtime, be of type EmailSpec:

类型检查工具知道有个email方法,它接受一个Closure作为参数,这个没问题,但是当他检查闭包内部的函数的时候,他就懵逼了。

代码语言:text
AI代码解释
复制
@groovy.transform.TypeChecked
void sendEmail() {
    email {
        from 'dsl-guru@mycompany.com'
        to 'john.doe@waitaminute.com'
        subject 'The pope has resigned!'
        body {
            p 'Really, the pope has resigned!'
        }
    }
}

will fail compilation with errors like this one:

最终它有可能会报错:

代码语言:text
AI代码解释
复制
[Static type checking] - Cannot find matching method MyScript#from(java.lang.String). Please check if the declared type is correct and if the method exists.
 @ line 31, column 21.
                       from 'dsl-guru@mycompany.com'

5.2. @DelegatesTo

For those reasons, Groovy 2.1 introduced a new annotation named @DelegatesTo. The goal of this annotation is to solve both the documentation issue, that will let your IDE know about the expected methods in the closure body, and it will also solve the type checking issue, by giving hints to the compiler about what are the potential receivers of method calls in the closure body.

为了解决这个问题,Groovy 2.1引入了一个新注解@DelegatesTo

The idea is to annotate the Closure parameter of the email method:

email函数的Closure参数注解:

代码语言:text
AI代码解释
复制
def email(@DelegatesTo(EmailSpec) Closure cl) {
    def email = new EmailSpec()
    def code = cl.rehydrate(email, this, this)
    code.resolveStrategy = Closure.DELEGATE_ONLY
    code()
}

What we’ve done here is telling the compiler (or the IDE) that when the method will be called with a closure, the delegate of this closure will be set to an object of type email. But there is still a problem: the default delegation strategy is not the one which is used in our method. So we will give more information and tell the compiler (or the IDE) that the delegation strategy is also changed:

但是我们在代码中设置了代理策略是DELEGATE_ONLY,所以还需要再注释中添加策略信息:

代码语言:text
AI代码解释
复制
def email(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=EmailSpec) Closure cl) {
    def email = new EmailSpec()
    def code = cl.rehydrate(email, this, this)
    code.resolveStrategy = Closure.DELEGATE_ONLY
    code()
}

Now, both the IDE and the type checker (if you are using @TypeChecked) will be aware of the delegate and the delegation strategy. This is very nice because it will both allow the IDE to provide smart completion, but it will also remove errors at compile time that exist only because the behaviour of the program is normally only known at runtime!

这就很完美。

The following code will now pass compilation:

代码语言:text
AI代码解释
复制
@TypeChecked
void doEmail() {
    email {
        from 'dsl-guru@mycompany.com'
        to 'john.doe@waitaminute.com'
        subject 'The pope has resigned!'
        body {
            p 'Really, the pope has resigned!'
        }
    }
}

5.3. DelegatesTo modes 代理模式

@DelegatesTo supports multiple modes that we will describe with examples in this section.

下面介绍一下代理模式

5.3.1. Simple delegation 简单代理

In this mode, the only mandatory parameter is the value which says to which class we delegate calls. Nothing more. We’re telling the compiler that the type of the delegate will always be of the type documented by @DelegatesTo (note that it can be a subclass, but if it is, the methods defined by the subclass will not be visible to the type checker).

再这种模式下,我们告诉编译器我们只会再我们注解的类型里面解析(即使是注解类型的子类型,子类型里面定义的内容也是不可以见的)

但是我觉得这个地方说得不对,也可能是我没理解不对。

代码语言:text
AI代码解释
复制
void body(@DelegatesTo(BodySpec) Closure cl) {
    // ...
}
5.3.2. Delegation strategy 代理策略

In this mode, you must specify both the delegate class and a delegation strategy. This must be used if the closure will not be called with the default delegation strategy, which is Closure.OWNER_FIRST.

在这种模式下,可以额外执行代理策略,默认的策略是:Closure.OWNER_FIRST

代码语言:text
AI代码解释
复制
void body(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=BodySpec) Closure cl) {
    // ...
}
5.3.3. Delegate to parameter 代理变量

In this variant, we will tell the compiler that we are delegating to another parameter of the method. Take the following code:

在这里,我打算直接代理一个变量

上面的例子,都是写死了被代理的对象类型,现在希望我们提供什么类型,就代理什么类型

代码语言:text
AI代码解释
复制
def exec(Object target, Closure code) {
   def clone = code.rehydrate(target, this, this)
   clone()
}

Here, the delegate which will be used is not created inside the exec method. In fact, we take an argument of the method and delegate to it. Usage may look like this:

在这里,我们要代理的对象不是在exec函数里面创建的,而是通过参数传进来的:

代码语言:text
AI代码解释
复制
def email = new Email()
exec(email) {
   from '...'
   to '...'
   send()
}

Each of the method calls are delegated to the email parameter. This is a widely used pattern which is also supported by @DelegatesTo using a companion annotation:

这也是@DelegatesTo另外一个很常用的一种用法:

代码语言:text
AI代码解释
复制
def exec(@DelegatesTo.Target Object target, @DelegatesTo Closure code) {
   def clone = code.rehydrate(target, this, this)
   clone()
}

A closure is annotated with @DelegatesTo, but this time, without specifying any class. Instead, we’re annotating another parameter with @DelegatesTo.Target. The type of the delegate is then determined at compile time. One could think that we are using the parameter type, which in this case is Object but this is not true. Take this code:

closure还是用@DelegatesTo标注,但是另外参数使用 @DelegatesTo.Target注解,这样就行了:

代码语言:text
AI代码解释
复制
class Greeter {
   void sayHello() { println 'Hello' }
}
def greeter = new Greeter()
exec(greeter) {
   sayHello()
}

Remember that this works out of the box without having to annotate with @DelegatesTo. However, to make the IDE aware of the delegate type, or the type checker aware of it, we need to add @DelegatesTo. And in this case, it will know that the Greeter variable is of type Greeter, so it will not report errors on the sayHello method even if the exec method doesn’t explicitly define the target as of type Greeter. This is a very powerful feature, because it prevents you from writing multiple versions of the same exec method for different receiver types!

其实这里不用 @DelegatesTo标注也是可以的,但是这里加上 @DelegatesTo可以给IDE提供额外的信息,这真是一个非常牛逼特性。

In this mode, the @DelegatesTo annotation also supports the strategy parameter that we’ve described upper.

在这个模式中, @DelegatesTo 注解依然支持 strategy

5.3.4. Multiple closures 多个闭包的情况

In the previous example, the exec method accepted only one closure, but you may have methods that take multiple closures:

上面的例子,只有一个闭包,但是如果有多个闭包的情况:

代码语言:text
AI代码解释
复制
void fooBarBaz(Closure foo, Closure bar, Closure baz) {
    ...
}

Then nothing prevents you from annotating each closure with @DelegatesTo:

依然可以使用@DelegatesTo标记代理

代码语言:text
AI代码解释
复制
class Foo { void foo(String msg) { println "Foo ${msg}!" } }
class Bar { void bar(int x) { println "Bar ${x}!" } }
class Baz { void baz(Date d) { println "Baz ${d}!" } }

void fooBarBaz(@DelegatesTo(Foo) Closure foo, @DelegatesTo(Bar) Closure bar, @DelegatesTo(Baz) Closure baz) {
   ...
}

But more importantly, if you have multiple closures and multiple arguments, you can use several targets:

还有更牛逼了,多个代理变量、多个闭包。

代码语言:text
AI代码解释
复制
void fooBarBaz(
    @DelegatesTo.Target('foo') foo,
    @DelegatesTo.Target('bar') bar,
    @DelegatesTo.Target('baz') baz,

    @DelegatesTo(target='foo') Closure cl1,
    @DelegatesTo(target='bar') Closure cl2,
    @DelegatesTo(target='baz') Closure cl3) {
    cl1.rehydrate(foo, this, this).call()
    cl2.rehydrate(bar, this, this).call()
    cl3.rehydrate(baz, this, this).call()
}

def a = new Foo()
def b = new Bar()
def c = new Baz()
fooBarBaz(
    a, b, c,
    { foo('Hello') },
    { bar(123) },
    { baz(new Date()) }
)

At this point, you may wonder why we don’t use the parameter names as references. The reason is that the information (the parameter name) is not always available (it’s a debug-only information), so it’s a limitation of the JVM.

你可能会觉得奇怪,这里为什么不直接通过指定变量名来建立对应关系,这是JVM的一个限制。

5.3.5. Delegating to a generic type 对泛型的代理

In some situations, it is interesting to instruct the IDE or the compiler that the delegate type will not be a parameter but a generic type. Imagine a configurator that runs on a list of elements:

有时候,对于一个泛型类型,我们怎么让编译器或者IDE知道我们代理的是什么类型呢:

注意这里的策略是Closure.DELEGATE_FIRST,我猜是第一个元素类型的意思

代码语言:text
AI代码解释
复制
public <T> void configure(List<T> elements, Closure configuration) {
   elements.each { e->
      def clone = configuration.rehydrate(e, this, this)
      clone.resolveStrategy = Closure.DELEGATE_FIRST
      clone.call()
   }
}

Then this method can be called with any list like this:

然后这么使用:

代码语言:text
AI代码解释
复制
@groovy.transform.ToString
class Realm {
   String name
}
List<Realm> list = []
3.times { list << new Realm() }
configure(list) {
   name = 'My Realm'
}
assert list.every { it.name == 'My Realm' }

To let the type checker and the IDE know that the configure method calls the closure on each element of the list, you need to use @DelegatesTo differently:

代码语言:text
AI代码解释
复制
public <T> void configure(
    @DelegatesTo.Target List<T> elements,
    @DelegatesTo(strategy=Closure.DELEGATE_FIRST, genericTypeIndex=0) Closure configuration) {
   def clone = configuration.rehydrate(e, this, this)
   clone.resolveStrategy = Closure.DELEGATE_FIRST
   clone.call()
}

@DelegatesTo takes an optional genericTypeIndex argument that tells what is the index of the generic type that will be used as the delegate type. This must be used in conjunction with @DelegatesTo.Target and the index starts at 0. In the example above, that means that the delegate type is resolved against List<T>, and since the generic type at index 0 is T and inferred as a Realm, the type checker infers that the delegate type will be of type Realm.

这里主要是genericTypeIndex参数表示第几个泛型类型,这里第0个,就是Realm

We’re using a genericTypeIndex instead of a placeholder (T) because of JVM limitations.

同样是由于JVM的限制,使用genericTypeIndex而不是T

5.3.6. Delegating to an arbitrary type 代理任意的类型

下面这段有段没懂,感觉可能也用不到,就不翻译了。

It is possible that none of the options above can represent the type you want to delegate to. For example, let’s define a mapper class which is parametrized with an object and defines a map method which returns an object of another type:

代码语言:text
AI代码解释
复制
class Mapper<T,U> {                             
    final T value                               
    Mapper(T value) { this.value = value }
    U map(Closure<U> producer) {                
        producer.delegate = value
        producer()
    }
}

The mapper class takes two generic type arguments: the source type and the target type

The source object is stored in a final field

The map method asks to convert the source object to a target object

As you can see, the method signature from map does not give any information about what object will be manipulated by the closure. Reading the method body, we know that it will be the value which is of type T, but T is not found in the method signature, so we are facing a case where none of the available options for @DelegatesTo is suitable. For example, if we try to statically compile this code:

代码语言:text
AI代码解释
复制
def mapper = new Mapper<String,Integer>('Hello')
assert mapper.map { length() } == 5

Then the compiler will fail with:

代码语言:text
AI代码解释
复制
Static type checking] - Cannot find matching method TestScript0#length()

In that case, you can use the type member of the @DelegatesTo annotation to reference T as a type token:

代码语言:text
AI代码解释
复制
class Mapper<T,U> {
    final T value
    Mapper(T value) { this.value = value }
    U map(@DelegatesTo(type="T") Closure<U> producer) {  
        producer.delegate = value
        producer()
    }
}

The @DelegatesTo annotation references a generic type which is not found in the method signature

Note that you are not limited to generic type toke

本文系外文翻译,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系外文翻译,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
代金券都快领完了?你还不知道有这个活动?
DNSPod官网年中大促已经正式上线! 你还不知道网址? 还不知道有多低的折扣? 更不知道有多少大奖等你来抽? OMG! 赶紧阅读这篇指南 上活动页面冲冲冲! 限时秒杀 每日10点~12点 14点~16点、18点~20点 整点秒杀! 低至1折起! 还能设置秒杀提醒, 心仪商品不能错过! 热卖单品 域名低价欢乐购 解析套餐焕新上线 证书多年期直冲最低价 足足32款域名, 真的可以选到手软! 2.5折超低折扣, 一年解析最低90元! 买到就是赚到! 证书多年期! 支持国际型,国密
腾讯云DNSPod团队
2021/06/11
8650
安装电脑管家小团队版领取超值代金券~
听说,注册并安装腾讯电脑管家小团队版,还可领取DNSPod超值代金券哦!那么腾讯电脑管家小团队版是一款什么样的产品呐,今天我们就一起来了解一下吧~ 点击此处可领代金券 一、你知道腾讯电脑管家小团队版吗? 为了帮助企业以低成本、高效率、一站式的方式解决企业电脑安全、资产管理和网络行为管控问题,腾讯电脑管家推出了小团队版,是一个专为500人以下的小微企业提供高效管理电脑的综合运维平台。无需部署服务器,只要注册并下载客户端,即可免费对企业所用终端设备实施统一管理,一个平台集中解决IT管理痛点,管理员用了都说
腾讯云DNSPod团队
2021/07/05
1.5K0
解析服务,由你定价!
DNSPod是一家上线15年的优质DNS解析服务商,为了更好的为广大用户提供可靠放心的解析服务,我们对产品性能开展了优化升级。而关于产品的定价,我们决定遵循我们一贯的宗旨:倾听用户的声音。 因此,这一次,解析套餐的定价权,交给你们。 只需要花3分钟,点击下方图片填写问卷,DNSPod解析服务,由你定价!更有大额代金券等你领取噢! SMB 腾讯云中小企业产品中心   腾讯云中小企业产品中心(简称SMB),作为腾讯云体系中唯一专业服务于8000万中小企业的业务线,致力于为中小微企业提供全面完善贴心的数字
腾讯云DNSPod团队
2020/06/22
2.4K0
DNSPod国密SSL证书重磅上线!全线证书6000元代金券可领
众所周知,证书是一种能够在服务器和浏览器之间的信息交换过程中实现通信安全的有效工具,在企业网站、邮件和文档等安全保护中扮演着重要角色。 而一个重要数据现实是,我国99.99%网站系统都是在使用国外CA签发的RSA SSL证书。但国际形势急剧变化、贸易战不断升级,此前微软还把“贸易制裁” 列为微软全球信任根认证计划的评估条件之一,中国有可能成为继“古巴、朝鲜、叙利亚和伊朗”之后不允许全球CA签发RSA SSL证书的国家之一。 因此,我国必须建立自主可控的HTTPS加密“备胎”方案,如果RSA证书等产品对我国
腾讯云DNSPod团队
2020/08/17
3.1K0
【重要】施主,你有一个重要的待办!
D妹经常接到一些粗心大意型的用户反馈:D妹,我注册的DNSPod的手机号换了,登录密码了也不记得了,怎么办呀?” 还有一些闻者流泪型: “D妹,我的账号登陆绑定的前女友的微信,她现在跟别人跑了,我还怎么扫码登录呢?” 在这里,D妹强烈强烈强烈提醒诸位施主,一定要完成账号实名认证! 当你的账号丢失,无法通过手机/邮箱找不回来,账号实名认证就成为你能找回账号唯一的方法,也是最后的保障了。 你的手机号可能会换,邮箱可能会换,女朋友也可能会换,但是你的身份是永远丢不了的,只有完成了实名认证,才能保证任何情况下
腾讯云DNSPod团队
2020/08/17
1.1K0
说到.icu,你的第一反应是什么?
说到.icu,你的第一反应是什么? 相信大多数人马上联想到的是“重症监护室” So,你的想象力就局限于此了? 在三字符域名后缀中,.icu是最独特的其中一种。.icu相当简短、易记。icu虽是重症监护病房的英文缩写,一般用于搭建医疗领域网站较多;但icu,也有i see you的谐音,可以翻译为“你在我眼中”,十分适合用于搭建社交平台。 此外,由于.icu在多个行业、语言、地理位置都具有不同的含义,因此世界上任何人都可以注册.icu。无论您的网站属于哪一个行业,只要你能发散思维赋予icu更多的含义,就
腾讯云DNSPod团队
2020/07/10
8590
.com 19.9元,不限新老不限购?
在上个月,DNSPod悄咪咪的上线了一个活动:周四狂欢日。 活动规则表明:自2020年9月17日-2020年12月31日期间每个周四当天0:00-24:00,都会在这个页面上线域名活动。 例如前几周,引起一波热潮的.com 19.9元/首年,不限新老不限购。 看到这几个字,老客户们是不是感动到想流泪了。 另外,再次郑重提醒各位,我们的批量转入的功能已经上线, 快把你们散落在“五湖四海”的域名们转入回家吧! 不仅可以在周四蹲点领取大额度转入代金券,(代金券数量有限,每周四来拼手速!) 现在转入
腾讯云DNSPod团队
2020/10/09
1.1K0
哪里买. com最便宜?
推荐了过那么多的后缀,. com仍然是大家心头不变的白月光。 那么,到底哪里能以最低的价格拥有.com? 当D妹打开搜索引擎,输入这个问题,出来的答案可谓是眼花缭乱。 首先,不说价格,想要以拿到最低的优惠,过程可不比追求“女神”简单。有的要先关注微信公众号对暗号,才能领取到优惠券。有的要扫各种二维码。有的还玩返利,返利的钱还不好提现。甚至有的还要准备一些额外的“工具”(不展开讲了)。 看到这些形形色色的套路,D妹陷入了深深的疑惑:你们为难用户的样子,和女神为难追求者有什么区别?还不如直接告诉对方:我洗澡了
腾讯云DNSPod团队
2020/06/28
16.5K0
6.18 ,一波行业专属域名来袭!
很多用户在注册域名的时候,往往都会优先考虑.com。实际上,有很多小众的后缀,因为其本身就具有的含义,搭配不同的前缀,反而成为了一个过目不忘的独特“标识”。 这一期,我们就这些为这一波小众域名”正名“,好价又好记! .icu,在所有其他的三字符域名后缀中,.icu是最独特的其中一种。.icu相当简短、好记。而且这个域名可以代表多种不同意思;“我看见你”,“重症监护室”,对于医疗相关行业再适用不过了。戳下图直达.icu后缀活动价:首年4元起。 .love域名爱象征着浪漫、家庭、情感、热情和赞颂。.lov
腾讯云DNSPod团队
2020/06/22
8310
活动 | 腾讯云证通 给你送长鹅~
腾讯云证通 暖冬活动 一站式数字资产管理平台 双十一都买了什么? 手还在吗? 小灵通来送温(chang)暖(e)啦 (简单粗暴) 福利1:开通有礼 免费开通 参与方法:登录腾讯云证通控制台,点击【立即开通】按钮,即可领取 开通好礼: 域名新注 无门槛代金券 10元 商标新注 无门槛代金券  5元 代金券数量有限,先到先得,抢完为止~ 福利2:上传有礼 首次成功上传资产 参与方法:登录腾讯云证通控制台,在【资质证照】、【知识产权】、【数字证书】任一页面中,首次成功上传数字资产,即可领取 上
腾讯云DNSPod团队
2021/11/15
1.9K0
七夕,你的情人在哪里?
他来了她来了 在七夕情人节它来了 它带着甜蜜代金券向你走来了! 很多朋友常常和D妹抱怨,SSL证书产品种类太多,什么国际国密,什么OV EV DV,什么单域名多域名泛域名,每次打开下单页面都要反反复复犹豫很久,到最后干脆不买了! 这怎么行?!D妹绝对不会让朋友们在DNSPod出现选购难的情况。为此,D妹赶紧让研发同学加班加点给大家推出了“证书测一测”活动,大家只需要完成个位数的测试题,即可马上知道自己到底需要哪一款证书! 无论你是政府行业的朋友、金融行业的朋友、教育行业的朋友,等来自各行各业,都可以在这个
腾讯云DNSPod团队
2021/08/17
4480
用户故事:不再和你擦肩而过
今天这篇推送,是一个悲伤的故事。 在上周的公众号,我们推送了.club的活动:薅羊毛党速进 D妹又送福利了 发完推送,D妹就欢快的去迎接周末了。 今天,D妹突然收到了用户的反馈: D妹,你快看,我上周用8块钱薅了好多! 今天再注册,都要2000了欸! D妹定睛一看,这位朋友,你可太会了,其中甚至还有6688这样的精品数字! 而今天打开DNSPod,再次尝试注册四数字.club, 发现已经赫然变成了精品域名。 曾经有一个8块钱可以拥有你的机会,我没有珍惜 。 当你昂首一变变成了4位数
腾讯云DNSPod团队
2020/07/17
4190
前行路上,无忧相伴
520好礼 腾讯云服务器公众号后台回复「520」 参与领取轻量应用服务器随机金额代金券 限量520张,最高1314元 SMB 腾讯云中小企业产品中心     腾讯云中小企业产品中心(简称SMB),作为腾讯云体系中唯一专业服务于8000万中小企业的业务线,致力于为中小微企业提供全面完善贴心的数字化解决方案。产品线覆盖了企业客户从创业起步期、规范治理期、规模化增长期、战略升级期等全生命周期,针对性的解决企业的信息化、数字化、智能化的生产力升级需求。本中心还拥有两大独立腾讯子品牌:DNSPod与D
腾讯云DNSPod团队
2021/05/28
5080
D妹上新|一键修改DNS,用上了吗?
一键修改DNS,适用于什么场景: 1.如果用户刚刚将域名从其他注册商转入腾讯云,但是还没来得及用上腾讯云提供的解析服务。 2.如果用户的域名是在腾讯云注册的,但是自己曾经修改了NS记录,解析用了其他家的服务器,现在又希望修改回来。 如果你符合上述两个场景,那么D妹今天要介绍的这个小功能,一定能让你感叹,真方便! 注意:新注册的域名 DNS 服务器地址默认为免费套餐对应的 DNS 服务器地址,若您不需要升级套餐,则无需调整DNS 服务器地址。 一键修改DNS,怎么用? 1.登录腾讯云控制台。点击域名管理
腾讯云DNSPod团队
2020/07/03
1.4K0
一键HTTPS | 特邀您参与用户调研
一 键 加 密 啦 嘿,各位新老朋友们,一晃眼 腾讯云「一键HTTPS」上线两个月啦 这两个月里,我们吸引了2W+新用户 被吐槽,被质疑,也被夸赞 唯一不变的是,我们在不断追求进步 期待您真诚的建(tu)议(cao) 在了解功能更新前 给新朋友预习,给老朋友复习 ⬇⬇⬇ 神器是啥 ✔ 一键 HTTPS 是 SSL 证书结合腾讯云 Web 应用防火墙而开发的快速部署HTTPS 的产品。 ✔ 使用该功能,您无需进行繁琐的 SSL 证书部署操作,仅需配置一个CNAME 解析,即可实现从 HTTP 到 HT
腾讯云DNSPod团队
2021/09/06
4340
官宣 | 腾讯云证通 正式上线!(内含域名/商标等代金券…)
TencentCloud Digital Credential Platform TDCP 腾讯云证通 正式上线 数字资产听起来是一个新潮时髦的概念 但实际上TA在我们身边无处不在 资质证照、知识产权等都是数字资产 突击测试 您拥有多少数字资产? 这些数字资产都位于何处? 这些数字资产什么时候到期? 是否需要定期更新?到期前多久可以续存? 礼貌三连问 幸好! 我们有腾讯云证通 一站式的数字资产管理平台 帮助您管理这些分散的数字资产 避免您陷入浪费时间的陷阱 一张图带您了解腾讯云证通
腾讯云DNSPod团队
2021/09/26
2K0
恭喜你成为腾讯云锦鲤
       重磅! 9月11号,我们「DNSPod十问」栏目 将邀请到一位特殊嘉宾!  同时,为了庆祝腾讯云十周年 预祝腾讯云数字生态大会的举办 我们将在11号这一期的「十问」 公众号文章的评论区 抽取一位腾讯云超级锦鲤! (抽取方式,将在11号公布) 送出下列图中 全部!全部!全部! 奖品! 『万千宠爱,只给你一人』 腾讯云超级锦鲤,会是你吗? 另外,除了超级锦鲤, 我们还会抽出两尾小锦鲤, 同样送上多多多多多多款云产品! 话不多说,定好闹钟! 9月11日,上午9点 约定DNSPod公众
腾讯云DNSPod团队
2020/09/07
7040
为什么要做网站备案?
很多用户不理解,对于网站服务器在国内的网站来说,网站备案是工信部的要求,是必须要完成的工作,如果网站没有备案,就无法展示给用户浏览。网站备案是为了规范网络安全,维护经营者的合法权益,保护用户的合法权益。 为什么要做网站备案? 那么,网络备案有什么好处呢?我们一起来看看吧! 1、网站信任度高 用户在浏览网站的时候,会注意到网站有没有备案,如果网站没有备案,那么网站的信任度就会很低,如果网站有备案,那么网站的信任度就会很高。当用户在浏览网站的时候,发新网站没有备案,用户就会对网站产生不信任感,从而对网站失
腾讯云DNSPod团队
2020/07/03
1.9K0
是时候关注 .today和.world了!
不是我不明白,这世界变化快!老崔的歌总是那么富有前瞻性,突飞猛进的发展,让我们今天的世界发生了翻天覆地的变化。即使在域名这个垂直行业里,也早已不是.com的寡头世界了。 自新通用顶级域名开放以来,数以千计的新后缀面世,这其中Donuts域名注册局以242个域名后缀数量傲视群雄。而这其中“.today”、“.world”域名在这个复杂、多样且特殊的今天,让人们格外关注。 .today,专注为你 今天是崭新的一天,会有很多新鲜和期待。.today域名,可以用于与生活密切相关的行业。因为每一个访问.today网
腾讯云DNSPod团队
2020/07/03
9180
总包价29.9,云开发域名备案上线
好消息,好消息!云开发正式支持域名备案了! 虽然备案本身不需要收费,但在过去,备案前大多数都需要先购买一台服务器,而现在,你有了更低成本的选择:通过云开发的云托管服务,可以办理域名备案了!限时推广期间,总包价29.9元购买云托管备案资源包,即可开始备案。 此外,云开发还限时推出「备案多久送多久」福利:截止到11月30日,通过活动页成功购买云托管备案资源包,7天内系统会自动到账35元云开发代金券,可按需购买时长最少1个月的云开发资源,用于抵消备案期间云开发应用产生的资源消耗,做到备案0担忧! 通过云开发备
腾讯云DNSPod团队
2023/05/04
2.9K0
总包价29.9,云开发域名备案上线
相关推荐
代金券都快领完了?你还不知道有这个活动?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档