jaxb_JAXB –新手的观点,第2部分

jaxb

在本系列的第1部分中,我讨论了使用JAXB和JPA将数据从XML文件加载到数据库中的基础知识。 (如果需要使用JSON而不是XML,则相同的想法应转化为类似Jackson的工具。)该方法是使用共享域对象,即,一组带有描述XML映射和关系映射的注释的POJO。 。

通过使用一个.java文件来描述所有数据表示形式,可以轻松地编写数据加载器,卸载器和转换器。 从理论上讲这很简单,但随后我提到了理论与实践之间的区别。 从理论上讲,没有区别。

现在,在第2部分中,我们将介绍当要求这两个工具在一个实际的数据模型上协同工作时可能遇到的一些陷阱,以及可以用来克服这些障碍的技术。

名字叫什么?

这第一点可能很明显,但是无论如何我都会提到:与依赖于bean属性约定的任何工具一样,JAXB对您的方法名敏感。 您可以通过配置直接字段访问来避免该问题,但是正如我们很快就会看到的那样,可能有一些您想坚持使用属性访问的原因。

属性名称确定相应元素的默认标记名称(尽管可以用注释覆盖它-在最简单的情况下,例如@XmlElement)。 更重要的是,您的getter和setter名称必须匹配。 当然,最好的建议是让您的IDE生成getter和setter,这样就不会出现拼写错误。

处理@EmbeddedId

假设您要加载一些表示订单的数据。 每个订单可能有多个订单项,每个订单的订单项从1开始依次编号,因此所有订单项的唯一ID将是订单ID和订单项编号的组合。 假设您使用@EmbeddedId方法表示键,则您的订单项可能会这样表示:

@Embeddable
public class LineItemKey {private Integer orderId;private Integer itemNumber;/* … getters and setters … */
}@XmlRootElement
@Entity
@Table(name=”ORDER_ITEM”)
public class OrderLineItem {@EmbeddedId@AttributeOverrides(/*…*/)private LineItemKey lineItemKey;@Column(name=”PART_NUM”)private String partNumber;private Integer quantity;// … getters and setters …
};

编组和解组代码看起来很像第1部分中 Employee示例中的代码。 注意,由于LineItemKey类是由OrderLineItem引用的,因此我们不必显式地告诉JAXBContext有关LineItemKey类。

LineItemKey liKey = new LineItemKey();liKey.setOrderId(37042);liKey.setItemNumber(1);OrderLineItem lineItem = new OrderLineItem();lineItem.setLineItemKey(liKey);lineItem.setPartNumber(“100-02”);lineItem.setQuantity(10);JAXBContext jaxb = JAXBContext.newInstance(OrderLineItem.class);Marshaller marshaller = jaxb.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);marshaller.marshal(lineItem, System.out);

但是,我们可能不会对由此产生的XML结构感到兴奋:

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?>
<orderLineItem><lineItemKey><itemNumber>1</itemNumber><orderId>37042</orderId></lineItemKey><partNumber>100-02</partNumber><quantity>10</quantity>
</orderLineItem>

如果我们不希望<lineItemKey>元素怎么办? 如果我们让JAXB使用属性访问,那么一个选择就是更改属性定义(即我们的getter和setter),使OrderLineItem看起来像JAXB的平面对象(并可能对我们应用程序的其余部分而言);这可能是一件好事)。

@XmlRootElement
@Entity
@Table(name=”ORDER_ITEM”)
public class OrderLineItem {@EmbeddedId@AttributeOverrides(/*…*/)private LineItemKey lineItemKey;// … additional fields …@XmlTransientpublic LineItemKey getLineItemKey() {return lineItemKey;}public void setLineItemKey(LineItemKey lineItemKey) {this.lineItemKey = lineItemKey;}// “pass-thru” properties to lineItemKeypublic Integer getOrderId() {return lineItemKey.getOrderId();}public void setOrderId(Integer orderId) {if (lineItemKey == null) {lineItemKey = new LineItemKey();}lineItemKey.setOrderId(orderId);}public Integer getItemNumber() {return lineItemKey.getItemNumber();}public void setItemNumber(Integer itemNumber) {if (lineItemKey == null) {lineItemKey = new LineItemKey();}lineItemKey.setItemNumber(itemNumber);}// … additional getters and setters …
};

请注意,在lineItemKey getter上添加了@XmlTransient; 这告诉JAXB不要映射此特定属性。 (如果JPA使用字段访问,则可以完全删除lineItemKey getter和setter。另一方面,如果JPA使用属性访问,则需要将“直通”获取器标记为@Transient以防止JPA提供程序推断到ORDER_ITEM表的错误映射。)

但是,如果lineItemKey标记为@ XmlTransient,JAXB将不知道在拆组期间需要创建嵌入式LineItemKey实例。 在这里,我们通过使“传递”设置器确保实例存在来解决该问题。 JPA至少应在使用字段访问的情况下对此进行容忍。 如果您希望该方法具有线程安全性,则必须同步设置器。 或者,您可以在默认构造函数中创建LineItemKey(如果您确信JPA提供程序不会介意)。

确保仅影响JAXB(没有专用的getter和setter)的另一个选项可能是使用ObjectFactory,该ObjectFactory在返回LineItemKey之前将其注入OrderLineItem中。 但是,据我所知,ObjectFactory必须覆盖一个包中的所有类,因此,如果您在同一包中有许多简单的域对象和一些复杂的对象(并且没有其他理由来创建ObjectFactory),那么您可能要避免这种方法。

您可能还想通过在尝试获取返回值之前检查LineITemKey是否存在来保护直通getter免受空指针异常的影响。

无论如何,我们的XML现在应该如下所示:

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?>
<orderLineItem><itemNumber>1</itemNumber><orderId>37042</orderId><partNumber>100-02</partNumber><quantity>10</quantity>
</orderLineItem>

相关对象:一对多

当然,您的订单项属于订单,因此您可能有一个ORDER表(和相应的Order类)。

@XmlRootElement
@Entity
@Table(name=”ORDER”)
public class Order {@Id@Column(name=”ORDER_ID”)private Integer orderId;@OneToMany(mappedBy=”order”)private List<OrderLineItem> lineItems;// … getters and setters …
}

我们已经与OrderLineItem建立了一对多的关系。 请注意,出于JPA的目的,我们期望OrderLineItem拥有此关系。

现在,我们将从OrderLineItem中删除@XmlRootElement批注。 (我们不必这样做;注释使该类有资格成为根元素,但不排除也将其用作嵌套元素。但是,如果我们要继续编写仅表示OrderLineItem的XML,则还有一些其他的决定要做,因此我们暂时不做。)

为了使编组满意,我们将OrderLineItem @XmlTransient的Order属性。 这避免了循环引用,否则该循环引用可以解释为无限深的XML树。 (您可能始终不打算在<orderLineItem>元素下嵌入完整的订单详细信息。)

将<orderLineItem>嵌入在<order>元素下,不再需要将<orderId>元素放在<orderLineItem>下。 我们知道从应用程序中其他地方的代码仍然可以使用lineItem.getOrder()。getOrderId()来从OrderLineItem中删除orderId属性。

新版本的OrderLineItem如下所示:

@Entity
@Table(name=”ORDER_ITEM”)
public class OrderLineItem {@EmbeddedId@AttributeOverrides(/*…*/)private LineItemKey lineItemKey;@MapsId(“orderId”)@ManyToOneprivate Order order;@Column(name=”PART_NUM”)private String partNumber;private Integer quantity; @XmlTransientpublic Order getOrder() {return order;}public void setOrder(Order order) {this.order = order;}public Integer getItemNumber() {return lineItemKey.getItemNumber();}public void setItemNumber(Integer itemNumber) {if (lineItemKey == null) {lineItemKey = new LineItemKey();}lineItemKey.setItemNumber(itemNumber);}// … more getters and setters …
};

我们的JAXBContext需要被告知有关Order类的信息。 在这种情况下,无需明确告知OrderLineItem。 因此我们可以像这样测试编组:

JAXBContext jaxb = JAXBContext.newInstance(Order.class);List<OrderLineItem> lineItems = new ArrayList<OrderLineItem>();Order order = new Order();order.setOrderId(37042);order.setLineItems(lineItems);OrderLineItem lineItem = new OrderLineItem();lineItem.setOrder(order);lineItem.setLineNumber(1);lineItem.setPartNumber(“100-02”);lineItem.setQuantity(10);lineItems.add(lineItem);lineItem = new OrderLineItem();lineItem.setOrder(order);lineItem.setLineNumber(2);lineItem.setPartNumber(“100-17”);lineItem.setQuantity(5);lineItems.add(lineItem);Marshaller marshaller = jaxb.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);marshaller.marshal(order, System.out);

请注意,我们为每个订单项设置了order属性。 编组时,JAXB不会关心此问题(因为该属性为@XmlTransient,并且其他属性均不取决于它影响的内部状态),但我们希望保持对象关系的一致性。 如果我们要将订单传递给JPA,那么无法设置order属性将成为一个问题-我们很快就会回到这一点。

我们应该得到这样的输出:

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?><order><orderId>37042</orderId><lineItems><lineNumber>1</lineNumber><partNumber>100-02</partNumber><quantity>10</quantity></lineItems><lineItems><lineNumber>2</lineNumber><partNumber>100-17</partNumber><quantity>5</quantity></lineItems></order>

默认元素名称映射在每个订单项周围放置一个<lineItems>标记(因为这是属性名称),这有点差。 我们可以通过将@XmlElement(name =“ lineItem”)放在Order的getLineItems()方法上来解决此问题。 (然后,如果我们希望将整个订单项元素列表包装在单个<lineItems>元素中,则可以在同一方法上使用@XmlElementWrapper(name =“ lineItems”)批注来实现。)

此时,封送测试应该看起来不错,但是如果取消封送订单并要求JPA保留生成的订单行项目对象,就会遇到麻烦。 问题在于解组器未设置OrderLineItem的order属性(出于JPA的目的,该属性拥有Order-to-OrderLineItem关系)。

我们可以通过让Order.setLineItems()遍历订单项列表并在每个订单项上调用setOrder()来解决此问题。 这依赖于JAXB首先构建订单项列表,然后将其传递给setLineItems();。 它在我的测试中起作用,但是我不知道它是否将始终与所有JAXB实现一起起作用。

另一种选择是在解组之后但将对象传递给JPA之前,在每个OrderLineItem上调用setOrder()。 这也许更简单,但是感觉就像是在跳动。 (封装的部分要点是,您的设置员应该可以确保对象始终保持内部一致的状态;那么为什么要将这种责任转移给对象类之外的代码呢?)

为了简化操作,在尝试解决此问题时,我将跳过一些我曾想过的更详细的想法。 稍后我们将讨论@XmlID和@XmlIDREF时,我们将讨论另一种解决方案。

财产获取案例

我依靠修改后的二传手来解决前两个问题。 如果您习惯了设置器应该只有一行(this.myField = myArgument)的想法,这似乎值得怀疑。 (然后再次,如果您不让设置员为您做任何工作,那么通过封装字段来购买什么?)

@XmlTransientpublic List<OrderLineItem> getLineItems() {return lineItems;}public void setLineItems(List<OrderLineItem> lineItems) {this.lineItems = lineItems;}// @Transient if JPA uses property access@XmlElement(name=”lineItem”)public List<OrderLineItem> getLineItemsForJAXB() {return getLineItems();}public void setLineItemsForJAXB(List<OrderLineItems> lineItems) {setLineItems(lineItems);// added logic, such as calls to setOrder()…}

如果需要,您可以避免在应用程序的其他任何地方使用“ ForJAXB”属性,因此,如果您觉得必须“仅针对JAXB”添加设置器逻辑,则该方法将阻止添加的逻辑妨碍您。

但是,以我的观点,我上面描述的setter逻辑类型只是从外部代码中隐藏了bean属性的实现细节。 我认为在这些情况下,JAXB鼓励更好的抽象。

如果您认为JAXB是序列化对象内部状态的一种方法,那么字段访问似乎更可取。 (我听说过要在任何情况下都将JPA与字段访问一起使用的论点。)不过,到最后,您希望该工具为您完成工作。 将JAXB视为构建(或记录)对象的外部机制可能更加实用。

相关对象:一对一,多对多

在一对多关系正常工作的情况下,似乎一对一关系应该很容易。 但是,尽管一对多关系通常会使其具有XML的层次结构性质(“许多”是“一个”的子代),但一对一关系中的对象通常只是对等体; 因此,充其量,将一个元素嵌入另一个XML表示形式的选择是任意的。

多对多关系对层次模型提出了更大的挑战。 而且,如果您有一个更复杂的关系网络(无论其基数如何),可能没有一种直接的方法将对象排列成树。

在探索通用解决方案之前,最好暂时停顿一下,问问自己是否需要通用解决方案。 我们的项目需要加载两种符合父子关系的对象,因此我之前描述的技术就足够了。 可能是您根本不需要将整个对象模型保存为XML。

但是,如果您确实发现需要建模不适合父子模型的关系的方法,则可以使用@XmlID和@XmlIDREF来实现。

当您学习使用@XmlID的规则时,您可能会问自己,将原始外键元素存储在reference元素下是否容易(类似于RDBMS通常表示外键的方式)。 您可以,并且编组将不会产生漂亮的XML问题。 但是在解组期间或之后,您将负责自行重组关系图。 @XmlID的规则很烦人,但是我发现它们很难适应,避免它们会证明这种努力是合理的。

ID值必须是字符串,并且它们在XML文档中的所有元素(不仅是给定类型的所有元素)中必须是唯一的。 这是因为从概念上讲,ID引用是无类型的。 实际上,如果让JAXB从架构构建域对象,它将把您的@XmlIDREF元素(或属性)映射到Object类型的属性。 (但是,当注释自己的域类时,只要引用的类型具有以@XmlID注释的字段或属性,就可以将@XmlIDREF与带类型的字段和属性一起使用。我宁愿这样做,因为这样可以避免不必要的强制转换在我的代码中。)建立关系的键可能不遵循这些规则; 但这没关系,因为您可以创建一个属性(例如,名为xmlId)。

假设我们的每个订单都有一个客户和一个“收货人”地址。 此外,每个客户都有一个帐单邮寄地址列表。 数据库中的两个表(CUSTOMER和ADDRESS)都使用Integer代理键,其顺序从1开始。

在我们的XML中,“客户”和“收货人”地址可以表示为“订单”下的子元素; 但也许我们需要跟踪当前没有任何订单的客户。 同样,帐单地址列表可以表示为“客户”下的子元素列表,但这将不可避免地导致数据重复,因为客户将订单运送到了帐单地址。 因此,我们将使用@XmlID。

我们可以如下定义地址:

@Entity@Table(name=”ADDRESS”)public class Address {@Id@Column(name=”ADDRESS_ID”)private Integer addressId;// other fields…@XmlTransientpublic Integer getAddressId() {return addressId;}public void setAddressId(Integer addressId) {this.addressId = addressId;}// @Transient if JPA uses property access@XmlID@XmlElement(name=”addressId”)public String getXmlId() {return getClass().getName() + getAddressId();}public void setXmlId(String xmlId) {//TODO: validate xmlId is of the form <className><Integer>setAddressId(Integer.parseInt(xmlId.substring( getClass().getName().length() )));}// … more getters and setters …
}

这里的xmlId属性提供了JAXB的addressId视图。 在类名前面加一个可在其键可能会冲突的类型之间提供唯一性。 如果表具有更复杂的自然键,则必须将键的每个元素转换为字符串,并可能使用某种分隔符,并将其全部串联在一起。

这种想法的一种变体是使用@XmlAttribute而不是@XmlElement。 我通常更喜欢使用元素作为数据值(因为它们在逻辑上是文档的内容),但是XmlId可以说是描述<Address> XML元素,而不是地址本身,因此记录起来可能很有意义作为属性。

为了解组工作,我们还必须从setter的xmlId中解析出addressId值。 如果我们同时保留xmlId属性和addressId属性,则可以避免这种情况。 在这种情况下,xmlId setter可能会丢掉它的值; 但是我不喜欢该选项,因为它可以节省相对较少的工作量,并且有可能遇到XMLId和addressId值不一致的XML文档。 (有时您可能不得不承认文档不一致的可能性,例如,如果您坚持恋爱关系的双方,我将在后面讨论。)

接下来,我们将创建客户映射:

@Entity@Table(name=“CUSTOMER”)public class Customer {@Id@Column(name=”CUSTOMER_ID”)private Integer customerId;@ManyToMany@JoinTable(name = “CUST_ADDR”)private List<Address> billingAddresses;// other fields…@XmlTransientpublic Integer getCustomerId() {return customerId;}public void setCustomerId(Integer customerId) {this.customerId = customerId;}@XmlIDREF@XmlElement(name = “billingAddress”)public List<Address> getBillingAddresses() {return billingAddresses;}public void setBillingAddresses(List<Address> billingAddresses) {this.billingAddresses = billingAddresses;}// @Transient if JPA uses property access@XmlID@XmlElement(name=”customerId”)public String getXmlId() {return getClass().getName() + getCustomerId();}public void setXmlId(String xmlId) {//TODO: validate xmlId is of the form <className><Integer>setCustomerId(Integer.parseInt(xmlId.substring( getClass().getName().length() )));}// … more getters and setters …}

客户的xmlId的处理与地址的处理相同。 我们用@XmlIDREF批注标记了billingAddresses属性,告诉JAXB每个<billingAddress>元素都应包含一个引用地址的ID值,而不是实际的Address元素结构。 以同样的方式,我们将customer和shipToAddress属性添加到Order中,并用@XmlIDREF注释。

此时,所有对客户或地址的引用都被标记为@XmlIDREF。 这意味着尽管我们可以将数据封送为XML,但结果实际上将不包含任何Customer或Address数据。 如果在您解组时@XmlIDREF与文档中的@XmlID不对应,则未编组对象上的相应属性将为null。 因此,如果我们真的希望这样做,我们必须创建一个新的@XmlRootElement来包含所有数据。

@XmlRootElementpublic class OrderData {private List<Order> orders;private List<Address> addresses;private List<Customer> customers;// getters and setters}

此类与我们数据库中的任何表都不对应,因此它没有JPA批注。 与先前的List-type属性一样,我们的getter可以具有@XmlElement和@XmlElementWrapper批注。 如果我们组装并封送一个OrderData对象,则可能会得到以下内容:

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?><orderData><addresses><address><addressId>Address1010</addressId><!-- … other elements … --></address><address><addressId>Address1011</addressId><!-- … --></address></addresses><customers><customer><billingAddress>Address1010</billingAddress><billingAddress>Address1011</billingAddress><customerId>Customer100</customerId></customer></customers><orders><order><customer>Customer100</customer><lineItem><itemNumber>1</itemNumber><partNumber>100-02</partNumber><quantity>10</quantity></lineItem><lineItem><lineNumber>2</lineNumber><partNumber>100-17</partNumber><quantity>5</quantity></lineItem><orderId>37042</orderId><shipToAddress>Address1011</shipToAddress></order></orders></orderData>

到目前为止,我们仅映射了每个关系的一侧。 如果我们的域对象需要支持双向导航,则可以选择:我们可以将关系一侧的属性标记为@XmlTransient; 这使我们处在与以分层表示的一对多关系相同的情况下,解组将不会自动设置@XmlTransient属性。 或者,我们可以将两个属性都设置为@XmlIDREF,因为意识到有人可能会编写不一致的XML文档。

回顾相关对象:一对多

早些时候,当我们查看一对多关系时,我们仅依赖于包含-嵌入在父元素中的子元素。 包容性的局限性之一是它只允许我们映射关系的一侧。 由于我们的域对象需要反向关系才能与JPA配合使用,因此这在解组期间使我们跳过了一些麻烦。

我们已经看到@XmlID和@XmlIDREF提供了更一般的关系表示。 混合使用这两种技术,我们可以表示父子关系的两面(需要注意的是,就像我们在XML中显示关系的两面一样,您可以手工编写具有不一致关系的XML文档)。

我们可以修改前面的一对多示例,使其看起来像这样:

@XmlRootElement
@Entity
@Table(name=”ORDER”)
public class Order {@Id@Column(name=”ORDER_ID”)private Integer orderId;@OneToMany(mappedBy=”order”)private List<OrderLineItem> lineItems;@XmlTransientpublic Integer getOrderId() {return orderId;}public void setOrderId(Integer orderId) {this.orderId = orderId;}@XmlID@XmlElement(name=”orderId”)public String getXmlId() {return getClass().getName() + getOrderId;}public void setXmlId(String xmlId) {//TODO: validate xmlId is of the form <className><Integer>setOrderId(Integer.parseInt(xmlId.substring( getClass().getName().length() )));}@XmlElement(“lineItem”)public List<OrderLineItem> getLineItems() {return lineItems;}public void setLineItems(List<OrderLineItem> lineItems) {this.lineItems = lineItems;}
}@Entity
@Table(name=”ORDER_ITEM”)
public class OrderLineItem {@EmbeddedId@AttributeOverrides(/*…*/)private LineItemKey lineItemKey;@MapsId(“orderId”)@ManyToOneprivate Order order;@Column(name=”PART_NUM”)private String partNumber;private Integer quantity; @XmlIDREFpublic Order getOrder() {return order;}public void setOrder(Order order) {this.order = order;}public Integer getItemNumber() {return lineItemKey.getItemNumber();}public void setItemNumber(Integer itemNumber) {if (lineItemKey == null) {lineItemKey = new LineItemKey();}lineItemKey.setItemNumber(itemNumber);}// … more getters and setters …
}

当编组Order时,我们现在将orderId写为XML ID。 我们没有使用OrderLineItem @XmlTransient的order属性,而是通过写@XmlIDREF而不是完整的Order结构来避免无限递归; 因此,双方的关系都以我们在解组时可以理解的方式得以保留。

生成的XML如下所示:

<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?><order><orderId>Order37042</orderId><lineItem><lineNumber>1</lineNumber><order>Order37042</order><partNumber>100-02</partNumber><quantity>10</quantity></lineItem><lineItem><lineNumber>2</lineNumber><order>Order37042</order><partNumber>100-17</partNumber><quantity>5</quantity></lineItem></order>

而编组和解组工作都是我们想要的。 重复包含订单ID值是我们可能对输出唯一的抱怨。 我们可以通过使用@XmlAttribute而不是@XmlElement来减少视觉影响。 这是另一种情况,我们可能会认为该值不是“真实内容”,因为我们只是将其放入以帮助JAXB进行编组。

总结思想

如标题所示,我作为JAXB的新手经历了本练习。 这绝不是关于JAXB可以做什么的全面讨论,从我阅读的文档中,我什至说我已经忽略了它的一些最复杂的功能。

但是,我希望这可以作为有用的入门,并可以说明来自bean约定以及与POJO进行友好交互的工具和框架的强大功能。

我还要重申一点,就是您可以根据自己的意愿使这种技术变得复杂。 因此,了解您的需求真正需要多少复杂度是关键。

翻译自: https://www.javacodegeeks.com/2014/09/jaxb-a-newcomers-perspective-part-2.html

jaxb

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

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

相关文章

redis是什么_什么是Redis?为什么我们要用Redis?

前言当结束Java和数据库的学习以后&#xff0c;你就会接触到Redis这个词&#xff0c;我第一次听到的时候脑海里就会浮现这两个问题&#xff1a;什么是Redis&#xff1f;为什么我们要用Redis&#xff1f;我了解完以后&#xff0c;写出来帮助大家能够更快的认识它。我们先来看它的…

php strpos无效,簡單的PHP strpos功能不起作用,為什么?

Why isnt this standalone code working:為什么這個獨立代碼不起作用&#xff1a;$link https://google.com;$unacceptables array(https:,.doc,.pdf, .jpg, .jpeg, .gif, .bmp, .png);foreach ($unacceptables as $unacceptable){if (strpos($link, $unacceptable) true) {…

java基准测试_星期五基准功能Java

java基准测试让我们的产品所有者有一天变得疯狂&#xff0c;并要求您执行以下操作&#xff1a; From a set of Strings as follows : “ marco_8”&#xff0c;“ john_33”&#xff0c;“ marco_1”&#xff0c;“ john_33”&#xff0c;“ thomas_5”&#xff0c;“ john_3…

python2048游戏代码_【Python】用Python实现2048小游戏(源代码,1.0版本)

#2048 用python实现import randomimport mathimport osglobal scorescore 0def start():#开始a [[0 for i in range(4)] for i in range(4)] #构造一个4*4的列表i random.randint(0,3)j random.randint(0,3)p2 random.random()if p2>0.9: a[i][j] 4 #有0.9几率出现2el…

性能php 教程,提高PHP性能效率的几个技巧

如何提高效率问题&#xff0c;往往同样的功能&#xff0c;不一样的代码&#xff0c;出来的效率往往大不一样。● 用单引号代替双引号来包含字符串&#xff0c;这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量&#xff0c;单引号则不会&#xff0c;注意&#xff1a;…

oop 类和对象的_实用程序类的OOP替代

oop 类和对象的实用程序类&#xff08;也称为帮助程序类&#xff09;是仅具有静态方法且不封装状态的“结构”。 StringUtils &#xff0c; IOUtils &#xff0c; FileUtils从Apache的共享 ; Guava的 Iterables和Iterators以及JDK7的Files是实用程序类的完美示例。 这种设计思…

python读取json数据格式问题_浅谈Python中的异常和JSON读写数据的实现

异常可以防止出现一些不友好的信息返回给用户&#xff0c;有助于提升程序的可用性&#xff0c;在java中通过try ... catch ... finally来处理异常&#xff0c;在Python中通过try ... except ... else来处理异常一、以ZeroDivisionError为例&#xff0c;处理分母为0的除法异常de…

python from numpy import,python zeros()使用(from numpy import *)-Go语言中文社区

参考&#xff1a;############################################################函数zeros()在模块numpy中&#xff1a;from numpy import *help(zeros)该函数功能是创建给定类型的矩阵&#xff0c;并初始化为0参数简洁&#xff1a;shape&#xff1a;可以是int类型数据&#x…

OCA第5部分中的Java难题

在Java Puzzlers系列的第五部分中&#xff0c;我们将看到与X.parseX&#xff08;String s&#xff09;方法相关的内容。 您可以看到我们对X.parseX&#xff08;&#xff09;方法的期望。 public class Puzzler { public static void main(String[] args){ int i Integer.pars…

sqlmap绕过d盾_Waf功能、分类与绕过

## 一. waf工作原理Web应用防火墙是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。常见的系统攻击分为两类&#xff1a;- 一是利用Web服务器的漏洞进行攻击&#xff0c;如DDOS攻击、病毒木马破坏等攻击&#xff1b;- 二是利用网页自身的安全漏洞进…

maven的常见问题_Maven常见问题和陷阱

maven的常见问题喜欢它还是讨厌它&#xff08;很多人似乎都讨厌它&#xff09;&#xff0c; Maven是64&#xff05;的Java开发人员广泛使用的工具&#xff08;来源– 2014年Java工具和技术前景 &#xff09;。 大多数经验丰富的开发人员已经对Maven感到头疼。 通常以困难的方式…

matlab graphic,Matlab图形系统,Matlab Graphic System,音标,读音,翻译,英文例句,英语词典...

Image:114994698204558.jpgmatlabmatlab是矩阵实验室(matrix laboratory)之意。除具备卓越的数值计算能力外&#xff0c;它还提供了专业水平的符号计算&#xff0c;文字处理&#xff0c;可视化建模仿真和实时控制等功能。matlab的基本数据单位是矩阵&#xff0c;它的指令表达式…

python调用opengl_Python运行OpenGL示例

说明python的opengl库叫PyOpenGL&#xff0c;安装这个库的时候要注意位数版本要正确&#xff0c;比如我的python37是32位的&#xff0c;安装PyOpenGL-3.1.5-cp37-cp37m-win32.whl才行&#xff0c;默认pip安装的运行时可能会有问题&#xff0c;所以需要手动下载安装对应版本的wh…

php内置的数组函数大全,php数组的内置函数大全

1.array_change_key_case($arr,CASE_UPPER/CASE_LOWER)将$arr的键值转换为大写或者小写2.array_combine($arr1, $arr2) $arr1的值作为键,$arr2作为值生成后返回新的数组3.array_key_exists(‘key’, $arr)$arr中是否存在key&#xff0c;如果存在返回true&#xff0c;如果不存在…

用vs写python和c++需要哪些工具包_从运行效率与开发效率比较Python和C++

之前有人一直在说python怎么怎么好用&#xff0c;也有人说C太难了&#xff0c;下面我做了一些笔记&#xff1a;1、运行效率&#xff1a;C >> PythonPython代码和C最终都会变成CPU指令来跑&#xff0c;但一般情况下&#xff0c;比如反转和合并两个字符串&#xff0c;Pytho…

JUnit5 TestSuite替代

JUnit4具有TestSuite类来聚合多个测试。 这在JUnit 5中不可用。通常&#xff0c;通过套件中的一堆命名测试进行的测试发现有些糟透了。 但是&#xff0c;如果目标不是测试发现&#xff0c;而是不同测试类之间的资源共享&#xff0c;那么创建父对象是有意义的。 JUnit 5提供了N…

oracle 日志丢失,Oracle联机日志文件丢失解决方法一例

由于丢失的当前的联机日志文件&#xff0c;所以可能会丢失部分数据&#xff0c;破坏数据库的完整性&#xff0c;而且普通的重建日志文件的方式是不可行的&#xff0c;这个时候我们需要借助隐含参数_ALLOW_READ_ONLY_CORRUPTION或者_ALLOW_RESETLOGS_CORRUPTION打开数据库。打开…

junit:junit_简而言之,JUnit:测试隔离

junit:junit作为顾问&#xff0c;我仍然经常遇到程序员&#xff0c;他们对JUnit及其正确用法的理解最多。 这使我有了编写多部分教程的想法&#xff0c;以从我的角度解释要点。 尽管存在一些有关使用该工具进行测试的好书和文章&#xff0c;但是也许可以通过本动手实践系列中的…

python基本模块中的对象_Python 学习笔记 -- OS模块的常用对象方法

1 #这里列举在os模块中关于文件/目录常用的函数使用方法23 #这里需要注意下&#xff0c;在使用这些方法前记得导入os模块4 import os #导入os模块5 """6 os对象方法&#xff1a;7 os.getcwd() #返回当前工作目录8 os.chdir(path) #改变工作目录9 os.listdir(pat…

OCA第2部分中的Java难题

欢迎使用OCA的Java Puzzlers的第二部分。 在这一部分中&#xff0c;我们将看到一个有趣的案例&#xff0c;涉及Java 7附带的数字文字中的下划线分隔符。 在下面的类中&#xff0c;您可以在十进制文字中看到分隔符下划线。 还请注意&#xff0c;该类现在可以正常编译。 八进制是…