dojo还有人用吗_我的Dojo中有一个Mojo(如何编写Maven插件)

dojo还有人用吗

我一直忙于在工作中使用Maven的腋窝。 对于很多开发人员,我会听到:“那又怎样。” 区别在于,我通常在无法直接访问Internet的环境中工作。 因此,当我说我经常使用Maven时,这意味着某些事情。

依赖地狱

公平地说,我在示例中一直在随意使用Maven。 我发现下载依赖项并避免“依赖地狱”更为方便。 我必须为正在使用的库下载库的情况。 例如,必须下载Hamcrest才能使用JUnit。 在家里,放入对JUnit的依赖关系,而Maven为我下载Hamcrest,因为它是JUnit的依赖关系。 如果存在Hamcrest的依赖关系,Maven也会下载该依赖关系。 在工作时,我需要研究JUnit具有哪些依赖关系,然后研究这些依赖关系具有哪些依赖关系。 由于这种情况,我避免使用库。

形势变化

更改是因为我在工作中使用Spring Roo。 Roo使用Maven来管理它需要合并的Spring依赖项。 由于此更改,我在开发网络上设置了Nexus服务器,并开始了将依赖项从Internet转移到开发网络的过程。 这使我了解了Maven。

我对Maven的了解

在阅读了《 Maven入门》和《 Maven Build Customization》两本书之后,我对Maven以及如何创建本文的主题有了一个很好的了解。 我可以继续学习我所学到的东西,但是我会将其重点放在学习Maven插件所需的知识上。 我确实假设一个人看到了一个pom文件并从现在开始运行了一些Maven构建。 如果还没有,请购买我读过的书,或者先去http://maven.apache.org 。

Maven插件丰富

Maven基于插件架构。 在Maven中执行任何操作的都是插件。 从诸如编译之类的核心功能到创建网站。 可以想象,每个插件都有某些共同点。

Maven是面向包,生命周期,阶段和目标的

Maven以将某种内容构建到某种打包项目(例如jar文件)中而闻名。 显而易见,这是pom文件的第一行。 可能不知道的是,有一系列“阶段”或“生命周期”恰巧完成了构建程序包的过程(请参阅我在其中所做的事情)。 实际上,这些阶段之一被称为“打包”。 生命周期中的默认阶段列表如下:

  1. 验证
  2. 产生源
  3. 过程源
  4. 产生资源
  5. 流程资源
  6. 编译
  7. 过程类
  8. 生成测试源
  9. 流程测试源
  10. 生成测试资源
  11. 流程测试资源
  12. 测试编译
  13. 过程测试类
  14. 测试
  15. 准备包装
  16. 包
  17. 整合前测试
  18. 整合测试
  19. 整合后测试
  20. 校验
  21. 安装
  22. 部署

Maven构建中正在进行很多工作! 所有这些都由某种插件运行。 每个插件都是由可以设置为在生命周期的特定阶段运行的目标组成的。 例如,将maven-jar-plugin的jar目标设置为在打包阶段运行。

制作插件

既然已经对构建过程进行了更深入的了解,是时候解释创建Maven插件所需的内容了。

插件充满了Mojos

什么是魔力? Mojo是Maven普通的Old Java Objects的缩写。 它是Maven识别的插件的最小单位。 所有插件均由mojos制成。 每个mojo与一个目标相关联。 因此,要使一个插件具有多个目标,就需要多个mojo。 可悲的是,我将仅显示一个示例,但是该示例还将显示测试插件的最佳实践。

最佳实践是唯一允许的实践

看看我在标题中与Dojo交易相关的工作吗? 如果有兴趣,编写插件涉及命名约定,单元测试和集成测试。 命名约定是最重要的

  1. 您不会破坏Apache商标
  2. 其他人知道一个人做了一个插件。

名称是什么?

Apache插件的命名约定为maven- <title> -plugin。 例如,jar插件名为maven-jar-plugin。 对于其他所有人,命名约定为<title> -maven-plugin。 例如,我创建的示例名为hinter-maven-plugin。 发表本文时使用的另一个示例是Spring Boot的插件,它名为spring-boot-maven-plugin。 Spring Boot的源代码在这里 。 我分叉了它,所以我可以细读和滥用代码。 我的叉子可以在这里找到。 如果您想一起滥用它,请在完成您特定的滥用行为后,将我的副本分叉并发送给我请求请求。 无论如何,如果使用Apache的命名约定,那就是商标侵权。 你被警告了。

单元测试

自动化的单元和集成测试也很重要。 单元测试所遵循的目录模式与普通单元测试略有不同,因此请耐心等待。

对插件进行单元测试时的目录结构为

unit_test_plugin

请注意,所有测试目录都组织在测试目录下。 一个正在制作的是将使用该插件的项目的一个小版本。 测试资源目录下是一个单元目录,其后是子目录中的单元名称。 目标是一次测试一个Mojo。 由于我的示例只有一个mojo,因此我仅设置了一个测试。 除了目录设置以外,还有其他区别,但示例部分将进行介绍。

整合测试

我发现该测试将使您最大程度地了解一个人的特定插件及其工作方式。 目标是测试某种情况,就像它是实际项目构建的一部分一样。 当我指的是实际项目构建时,我的意思是甚至有一个仅用于集成构建的临时存储库。 在阅读了有关如何设置测试的信息之后,我大量借鉴了spring-boot-maven-plugin的集成测试设置和mini pom文件。 好的,我将一些文件复制到示例代码中。 只是通知一个人Spring Boot做得对。 只是为了安全起见,一个克隆只读文件或派生他们的代码才是安全的。 目录结构如下所示。

it_test_plugin

集成测试不在test目录下,而是位于it目录中src目录下。 我本可以做更多的集成测试,但到目前为止已经足够了。

例

该示例插件的灵感来自于我心不在and,需要提醒我所做的一切。 我曾想创建一个“洗狗提醒” Maven插件,但是我决定使用一个简单的“提醒” Maven插件,因为这样我就可以用它来提醒我需要做的任何事情。

Pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.darylmathison</groupId><artifactId>reminder-maven-plugin</artifactId><packaging>maven-plugin</packaging><version>1.0-SNAPSHOT</version><name>reminder-maven-plugin Maven Mojo</name><url>http://maven.apache.org</url><properties><mavenVersion>3.2.1</mavenVersion><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><!-- Maven dependencies --><dependency><groupId>org.apache.maven</groupId><artifactId>maven-plugin-api</artifactId><version>${mavenVersion}</version></dependency><dependency><groupId>org.apache.maven</groupId><artifactId>maven-core</artifactId><version>${mavenVersion}</version></dependency><dependency><groupId>org.apache.maven.plugin-tools</groupId><artifactId>maven-plugin-annotations</artifactId><version>3.2</version><scope>provided</scope></dependency><dependency><groupId>org.apache.maven</groupId><artifactId>maven-compat</artifactId><version>3.2.1</version><scope>test</scope></dependency><dependency><groupId>org.apache.maven.plugin-testing</groupId><artifactId>maven-plugin-testing-harness</artifactId><version>3.1.0</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies><build><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-plugin-plugin</artifactId><version>3.2</version><executions><execution><id>mojo-descriptor</id><goals><goal>descriptor</goal></goals></execution></executions><configuration><skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound></configuration></plugin></plugins></pluginManagement></build><profiles><profile><id>run-its</id><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-invoker-plugin</artifactId><version>1.7</version><configuration><debug>true</debug><cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo><cloneClean>true</cloneClean><pomIncludes><pomInclude>*/pom.xml</pomInclude></pomIncludes><addTestClassPath>true</addTestClassPath><postBuildHookScript>verify</postBuildHookScript><localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath><settingsFile>src/it/settings.xml</settingsFile><goals><goal>clean</goal><goal>compile</goal><goal>package</goal></goals></configuration><executions><execution><id>integration-test</id><goals><goal>install</goal><goal>run</goal></goals></execution></executions></plugin></plugins></build></profile></profiles>
</project>

如人们所见,构建一个插件需要很多插件和依赖项。 这里有一个注释依赖项。 这是Junit的版本。 该版本必须为3.8.1。 这是因为Maven扩展了TestCase类,以使其更易于进行单元测试。 很快就会看到。 需要注意两个插件,一个是maven-plugin-plugin,另一个是maven-invoker-plugin。 maven-plugin-plugin可以自动为一个插件创建帮助目标。 maven-invoker-plugin用于集成测试。 它的功能是运行Maven项目,如果一个人正在测试pom中运行它就很方便。

提醒Mojo.java

package com.darylmathison;import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;@Mojo(name = "remind",defaultPhase = LifecyclePhase.PACKAGE,requiresOnline = false, requiresProject = true,threadSafe = false)
public class ReminderMojo extends AbstractMojo {@Parameter(property = "basedir", required = true)protected File basedir;@Parameter(property = "message", required = true)protected String message;@Parameter(property = "numOfWeeks", defaultValue = "6", required = true)protected int numOfWeeks;public void execute() throws MojoExecutionException {File timestampFile = new File(basedir, "timestamp.txt");getLog().debug("basedir is " + basedir.getName());if(!timestampFile.exists()) {basedir.mkdirs();getLog().info(message);timestamp(timestampFile);} else {LocalDateTime date = readTimestamp(timestampFile);date.plus(numOfWeeks, ChronoUnit.WEEKS);if(date.isBefore(LocalDateTime.now())) {getLog().info(message);timestamp(timestampFile);}}}private void timestamp(File file) throws MojoExecutionException {try(FileWriter w = new FileWriter(file)) {LocalDateTime localDateTime = LocalDateTime.now();w.write(localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));} catch (IOException e) {throw new MojoExecutionException("Error creating file " + file, e);}}private LocalDateTime readTimestamp(File file) throws MojoExecutionException {try(FileReader r = new FileReader(file)) {char[] buffer = new char[1024];int len = r.read(buffer);LocalDateTime date = LocalDateTime.parse(String.valueOf(buffer, 0, len));return date;} catch(IOException ioe) {throw new MojoExecutionException("Error reading file " + file, ioe);}}
}

这是插件中唯一的Mojo,并且可以找到,它非常简单,但是显示了Mojo api提供的一些很酷的功能。 类注释定义目标的名称为“ remind”,并且它不是线程安全的。 它还定义了默认阶段为打包阶段。 我要提到的最后一件事是任何成员变量都可以成为参数。 这成为目标插件的参数。

提醒MojoTest

package com.darylmathison;import org.apache.maven.plugin.testing.AbstractMojoTestCase;import java.io.File;/*** Created by Daryl on 3/31/2015.*/
public class ReminderMojoTest extends AbstractMojoTestCase {@Overrideprotected void setUp() throws Exception {super.setUp();}@Overrideprotected void tearDown() throws Exception {super.tearDown();}public void testJustMessage() throws Exception {File pom = getTestFile("src/test/resources/unit/reminder-mojo/pom.xml");assertNotNull(pom);assertTrue(pom.exists());ReminderMojo myMojo = (ReminderMojo) lookupMojo("remind", pom);assertNotNull(myMojo);myMojo.execute();}
}

这是mojo的基本单元测试用例。 测试类扩展AbstractMojoTestCase以获得一些功能,如getTestFile和lookupMojo。 以下是测试pom文件。

单元测试Pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.darylmathison.test</groupId><artifactId>reminder-maven-plugin-test-reminder</artifactId><packaging>jar</packaging><version>1.0-SNAPSHOT</version><name>reminder-maven-plugin Maven Mojo</name><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>com.darylmathison</groupId><artifactId>reminder-maven-plugin</artifactId><version>1.0-SNAPSHOT</version><configuration><basedir>target/test-classes/unit/reminder-mojo</basedir><message>Wash the doggies</message></configuration></plugin></plugins></build>
</project>

只是定义插件的主pom文件的迷你版本。

整合测试

这是值得的,因为它实际上是Maven项目中的一个单独的Maven项目。 本练习的主要重点是查看插件将执行的操作,而不是其他操作。 该示例应用程序很简单,就可以在其中构建Maven项目。 要注意的另一件事是pom文件使用一些过滤来匹配groupId,artifactId和主插件pom的版本。

Pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.darylmathison.it</groupId><artifactId>new-timestamp</artifactId><version>0.0.1.BUILD-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><build><plugins><plugin><groupId>@project.groupId@</groupId><artifactId>@project.artifactId@</artifactId><version>@project.version@</version><executions><execution><id>blah</id><goals><goal>remind</goal></goals></execution></executions><configuration><message>Wash the doggies</message></configuration></plugin></plugins></build>
</project>

SampleApp

package java.test;/*** Created by Daryl on 4/5/2015.*/
public class SampleApp {public static void Main(String[] args) {System.out.println("out");}
}

验证

System.out.println(basedir);
def file = new File(basedir, "timestamp.txt");
return file.exists();

验证脚本是为了确保插件能够完成其预期的工作。 它只是检查timestamp.txt文件是否存在,因为该插件在找不到时间戳文件时会创建一个。 Maven检查验证脚本的输出是对还是错。

结论

哇! 我在这篇文章中介绍了很多内容。 我去举了一个如何创建一个Maven插件的例子。 我还展示了如何使用最佳实践来测试该插件。 我得到了两本书之间的信息,以及一个正在进行的开源项目的实例。 示例代码在GitHub上托管这里 。 这是我的新示例主页中的第一个示例。

参考资料

    • 介绍Maven
    • Maven构建定制
    • http://maven.apache.org
    • Sprint Boot

翻译自: https://www.javacodegeeks.com/2015/04/there-is-a-mojo-in-my-dojo-how-to-write-a-maven-plugin.html

dojo还有人用吗

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

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

相关文章

html5 css3炫酷效果,28种纯CSS3炫酷loading加载动画特效

这是一组效果非常炫酷的纯CSS3 Loading加载动画特效。这组loading动画共有27种不同的效果。每一种loading动画都是通过CSS3的keyframes帧动画来完成的&#xff0c;每一个加载动画都构思新颖&#xff0c;效果非常的酷。安装可以通过bower来按钮这个loading动画特效&#xff1a;b…

中点和中值滤波的区别_频谱仪和EMI测试接收机什么区别?安泰维修中心分享

测试人员在选择使用射频仪器的时候都在纠结选择频谱仪还是测试接收机又或者信号分析仪。下面由安泰频谱分析仪维修中心分享频谱仪和EMI测试接收机什么区别&#xff1f;测量接收机是什么&#xff1f;频谱仪和信号分析仪什么区别&#xff1f;信号源分析仪是什么&#xff1f;一、频…

C++ 面试必问:深入理解虚函数表

点击蓝字关注我们深入理解C 虚函数表C中的虚函数的作用主要是实现了多态的机制。关于多态&#xff0c;简而言之就是用父类型别的指针指向其子类的实例&#xff0c;然后通过父类的指针调用实际子类的成员函数。Derive d; Base1 *b1 &d; Base2 *b2 &d; Base3 *b3 &…

html 图片剪裁压缩,HTML5 canvas实现图片拉伸、压缩与裁剪

前言&#xff1a;我们在网页中经常会用到图片展示&#xff0c;通常情况下会给一个固定的宽高来显示这个图片&#xff0c;然而从服务器端上传的图片大小是不确定的&#xff0c;如果直接按默认填充这个框有时候就会特别丑orz。作为一个完(wai)美(mao)主(xie)义(hui)者&#xff0c…

switch日文键盘打中文_12月有哪些Switch游戏值得期待?

文章转自A9vg&#xff0c;作者setsuka_duki 经历了11月的游戏浪潮后&#xff0c;一年中最后一个月份也悄然而至&#xff0c;相比较“战火连天”的11月&#xff0c;在12月发售的重量级游戏并不算太多&#xff0c;这边为大家整理12月哪些值得一玩的Switch游戏。 《Tools Up!》(分…

neo4j cypher_Neo4j:使用Cypher生成实时建议

neo4j cypherNeo4j的最常见用途之一是构建实时推荐引擎&#xff0c;一个共同的主题是它们利用大量不同的数据来提出有趣的推荐。 例如&#xff0c; 在此视频中&#xff0c; 阿曼达&#xff08;Amanda&#xff09;展示了约会网站如何通过社交联系开始&#xff0c;然后介绍热情&…

基于 C++11 的线程池 threadpool , 简洁且可以带任意多的参数

点击蓝字关注我们咳咳。C11 加入了线程库&#xff0c;从此告别了标准库不支持并发的历史。然而 c 对于多线程的支持还是比较低级&#xff0c;稍微高级一点的用法都需要自己去实现&#xff0c;譬如线程池、信号量等。线程池(thread pool)这个东西&#xff0c;在面试上多次被问到…

html jq移到出现内容,jquery操作html元素之( 获得内容和属性)

jQuery DOM 操作jQuery 中非常重要的部分&#xff0c;就是操作 DOM 的能力。jQuery 提供一系列与 DOM 相关的方法&#xff0c;这使访问和操作元素和属性变得很容易。提示&#xff1a;DOM Document Object Model(文档对象模型)DOM 定义访问 HTML 和 XML 文档的标准&#xff1a;…

c# 字典排序_Python零基础入门之列表与字典

本篇内容需结合源码&#xff0c;获取方法看末尾数据结构数据结构就是指从计算机存储、组织数据的结构列表(List) 元组(Tuple)字典(Dictionary)集合(Set)列表(List)列表中的数据按顺序排列列表有正序与倒序两种索引列表可存储任意类型数据&#xff0c;且允许重复创建列表变量名 …

jaxb xsd生成xml_使用JAXB和Jackson从XSD生成JSON模式

jaxb xsd生成xml在本文中&#xff0c;我演示了一种从XML Schema &#xff08;XSD&#xff09;生成JSON Schema的 方法 。 在概述从XML Schema创建JSON Schema的方法的同时&#xff0c;本文还演示了JAXB实现的使用&#xff08;与JDK 9捆绑在一起的xjc版本2.2.12-b150331.1824 [b…

C语言中结构体struct的用法

点击蓝字关注我们定义结构体变量下面举一个例子来说明怎样定义结构体变量。struct string { char name[8]; int age; char sex[2]; char depart[20]; float wage1, wage2, wage3, wage4, wage5; }person;这个例子定义了一个结构名为string的结构体变量person。还可以省略变量名…

html全屏漂浮,jquery全屏漂浮广告插件,可点击关闭(原创)

jquery全屏漂浮广告插件 兼容主流浏览器 实现简单 调用简单 在线预览 源码下载jquery全屏漂浮广告插件 兼容主流浏览器 实现非常简单说明&#xff1a;jquery在1.9开始不支持.live()方法的写法而改用.on()&#xff0c;见http://jquery.com/upgrade-guide/1.9/#live-removed.该插…

华南理工计算机接口技术随堂练习_研究生考试计算机408跟845有什么区别?

楼上已经解释了什么是408&#xff0c;什么是845&#xff0c;那我当时考的就是计算机408&#xff0c;我就来补充一下408该怎么复习才能拿高分吧。首先介绍一下我自己&#xff0c;计算机本科生&#xff0c;然后头铁考了某个985的计算机专业&#xff0c;最后以403分的成绩成功上岸…

关于RabbitMQ集群分区的通知

如果您在集群中运行RabbitMQ&#xff0c;则集群不太可能会被分区 &#xff08;集群的一部分失去与其余部分的连接&#xff09;。 上面的链接页面介绍了显示状态和配置行为的基本命令。 当发生分区时&#xff0c;您首先希望得到通知&#xff0c;然后再解决它。 RabbitMQ实际上使…

C++ 面试考点(二)

点击蓝字关注我们11、extern 用法&#xff1f;extern 修饰变量的声明如果文件a.c 需要引用b.c 中变量int v&#xff0c;就可以在a.c 中声明extern int v&#xff0c;然后就可以引用变量v。extern 修饰函数的声明如果文件a.c 需要引用b.c 中的函数&#xff0c;比如在b.c 中原型是…

内存不能为read进不去桌面_四级报名进不去怎么办

英语四级报名进不去怎么办?这里提供有两种方法&#xff0c;一种是重复刷新&#xff0c;直到页面出现;另外一种就是错峰报名&#xff0c;叉开登录高峰期。很多考生在报名的时候遇到困难&#xff0c;最多的就是报名页面进不去&#xff0c;这个时候有一些考生就会产生疑惑&#x…

bean创建异常_快速提示:消息驱动Bean中的异常处理

bean创建异常让我们快速回顾一下关于消息驱动Bean的特殊处理。 MDB的入口点是重写的onMessage方法。 它不提供引发检查异常的作用域&#xff0c;因此&#xff0c;如果要处理错误情形&#xff0c;则需要从代码中传播未检查异常&#xff08;java.lang.RuntimeException的子类&am…

C语言线程库的使用,这篇值得收藏!

点击蓝字关注我们1. 线程概述线程是轻量级的进程&#xff08;LWP&#xff1a;light weight process&#xff09;&#xff0c;在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合&#xff0c;指令按照既定的逻辑控制计算机运行。操作系统会以进…

alexeyab darknet 编译_【目标检测实战】Darknet—yolov3模型训练(VOC数据集)

原文发表在&#xff1a;语雀文档0.前言本文为Darknet框架下&#xff0c;利用官方VOC数据集的yolov3模型训练&#xff0c;训练环境为&#xff1a;Ubuntu18.04下的GPU训练&#xff0c;cuda版本10.0&#xff1b;cudnn版本7.6.5。经过一晚上的训练&#xff0c;模型20个类别的mAP达到…

html字符串转svg,【SVG】如何操作SVG Text

上周我们学习了如何使用元素创建SVG文本。在实例中我们设置了x和y坐标来定位文本&#xff0c;也尝试了给SVG文本中的每个字符定位。关于元素还有很多内容。在处理SVG文本时&#xff0c;不要局限于x和y属性。元素还有几个可以添加的属性&#xff0c;现在我们开始讨论吧。dx和dy属…