搜索词>>modbus java 耗时0.0020
  • modbus tcp通讯modbus4j使用说明-java编程

    modbus tcp 通讯协议在Java编程中的使用。本文主要讲解Java编程中通过modbus4j工具类来实现modbus tcp通讯协议的通讯。包括通过modbus协议读取数据,写入数据的实现。<h2>一.什么是modbus</h2>   Modbus是由Modicon(现为施耐德电气公司的一个品牌)在1979年发明的,是全球第一个真正用于工业现场的总线协议。<br /> ModBus网络是一个工业通信系统,由带智能终端的可编程序控制器和计算机通过公用线路或局部专用线路连接而成。其系统结构既包括硬件、亦包括软件。它可应用于各种数据采集和过程监控。<br />   ModBus网络只有一个主机,所有通信都由他发出。网络可支持247个之多的远程从属控制器,但实际所支持的从机数要由所用通信设备决定。采用这个系统,各PC可以和中心主机交换信息而不影响各PC执行本身的控制任务。 <h2>二.Java实现modbus协议通讯</h2> Java编程中,使用modbus4j实现Java中的modbus协议通讯<br /> <br /> modbus4j实现了Java与modbus协议的以下几种通讯方式:<br /> modbus TCP/IP通讯<br /> modubs UDP/IP通讯<br /> modbus RTU/IP通讯<br /> <br /> 核心依赖:<br /> <strong>modbus4j.jar<br /> commons-lang3-3.0.jar<br /> //下载地址代码里有</strong><br /> Java读取工具类 <pre> <code class="language-java">package com.leftso.project.demo.modbus4j; import com.serotonin.modbus4j.BatchRead; import com.serotonin.modbus4j.BatchResults; import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; import com.serotonin.modbus4j.exception.ErrorResponseException; import com.serotonin.modbus4j.exception.ModbusInitException; import com.serotonin.modbus4j.exception.ModbusTransportException; import com.serotonin.modbus4j.ip.IpParameters; import com.serotonin.modbus4j.locator.BaseLocator; /** * modbus通讯工具类,采用modbus4j实现 * * @author lxq * @dependencies modbus4j-3.0.3.jar * @website https://github.com/infiniteautomation/modbus4j */ public class Modbus4jUtils { /** * 工厂。 */ static ModbusFactory modbusFactory; static { if (modbusFactory == null) { modbusFactory = new ModbusFactory(); } } /** * 获取master * * @return * @throws ModbusInitException */ public static ModbusMaster getMaster() throws ModbusInitException { IpParameters params = new IpParameters(); params.setHost("localhost"); params.setPort(502); // // modbusFactory.createRtuMaster(wapper); //RTU 协议 // modbusFactory.createUdpMaster(params);//UDP 协议 // modbusFactory.createAsciiMaster(wrapper);//ASCII 协议 ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 master.init(); return master; } /** * 读取[01 Coil Status 0x]类型 开关数据 * * @param slaveId * slaveId * @param offset * 位置 * @return 读取值 * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Boolean readCoilStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 01 Coil Status BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取[02 Input Status 1x]类型 开关数据 * * @param slaveId * @param offset * @return * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static Boolean readInputStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 02 Input Status BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset); Boolean value = getMaster().getValue(loc); return value; } /** * 读取[03 Holding Register类型 2x]模拟量数据 * * @param slaveId * slave Id * @param offset * 位置 * @param dataType * 数据类型,来自com.serotonin.modbus4j.code.DataType * @return * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Number readHoldingRegister(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 03 Holding Register类型数据读取 BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 读取[04 Input Registers 3x]类型 模拟量数据 * * @param slaveId * slaveId * @param offset * 位置 * @param dataType * 数据类型,来自com.serotonin.modbus4j.code.DataType * @return 返回结果 * @throws ModbusTransportException * 异常 * @throws ErrorResponseException * 异常 * @throws ModbusInitException * 异常 */ public static Number readInputRegisters(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 04 Input Registers类型数据读取 BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType); Number value = getMaster().getValue(loc); return value; } /** * 批量读取使用方法 * * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException { BatchRead<Integer> batch = new BatchRead<Integer>(); batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.FOUR_BYTE_FLOAT)); batch.addLocator(1, BaseLocator.inputStatus(1, 0)); ModbusMaster master = getMaster(); batch.setContiguousRequests(false); BatchResults<Integer> results = master.send(batch); System.out.println(results.getValue(0)); System.out.println(results.getValue(1)); } /** * 测试 * * @param args */ public static void main(String[] args) { try { // 01测试 Boolean v011 = readCoilStatus(1, 0); Boolean v012 = readCoilStatus(1, 1); Boolean v013 = readCoilStatus(1, 6); System.out.println("v011:" + v011); System.out.println("v012:" + v012); System.out.println("v013:" + v013); // 02测试 Boolean v021 = readInputStatus(1, 0); Boolean v022 = readInputStatus(1, 1); Boolean v023 = readInputStatus(1, 2); System.out.println("v021:" + v021); System.out.println("v022:" + v022); System.out.println("v023:" + v023); // 03测试 Number v031 = readHoldingRegister(1, 1, DataType.FOUR_BYTE_FLOAT);// 注意,float Number v032 = readHoldingRegister(1, 3, DataType.FOUR_BYTE_FLOAT);// 同上 System.out.println("v031:" + v031); System.out.println("v032:" + v032); // 04测试 Number v041 = readInputRegisters(1, 1, DataType.FOUR_BYTE_FLOAT);// Number v042 = readInputRegisters(1, 3, DataType.FOUR_BYTE_FLOAT);// System.out.println("v041:" + v041); System.out.println("v042:" + v042); // 批量读取 batchRead(); } catch (Exception e) { e.printStackTrace(); } } }</code></pre> <h2>三、测试</h2> 使用ModbusSlave模拟modbus协议<br /> slave中模拟数据如下<br /> <img alt="modbus slave模拟数据" class="img-thumbnail" src="/resources/assist/images/blog/afe4a730-8fb5-4aa2-9f6b-ff09f4368459.png" style="height:856px; width:825px" /><br /> 运行工具类的main方法: <pre> <code>11:14:54.547 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 00 00 01 11:14:54.550 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.598 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 01 11:14:54.600 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 01 00 01 11:14:54.600 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.650 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 00 11:14:54.652 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 06 00 01 11:14:54.652 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.703 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 01 v011:true v012:false v013:true 11:14:54.704 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 00 00 01 11:14:54.704 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.755 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01 11:14:54.757 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 01 00 01 11:14:54.757 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.807 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 00 11:14:54.810 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 02 00 01 11:14:54.810 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.860 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01 v021:true v022:false v023:true 11:14:54.866 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 03 00 01 00 02 11:14:54.866 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.915 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 03 04 40 20 00 00 11:14:54.917 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 03 00 03 00 02 11:14:54.917 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:54.967 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 03 04 41 28 00 00 v031:2.5 v032:10.5 11:14:54.971 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 04 00 01 00 02 11:14:54.971 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:55.020 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 04 04 3F C0 00 00 11:14:55.021 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 04 00 03 00 02 11:14:55.021 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:55.072 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 04 04 40 40 00 00 v041:1.5 v042:3.0 11:14:55.074 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 00 00 01 11:14:55.074 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:55.123 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01 11:14:55.125 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 01 00 00 00 06 01 03 00 01 00 02 11:14:55.125 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502 11:14:55.179 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 01 00 00 00 07 01 03 04 40 20 00 00 2.5 true </code></pre> <br /> 观察输出结果与 slave上的模拟数据一致 <h2>四、Java通过modbus4j对数据的写入</h2> <strong>Modbus4jWriteUtils.java</strong> <pre> <code class="language-java">package com.leftso.project.demo.modbus4j; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; import com.serotonin.modbus4j.exception.ErrorResponseException; import com.serotonin.modbus4j.exception.ModbusInitException; import com.serotonin.modbus4j.exception.ModbusTransportException; import com.serotonin.modbus4j.ip.IpParameters; import com.serotonin.modbus4j.locator.BaseLocator; import com.serotonin.modbus4j.msg.ModbusResponse; import com.serotonin.modbus4j.msg.WriteCoilRequest; import com.serotonin.modbus4j.msg.WriteCoilResponse; import com.serotonin.modbus4j.msg.WriteCoilsRequest; import com.serotonin.modbus4j.msg.WriteCoilsResponse; import com.serotonin.modbus4j.msg.WriteRegisterRequest; import com.serotonin.modbus4j.msg.WriteRegisterResponse; import com.serotonin.modbus4j.msg.WriteRegistersRequest; /** * modbus4j写入数据 * * @author xq * */ public class Modbus4jWriteUtils { static Log log = LogFactory.getLog(Modbus4jWriteUtils.class); /** * 工厂。 */ static ModbusFactory modbusFactory; static { if (modbusFactory == null) { modbusFactory = new ModbusFactory(); } } /** * 获取tcpMaster * * @return * @throws ModbusInitException */ public static ModbusMaster getMaster() throws ModbusInitException { IpParameters params = new IpParameters(); params.setHost("localhost"); params.setPort(502); ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false); tcpMaster.init(); return tcpMaster; } /** * 写 [01 Coil Status(0x)]写一个 function ID = 5 * * @param slaveId * slave的ID * @param writeOffset * 位置 * @param writeValue * 值 * @return 是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeCoil(int slaveId, int writeOffset, boolean writeValue) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求 WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue); // 发送请求并获取响应对象 WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request); if (response.isException()) { return false; } else { return true; } } /** * 写[01 Coil Status(0x)] 写多个 function ID = 15 * * @param slaveId * slaveId * @param startOffset * 开始位置 * @param bdata * 写入的数据 * @return 是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeCoils(int slaveId, int startOffset, boolean[] bdata) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求 WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata); // 发送请求并获取响应对象 WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request); if (response.isException()) { return false; } else { return true; } } /*** * 写[03 Holding Register(4x)] 写一个 function ID = 6 * * @param slaveId * @param writeOffset * @param writeValue * @return * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeRegister(int slaveId, int writeOffset, short writeValue) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求对象 WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue); WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request); if (response.isException()) { log.error(response.getExceptionMessage()); return false; } else { return true; } } /** * * 写入[03 Holding Register(4x)]写多个 function ID=16 * * @param slaveId * modbus的slaveID * @param startOffset * 起始位置偏移量值 * @param sdata * 写入的数据 * @return 返回是否写入成功 * @throws ModbusTransportException * @throws ModbusInitException */ public static boolean writeRegisters(int slaveId, int startOffset, short[] sdata) throws ModbusTransportException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 创建请求对象 WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata); // 发送请求并获取响应对象 ModbusResponse response = tcpMaster.send(request); if (response.isException()) { log.error(response.getExceptionMessage()); return false; } else { return true; } } /** * 写入数字类型的模拟量(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long) * * @param slaveId * @param offset * @param value * 写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long * @param registerCount * ,com.serotonin.modbus4j.code.DataType * @throws ModbusTransportException * @throws ErrorResponseException * @throws ModbusInitException */ public static void writeHoldingRegister(int slaveId, int offset, Number value, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 获取master ModbusMaster tcpMaster = getMaster(); // 类型 BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType); tcpMaster.setValue(locator, value); } public static void main(String[] args) { try { //@formatter:off // 测试01 // boolean t01 = writeCoil(1, 0, true); // System.out.println("T01:" + t01); // 测试02 // boolean t02 = writeCoils(1, 0, new boolean[] { true, false, true }); // System.out.println("T02:" + t02); // 测试03 // short v = -3; // boolean t03 = writeRegister(1, 0, v); // System.out.println("T03:" + t03); // 测试04 // boolean t04 = writeRegisters(1, 0, new short[] { -3, 3, 9 }); // System.out.println("t04:" + t04); //写模拟量 writeHoldingRegister(1,0, 10.1f, DataType.FOUR_BYTE_FLOAT); //@formatter:on } catch (Exception e) { e.printStackTrace(); } } } </code></pre> <br /> <img alt="浮点类型数据写入" class="img-thumbnail" src="/resources/assist/images/blog/0cee0505f42e44bda68381524f669ba1.png" /><br /> <br /> modbus协议中常见功能代码说明:<br /> <img alt="function ID/code说明" class="img-thumbnail" src="/resources/assist/images/blog/6333daae54c94281b86fba2676238c48.png" /><br />  
  • modbus tcp 通讯modbus-master-tcp Java使用说明

    modbus tcp通讯在之前的博客已经有一种方案。通过modbus4j来实现。本文章主要讲解另外一种方案。通过modbus-master-tcp实现。<h2>引言</h2>     modbus tcp通讯Java的方案之前已经讲解过一种,<a rel="" target="_blank"href="http://www.leftso.com/blog/83.html" rel="" target="_blank">modbus4j实现Java语言的modbus tcp协议通讯</a>。从上一个方案中我们不难发现modbus4j的通讯实现方式是同步的。实际应用中可能会读取大量的数据。同步处理对于应用的响应还是不太友好的。本博客主要讲解另外一种Java语言的modbux tcp通讯方案。那就是modbus-master-tcp。 <h2>一.创建一个demo项目</h2> 创建一个简单的maven项目,项目结构图如下:<br /> <img alt="modbus tcp通讯例子项目结构图" class="img-thumbnail" src="/resources/assist/images/blog/cd159cddb83c4b9191a1b2d126cdd9fc.png" /> <h2>二.pom.xml maven依赖</h2> <pre> <code class="language-xml"><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.leftso.demo.modbus</groupId> <artifactId>demo-modbus-master-slave</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>com.digitalpetri.modbus</groupId> <artifactId>modbus-master-tcp</artifactId> <version>1.1.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project></code></pre> <br /> <strong>pom.xml注意,需要将java的编译版本指定到1.8.因为只有1.8以后才支持lambda表达式。</strong><br /> <br /> 配置完成后,我们观察引入的依赖包:<br /> <img alt="modbus maven依赖" class="img-thumbnail" src="/resources/assist/images/blog/f00bb8ebc3c54c80a3ee512f9849a4c7.png" /><br /> 观察可以发现,modbus-master-tcp项目的底层是基于netty框架开发。天然的支持异步处理。在性能方面有很好的提升。 <h2>三.编写modbus tcp读取案例</h2> <pre> <code class="language-java">package com.leftso.demo.modbus; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import com.digitalpetri.modbus.codec.Modbus; import com.digitalpetri.modbus.master.ModbusTcpMaster; import com.digitalpetri.modbus.master.ModbusTcpMasterConfig; import com.digitalpetri.modbus.requests.ReadCoilsRequest; import com.digitalpetri.modbus.requests.ReadDiscreteInputsRequest; import com.digitalpetri.modbus.requests.ReadHoldingRegistersRequest; import com.digitalpetri.modbus.requests.ReadInputRegistersRequest; import com.digitalpetri.modbus.responses.ReadCoilsResponse; import com.digitalpetri.modbus.responses.ReadDiscreteInputsResponse; import com.digitalpetri.modbus.responses.ReadHoldingRegistersResponse; import com.digitalpetri.modbus.responses.ReadInputRegistersResponse; import io.netty.buffer.ByteBuf; import io.netty.util.ReferenceCountUtil; /*** * modbus TCP协议Java通讯读取例子 * * @author xqlee * */ public class SimpleMasterExample { static ModbusTcpMaster master; /** * 获取TCP协议的Master * * @return */ public static void initModbusTcpMaster() { if (master == null) { // 创建配置 ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost").setPort(502).build(); master = new ModbusTcpMaster(config); } } /*** * 释放资源 */ public static void release() { if (master != null) { master.disconnect(); } Modbus.releaseSharedResources(); } /** * 读取HoldingRegister数据 * * @param address * 寄存器地址 * @param quantity * 寄存器数量 * @param unitId * id * @return 读取结果 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Number readHoldingRegisters(int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Number result = null; CompletableFuture<ReadHoldingRegistersResponse> future = master .sendRequest(new ReadHoldingRegistersRequest(address, quantity), unitId); ReadHoldingRegistersResponse readHoldingRegistersResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readHoldingRegistersResponse != null) { ByteBuf buf = readHoldingRegistersResponse.getRegisters(); result = buf.readFloat(); ReferenceCountUtil.release(readHoldingRegistersResponse); } return result; } /** * 读取InputRegisters模拟量数据 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Number readInputRegisters(int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Number result = null; CompletableFuture<ReadInputRegistersResponse> future = master .sendRequest(new ReadInputRegistersRequest(address, quantity), unitId); ReadInputRegistersResponse readInputRegistersResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readInputRegistersResponse != null) { ByteBuf buf = readInputRegistersResponse.getRegisters(); result = buf.readFloat(); ReferenceCountUtil.release(readInputRegistersResponse); } return result; } /** * 读取Coils开关量 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Boolean readCoils(int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Boolean result = null; CompletableFuture<ReadCoilsResponse> future = master.sendRequest(new ReadCoilsRequest(address, quantity), unitId); ReadCoilsResponse readCoilsResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (readCoilsResponse != null) { ByteBuf buf = readCoilsResponse.getCoilStatus(); result = buf.readBoolean(); ReferenceCountUtil.release(readCoilsResponse); } return result; } /** * 读取readDiscreteInputs开关量 * * @param address * 寄存器开始地址 * @param quantity * 数量 * @param unitId * ID * @return 读取值 * @throws InterruptedException * 异常 * @throws ExecutionException * 异常 */ public static Boolean readDiscreteInputs(int address, int quantity, int unitId) throws InterruptedException, ExecutionException { Boolean result = null; CompletableFuture<ReadDiscreteInputsResponse> future = master .sendRequest(new ReadDiscreteInputsRequest(address, quantity), unitId); ReadDiscreteInputsResponse discreteInputsResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理 if (discreteInputsResponse != null) { ByteBuf buf = discreteInputsResponse.getInputStatus(); result = buf.readBoolean(); ReferenceCountUtil.release(discreteInputsResponse); } return result; } public static void main(String[] args) { try { // 初始化资源 initModbusTcpMaster(); // 执行操作 // 读取模拟量 System.out.println(readHoldingRegisters(0, 4, 1)); System.out.println(readInputRegisters(0, 4, 1)); // 读取开关量 System.out.println(readCoils(0, 1, 1)); System.out.println(readDiscreteInputs(0, 1, 1)); System.out.println(readDiscreteInputs(2, 1, 1)); // 释放资源 release(); } catch (Exception e) { e.printStackTrace(); } } } </code></pre> 上面的代码中模拟量的读取需要注意,根据实际类型来读取相应的类型,例子中读取的double类型数据 <h2>四.运行上面的案例演示modbus tcp数据读取</h2> 首先打开软件Modbus Slave(没有的可以百度下载)。启动连接:<br /> <img alt="连接到slave" class="img-thumbnail" src="/resources/assist/images/blog/6f9cb23d6ab04284bc2d1c08b328c37e.png" /><br /> 连接完成后,创建四个文档如下图所示:<br /> <img alt="modbus 数据文档" class="img-thumbnail" src="/resources/assist/images/blog/104a6b808dc2451bbd2bfe042d2005d4.png" /><br /> <br /> 好了,现在运行我们刚才编写的Java demo程序,SimpleMasterExample:<br /> <br /> <img alt="执行结果" class="img-thumbnail" src="/resources/assist/images/blog/31a4549943574c5aa3d5d1d3a20b955a.png" /><br /> 通过执行结果可以看到与Modbus Slave软件中的文档数据一致。<br />   <h2> </h2>
  • spring boot FastDFS Java client使用-Java编程

    Java编程之spring boot FastDFS Java client使用,Java编程,FastDFS Java客户端<h2>一、获取FastDFS Java的客户端链接工具</h2> 由于maven库中并没有编译好的jar工具包,目前只能通过GitHub下载源码自己打包成jar<br /> 下载地址:<a href="https://github.com/happyfish100/fastdfs-client-java" rel="external nofollow" target="_blank">点击去下去</a><br /> <br /> 如果通过浏览器直接下载,则下载后是一个zip压缩包。<br /> 1.解压zip包<br /> 2.eclipse通过已存在的maven项目方式导入<br /> 3.执行maven install命令打包<br /> <br /> 打包完成后再target目录下有打包好的jar文件:<br /> <strong>fastdfs-client-java-1.27-SNAPSHOT.jar</strong><br />   <h2>二、导入spring boot项目</h2> 创建一个spring boot项目,在创建好的项目中创建一个lib的文件夹,将上面打包的jar文件复制进去。然后打开spring boot项目的pom.xml文件,添加本地依赖如下: <pre> <code class="language-xml"> <!-- fastfds 客户端 |https://github.com/happyfish100/fastdfs-client-java --> <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.27-SNAPSHOT</version> <scope>system</scope> <systemPath>${project.basedir}/lib/fastdfs-client-java-1.27-SNAPSHOT.jar</systemPath> </dependency></code></pre> <h2>三、配置文件</h2> 在spring boot项目的resource目录下创建一个fdfs_client.conf文件,内容如下: <pre> <code>#注1:tracker_server指向您自己IP地址和端口,1-n个 #注2:除了tracker_server,其它配置项都是可选的 #注3:.conf 配置文件文件所在位置可以是项目classpath(或OS文件系统目录比如/opt/): #注4:.conf 配置文件优先按OS文件系统路径读取,没有找到才查找项目classpath,尤其针对linux环境下的相对路径 #注5:其他相关参考:https://github.com/happyfish100/fastdfs-client-java connect_timeout = 120 network_timeout = 130 charset = UTF-8 http.tracker_http_port = 80 http.anti_steal_token = no http.secret_key = FastDFS1234567890 tracker_server = 192.168.8.202:22122</code></pre> 其中里面的tracker_server 以及端口均需要根据自身使用的实际请来修改 <h2><br /> 四、编写一个公用的Java 的fastdfs客户端</h2> 首先需要创建一个FastDFS的文件辅助类:<br /> <strong>FastDSFile.java</strong> <pre> <code class="language-java">public class FastDSFile { private String name; private byte[] content; private String ext; private String md5; public String getName() { return name; } public void setName(String name) { this.name = name; } public byte[] getContent() { return content; } public void setContent(byte[] content) { this.content = content; } public String getExt() { return ext; } public void setExt(String ext) { this.ext = ext; } public String getMd5() { return md5; } public void setMd5(String md5) { this.md5 = md5; } } </code></pre> <br /> <strong>FastDFSClient.java</strong> <pre> <code class="language-java">import java.io.File; import java.io.IOException; import org.csource.common.MyException; import org.csource.fastdfs.ClientGlobal; import org.csource.fastdfs.StorageClient1; import org.csource.fastdfs.StorageServer; import org.csource.fastdfs.TrackerClient; import org.csource.fastdfs.TrackerServer; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import com.alibaba.fastjson.JSONArray; /** * fastDFS文件服务Java客户端实现,所有执行方法均为静态方法。 * * @author xq * */ public class FastDFSClient { /** * 客户端 */ private static StorageClient1 storageClient1 = null; // 初始化客户端,加载类时候执行片段 static { try { Resource resource = new ClassPathResource("fdfs_client.conf"); File file = resource.getFile(); String configFile = file.getAbsolutePath(); ClientGlobal.init(configFile); // TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group); // TrackerServer trackerServer = trackerClient.getConnection(); // StorageServer storageServer = trackerClient.getStoreStorage(trackerServer); // storageClient1 = new StorageClient1(trackerServer, storageServer); System.out.println("FastDFS Client Init Success!"); } catch (Exception e) { e.printStackTrace(); System.out.println("FastDFS Client Init Fail!"); } } /*** * 文件上传 * * @param fastDSFile * @return * @throws IOException * @throws MyException */ public static JSONArray upload(FastDSFile fastDSFile) throws IOException, MyException { String[] uploadResult = storageClient1.upload_file(fastDSFile.getContent(), fastDSFile.getExt(), null); // String arr = JSONArray.toJSONString(uploadResult); JSONArray arr = (JSONArray) JSONArray.toJSON(uploadResult); return arr; } /** * 文件下载 * * @param groupName * @param remoteFileName * @return * @throws IOException * @throws MyException */ public static byte[] download(String groupName, String remoteFileName) throws IOException, MyException { return storageClient1.download_file(groupName, remoteFileName); } /** * 文件删除 * * @param groupName * @param remoteFileName * @throws Exception * @return 返回0成功;非0失败. */ public static int delete(String groupName, String remoteFileName) throws Exception { return storageClient1.delete_file(groupName, remoteFileName); } } </code></pre> <h2>五、编写测试</h2> <strong>DemoSpringbootFastdfsApplicationTests.java</strong> <pre> <code class="language-java">import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.alibaba.fastjson.JSONArray; import net.xqlee.project.demo.fastdfs.clients.FastDFSClient; import net.xqlee.project.demo.fastdfs.clients.FastDSFile; @RunWith(SpringRunner.class) @SpringBootTest public class DemoSpringbootFastdfsApplicationTests { @Test public void contextLoads() { try { FileInputStream fis = new FileInputStream(new File("C:/Users/xq/Pictures/tx.jpg")); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] cache = new byte[4096]; while (fis.read(cache) != -1) { bos.write(cache); } fis.close(); FastDSFile fastDSFile = new FastDSFile(); fastDSFile.setContent(bos.toByteArray()); fastDSFile.setExt("jpg"); // -------上传---- JSONArray rs = FastDFSClient.upload(fastDSFile); System.out.println("上传结束:" + rs); // -------下载---- byte[] dfile = FastDFSClient.download(rs.getString(0), rs.getString(1)); FileOutputStream fos = new FileOutputStream(new File("C:/Users/xq/Pictures/tx-fdfs.jpg")); fos.write(dfile); fos.flush(); fos.close(); // -------删除----- int ds=FastDFSClient.delete(rs.getString(0), rs.getString(1)); // System.out.println("Delete:"+ds); System.out.println("---End----"); } catch (Exception e) { e.printStackTrace(); } } } </code></pre> <br /> 运行测试,可以看到在上传图片的目录下多了一个名为tx-fdfs.jpg的文件
  • Java编程之java static关键字

    Java编程之java static关键字,Java编程,static关键字<h2>一、java中static关键字</h2> java中的static关键字可以应用于变量、方法、块、导入和内部类。在本教程中,我们将了解在这些地方使用static关键字的效果。<br /> <br /> 本文将要讲解的内容目录: <ul> <li>Static 变量的使用讲解</li> <li>Static 方法的使用讲解</li> <li>Static 导入声明使用讲解</li> <li>Static 块的使用讲解</li> <li>Static 类的使用讲解</li> <li>static关键字使用总结</li> </ul> <h2>二、static变量</h2> 要声明一个static变量,请在变量声明中使用static关键字。static变量的语法是: <pre> <code>ACCESS_MODIFER static DATA_TYPE VARNAME;</code></pre> 例如,用这种方式声明整数类型的公共静态变量。 <pre> <code class="language-java">public static Integer staticVar;</code></pre> 静态变量最重要的一点是它们属于类级别。这意味着在运行时只能有一个变量的副本。当在类定义中定义静态变量时,类的每个实例都可以访问该单一副本。单独的类实例不会有它们自己的本地副本,就像它们对非静态变量一样。<br /> <br /> 让我们来了解一个例子: <pre> <code class="language-java">public class JavaStaticExample { public static void main(String[] args) { DataObject objOne = new DataObject(); objOne.staticVar = 10; objOne.nonStaticVar = 20; DataObject objTwo = new DataObject(); System.out.println(objTwo.staticVar); //10 System.out.println(objTwo.nonStaticVar); //null DataObject.staticVar = 30; //Direct Access System.out.println(objOne.staticVar); //30 System.out.println(objTwo.staticVar); //30 } } class DataObject { public static Integer staticVar; public Integer nonStaticVar; }</code></pre> <br /> 输出内容: <pre> <code>10 null 30 30</code></pre> 注意我们如何将值更改为30,并且这两个对象现在看到的更新值为30。<br /> <br /> 另一件您应该注意到的是,我们如何能够使用它的类名来访问静态变量,即dataobject . staticvar。我们不需要创建任何实例来访问静态变量。它清楚地表明静态变量属于类范围。 <h2>三、static方法</h2> 要声明静态方法,请在方法声明中使用静态关键字。静态方法的语法是: <pre> <code>ACCESS_MODIFER static RETURN_TYPE METHOD_NAME;</code></pre> <br /> 例如,用这种方式声明整数类型的公共静态变量。 <pre> <code class="language-java">public static Integer getStaticVar(){ return staticVar; }</code></pre> <p>要记住的一些事项。</p> <ol> <li>您只能在静态方法中访问静态变量。如果您尝试访问任何非静态变量,将生成的编译器错误信息“无法对非静态字段非静态变量进行静态引用”。</li> <li>静态方法可以通过它的类引用来访问,并且不需要创建类的实例。虽然您也可以使用实例引用,但是与通过类引用的访问相比,它不会有任何不同。</li> <li>静态方法也属于类级范围。</li> </ol>   <pre> <code class="language-java">public class JavaStaticExample { public static void main(String[] args) { DataObject.staticVar = 30; //Direct Access Integer value1 = DataObject.getStaticVar(); //access with class reference DataObject objOne = new DataObject(); Integer value2 = objOne.getStaticVar(); //access with instance reference System.out.println(value1); System.out.println(value2); } } class DataObject { public Integer nonStaticVar; public static Integer staticVar; //static variable public static Integer getStaticVar(){ return staticVar; } }</code></pre> 输出内容: <pre> <code>30 30</code></pre> <h2>四、static Import 声明</h2> <p>    正常的导入声明从包中导入类,因此它们可以在没有包引用的情况下使用。类似地,静态导入声明从类中导入静态成员,并允许它们在没有类引用的情况下使用。</p> <p>    静态导入声明也有两种类型:单静态导入和静态导入。单静态导入声明从类型中导入一个静态成员。静态输入-点播声明导入了类型的所有静态成员。<br />  </p> <pre> <code class="language-java">//Single-static-import declaration: import static <<package name>>.<<type name>>.<<static member name>>; //Static-import-on-demand declaration: import static <<package name>>.<<type name>>.*;</code></pre> 例如, <code>System.out</code> is <pre> <code class="language-java">//Static import statement import static java.lang.System.out; public class JavaStaticExample { public static void main(String[] args) { DataObject.staticVar = 30; out.println(DataObject.staticVar); //Static import statement example } } class DataObject { public static Integer staticVar; //static variable }</code></pre> 输出: <pre> <code>30</code></pre> <h2>五、Static 块</h2> 静态块是类初始化代码的一部分,它用静态关键字包装。一般的语法是: <pre> <code class="language-java">static { //initialize static members of class }</code></pre> 当类装入内存时,将执行静态块。一个类可以有多个静态块,并且它们将以相同的顺序执行,它们在类定义中出现。 <pre> <code class="language-java">import static java.lang.System.out; class DataObject { public Integer nonStaticVar; public static Integer staticVar; //static variable //It will be executed first static { staticVar = 40; //nonStaticVar = 20; //Not possible to access non-static members } //It will be executed second static { out.println(staticVar); } }</code></pre> 输出: <pre> <code>40</code></pre> <h2>六、static 类</h2> 在java中,可以将静态类作为内部类。与其他静态成员一样,嵌套的类属于类范围,所以可以访问内部的静态类,而不具有外部类的对象。 <pre> <code class="language-java">public class JavaStaticExample { public static void main(String[] args) { //Static inner class example System.out.println( DataObject.StaticInnerClas.innerStaticVar ); } } class DataObject { public Integer nonStaticVar; public static Integer staticVar; //static variable static class StaticInnerClas { Integer innerNonStaticVar = 60; static Integer innerStaticVar = 70; //static variable inside inner class } }</code></pre> 请注意,静态内部类无法访问外部类的非静态成员。它只能访问来自外部类的静态成员。 <pre> <code class="language-java">public class JavaStaticExample { public static void main(String[] args) { //Static inner class example DataObject.StaticInnerClas.accessOuterClass(); } } class DataObject { public Integer nonStaticVar; public static Integer staticVar; //static variable static { staticVar = 40; //nonStaticVar = 20; //Not possible to access non-static members } public static Integer getStaticVar(){ return staticVar; } static class StaticInnerClas { public static void accessOuterClass() { System.out.println(DataObject.staticVar); //static variable of outer class System.out.println(DataObject.getStaticVar()); //static method of outer class } } }</code></pre> 输出: <pre> <code>40</code></pre> <h2>七、总结</h2> 让我们总结一下java中静态使用的所有内容。 <ol> <li>静态成员属于类。不需要创建类实例来访问静态成员。</li> <li>静态成员(变量和方法)只能在静态方法和静态块中访问。</li> <li>不能在静态方法、块和内部类中访问非静态成员。</li> <li>一个类可以有多个静态块,它们将按照类定义的顺序执行。</li> <li>只有当类声明为内部类内部类时,类才能是静态的。</li> <li>静态导入可用于从类导入所有的静态成员。这些成员可以被引用,没有任何类引用。</li> </ol>
  • java编程之java jwt token使用autho0-jwt框架使用(二)

    java编程之java jwt token使用,autho0的Java-jwt框架使用,java编程,java-jwt<h2>一、前言</h2> Java编程中使用jwt,首先你必须了解jwt是什么,长什么样子。如果你不了解可以先去本站另外一篇博客<a href="http://www.leftso.com/blog/220.html" rel="" target="_blank" >什么是JWT?</a><br />   <h2>二、Java编程中jwt框架选择</h2> 在Java编程中,实现jwt标准的有很多框架,本博客采用的框架是auth0的java-jwt版本为3.2.0 <h2>三、什么是Java-JWT</h2> auth0的java-jwt是一个JSON WEB TOKEN(JWT)的一个实现。 <h2>四、安装下载相关依赖</h2> 如果你是采用<strong>maven</strong>的方式,在你的项目pom.xml文件中添加以下java-jwt的依赖片段: <pre> <code class="language-xml"><dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.2.0</version> </dependency></code></pre> 如果你是采用<strong>Gradle</strong>的方式,则添加以下内容: <pre> <code>compile 'com.auth0:java-jwt:3.2.0'</code></pre> <h2>五、java-jwt已经实现的算法</h2> 该库使用以下算法实现JWT验证和签名: <table class="table table-bordered table-hover" > <thead> <tr> <th>JWS</th> <th>算法</th> <th>介绍</th> </tr> </thead> <tbody> <tr> <td>HS256</td> <td>HMAC256</td> <td>HMAC with SHA-256</td> </tr> <tr> <td>HS384</td> <td>HMAC384</td> <td>HMAC with SHA-384</td> </tr> <tr> <td>HS512</td> <td>HMAC512</td> <td>HMAC with SHA-512</td> </tr> <tr> <td>RS256</td> <td>RSA256</td> <td>RSASSA-PKCS1-v1_5 with SHA-256</td> </tr> <tr> <td>RS384</td> <td>RSA384</td> <td>RSASSA-PKCS1-v1_5 with SHA-384</td> </tr> <tr> <td>RS512</td> <td>RSA512</td> <td>RSASSA-PKCS1-v1_5 with SHA-512</td> </tr> <tr> <td>ES256</td> <td>ECDSA256</td> <td>ECDSA with curve P-256 and SHA-256</td> </tr> <tr> <td>ES384</td> <td>ECDSA384</td> <td>ECDSA with curve P-384 and SHA-384</td> </tr> <tr> <td>ES512</td> <td>ECDSA512</td> <td>ECDSA with curve P-521 and SHA-512</td> </tr> </tbody> </table> <h2>六、如何使用java-jwt</h2> <strong>6.1.选择一种算法</strong> <p>  算法定义了一个令牌是如何被签名和验证的。它可以用HMAC算法的原始值来实例化,也可以在RSA和ECDSA算法的情况下对密钥对或密钥提供程序进行实例化。创建后,该实例可用于令牌签名和验证操作。</p> <p>在使用RSA或ECDSA算法时,只需要签署JWTs,就可以通过传递null值来避免指定公钥。当您需要验证JWTs时,也可以使用私钥进行操作<br /> <br /> 使用静态的字符密文或者key来获取算法器:<br />  </p> <pre> <code class="language-java">//HMAC Algorithm algorithmHS = Algorithm.HMAC256("secret"); //RSA RSAPublicKey publicKey = //Get the key instance RSAPrivateKey privateKey = //Get the key instance Algorithm algorithmRS = Algorithm.RSA256(publicKey, privateKey);</code></pre> 使用一个key提供者来获取算法:<br />   通过使用KeyProvider,您可以在运行时更改密钥,用于验证令牌签名或为RSA或ECDSA算法签署一个新的令牌。这是通过实现RSAKeyProvider或ECDSAKeyProvider方法实现的: <ul> <li><code>getPublicKeyById(String kid)</code>: 它在令牌签名验证中调用,它应该返回用于验证令牌的密钥。如果使用了关键的轮换,例如JWK,它可以使用id来获取正确的轮换键(或者只是一直返回相同的键)。</li> <li><code>getPrivateKey()</code>: 在令牌签名期间调用它,它应该返回用于签署JWT的密钥。</li> <li><code>getPrivateKeyId()</code>:在令牌签名期间调用它,它应该返回标识由getPrivateKey()返回的键的id的id。这个值比JWTCreator.Builder和keyid(String)方法中的值更受欢迎。如果您不需要设置孩子的值,就避免使用KeyProvider实例化算法。</li> </ul> 下面的代码片段将展示如何使用: <pre> <code class="language-java">final JwkStore jwkStore = new JwkStore("{JWKS_FILE_HOST}"); final RSAPrivateKey privateKey = //Get the key instance final String privateKeyId = //Create an Id for the above key RSAKeyProvider keyProvider = new RSAKeyProvider() { @Override public RSAPublicKey getPublicKeyById(String kid) { //Received 'kid' value might be null if it wasn't defined in the Token's header RSAPublicKey publicKey = jwkStore.get(kid); return (RSAPublicKey) publicKey; } @Override public RSAPrivateKey getPrivateKey() { return privateKey; } @Override public String getPrivateKeyId() { return privateKeyId; } }; Algorithm algorithm = Algorithm.RSA256(keyProvider); //Use the Algorithm to create and verify JWTs.</code></pre> <br /> <em>提示:对于使用JWKs的简单的键轮换,可以尝试JWKs-rsa-java库。</em><br /> <br /> <strong>6.2.创建一个签名的JWT token</strong><br /> 首先需要通过调用<code>jwt.create()</code>创建一个<code>JWTCreator</code>实例 <ul> <li>例如使用 <code>HS256算法:</code></li> </ul> <pre> <code class="language-java">try { Algorithm algorithm = Algorithm.HMAC256("secret"); String token = JWT.create() .withIssuer("auth0") .sign(algorithm); } catch (UnsupportedEncodingException exception){ //UTF-8 encoding not supported } catch (JWTCreationException exception){ //Invalid Signing configuration / Couldn't convert Claims. }</code></pre> <ul> <li>例如使用<code>RS256算法:</code></li> </ul> <pre> <code class="language-java">RSAPublicKey publicKey = //Get the key instance RSAPrivateKey privateKey = //Get the key instance try { Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey); String token = JWT.create() .withIssuer("auth0") .sign(algorithm); } catch (JWTCreationException exception){ //Invalid Signing configuration / Couldn't convert Claims. }</code></pre> 如果Claim不能转换为JSON,或者在签名过程中使用的密钥无效,那么将会抛出<code>JWTCreationException</code>异常。<br /> <br /> <strong>6.3.验证令牌</strong><br />   首先需要通过调用jwt.require()和传递算法实例来创建一个JWTVerifier实例。如果您要求令牌具有特定的Claim值,请使用构建器来定义它们。方法build()返回的实例是可重用的,因此您可以定义一次,并使用它来验证不同的标记。最后调用verifier.verify()来验证token <ul> <li>例如使用 <code>HS256算法的时候:</code></li> </ul> <pre> <code class="language-java">String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; try { Algorithm algorithm = Algorithm.HMAC256("secret"); JWTVerifier verifier = JWT.require(algorithm) .withIssuer("auth0") .build(); //Reusable verifier instance DecodedJWT jwt = verifier.verify(token); } catch (UnsupportedEncodingException exception){ //UTF-8 encoding not supported } catch (JWTVerificationException exception){ //Invalid signature/claims }</code></pre> <ul> <li>例如使用 <code>RS256算法的时候:</code></li> </ul> <pre> <code class="language-java">String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; RSAPublicKey publicKey = //Get the key instance RSAPrivateKey privateKey = //Get the key instance try { Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey); JWTVerifier verifier = JWT.require(algorithm) .withIssuer("auth0") .build(); //Reusable verifier instance DecodedJWT jwt = verifier.verify(token); } catch (JWTVerificationException exception){ //Invalid signature/claims }</code></pre> 如果令牌有一个无效的签名,或者没有满足Claim要求,那么将会抛出JWTVerificationException异常<br /> <br /> <strong>6.4.jwt时间的验证</strong><br /> JWT令牌可能包括可用于验证的DateNumber字段: <ul> <li>这个令牌发布了一个过期的时间 <code>"iat" < TODAY</code></li> <li>这个令牌还没过期 <code>"exp" > TODAY</code> and</li> <li>这个令牌已经被使用了. <code>"nbf" > TODAY</code></li> </ul> 当验证一个令牌时,时间验证会自动发生,导致在值无效时抛出一个JWTVerificationException。如果前面的任何一个字段都丢失了,那么在这个验证中就不会考虑这些字段。<br /> 要指定令牌仍然被认为有效的余地窗口,在JWTVerifier builder中使用accept回旋()方法,并传递一个正值的秒值。这适用于上面列出的每一项。 <pre> <code class="language-java">JWTVerifier verifier = JWT.require(algorithm) .acceptLeeway(1) // 1 sec for nbf, iat and exp .build();</code></pre> 您还可以为给定的日期声明指定一个自定义值,并为该声明覆盖缺省值。 <pre> <code class="language-java">JWTVerifier verifier = JWT.require(algorithm) .acceptLeeway(1) //1 sec for nbf and iat .acceptExpiresAt(5) //5 secs for exp .build();</code></pre> 如果您需要在您的lib/app中测试此行为,将验证实例转换为basever可视化,以获得verific.build()方法的可见性,该方法可以接受定制的时钟。例如: <pre> <code class="language-java">BaseVerification verification = (BaseVerification) JWT.require(algorithm) .acceptLeeway(1) .acceptExpiresAt(5); Clock clock = new CustomClock(); //Must implement Clock interface JWTVerifier verifier = verification.build(clock);</code></pre> <br /> <strong>6.5解码一个jwt令牌</strong> <pre> <code class="language-java">String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; try { DecodedJWT jwt = JWT.decode(token); } catch (JWTDecodeException exception){ //Invalid token }</code></pre> 如果令牌有无效的语法,或者消息头或有效负载不是JSONs,那么将会抛出JWTDecodeException异常。<br /> <br /> <strong>6.6JWT头部解析</strong> <h4><br /> Algorithm ("alg")</h4> 返回jwt的算法值或,如果没有定义则返回null <pre> <code class="language-java">String algorithm = jwt.getAlgorithm();</code></pre> <p> </p> <p>Type ("typ")</p> <p>返回jwt的类型值,如果没有定义则返回null(多数情况类型值为jwt)</p> <pre> <code class="language-java">String type = jwt.getType();</code></pre> <p> </p> <p>Content Type ("cty")</p> <p>返回内容的类型,如果没有定义则返回null</p> <pre> <code class="language-java">String contentType = jwt.getContentType();</code></pre> <p><br /> Key Id ("kid")<br /> 返回key的id值,如果没有定义则返回null<br />  </p> <pre> <code class="language-java">String keyId = jwt.getKeyId();</code></pre> <h4>私有的Claims,即自定义字段</h4> 在令牌的头部中定义的附加声明可以通过调用getHeaderClaim() 获取,即使无法找到,也会返回。您可以通过调用claim.isNull()来检查声明的值是否为null。 <pre> <code class="language-java">Claim claim = jwt.getHeaderClaim("owner");</code></pre> 当使用jwt.create()创建一个令牌时,您可以通过调用withHeader()来指定头声明,并同时传递声明的映射。 <pre> <code class="language-java">Map<String, Object> headerClaims = new HashMap(); headerClaims.put("owner", "auth0"); String token = JWT.create() .withHeader(headerClaims) .sign(algorithm); </code></pre> <em>提示:在签名过程之后,alg和typ值将始终包含在Header中。</em><br /> <br /> <strong>6.7JWT的负载(Payload)声明</strong> <h4>Issuer ("iss")</h4> 返回签发者的名称值,如果没有在负载中定义则返回null <pre> <code class="language-java">String issuer = jwt.getIssuer();</code></pre> <h4>Subject ("sub")</h4> 返回jwt所面向的用户的值,如果没有在负载中定义则返回null <pre> <code class="language-java">String subject = jwt.getSubject();</code></pre> <h4>Audience ("aud")</h4> 返回该jwt由谁接收,如果没有在负载中定义则返回null <pre> <code class="language-java">List<String> audience = jwt.getAudience();</code></pre> <h4>Expiration Time ("exp")</h4> 返回该jwt的过期时间,如果在负载中没有定义则返回null <pre> <code class="language-java">Date expiresAt = jwt.getExpiresAt();</code></pre> <h4>Not Before ("nbf")</h4> Returns the Not Before value or null if it's not defined in the Payload. <pre> <code class="language-java">Date notBefore = jwt.getNotBefore();</code></pre> <h4>Issued At ("iat")</h4> 返回在什么时候签发的,如果在负载中没有定义则返回null <pre> <code class="language-java">Date issuedAt = jwt.getIssuedAt();</code></pre> <h4>JWT ID ("jti")</h4> 返回该jwt的唯一标志,如果在负载中没有定义则返回null <pre> <code class="language-java">String id = jwt.getId();</code></pre> <strong>自定义声明</strong><br /> 在令牌有效负载中定义的附加声明可以通过调用getClaims()或 getClaim()和传递声明名来获得。即使无法找到声明,也将会有返回值。您可以通过调用claim.isNull()来检查声明的值是否为null。 <pre> <code class="language-java">Map<String, Claim> claims = jwt.getClaims(); //Key is the Claim name Claim claim = claims.get("isAdmin");</code></pre> 或者: <pre> <code class="language-java">Claim claim = jwt.getClaim("isAdmin");</code></pre> 当使用jwt.create()创建一个令牌时,您可以通过调用withClaim()来指定自定义声明,并同时传递名称和值。 <pre> <code class="language-java">String token = JWT.create() .withClaim("name", 123) .withArrayClaim("array", new Integer[]{1, 2, 3}) .sign(algorithm);</code></pre> 您还可以通过调用withClaim()来验证jwt.require()的自定义声明,并传递该名称和所需的值。 <pre> <code class="language-java">JWTVerifier verifier = JWT.require(algorithm) .withClaim("name", 123) .withArrayClaim("array", 1, 2, 3) .build(); DecodedJWT jwt = verifier.verify("my.jwt.token");</code></pre> <em>提示:当前支持的自定义JWT声明创建和验证的类型是:Boolean, Integer, Double, String, Date 和Arrays。</em><br /> <br /> <strong>6.8Claim Class</strong><br /> 索赔类是索赔值的包装器。它允许您将索赔作为不同的类类型。可用的工具方法:<br /> 原始的: <ul> <li><strong>asBoolean()</strong>: 返回布尔值,如果不能转换返回null。</li> <li><strong>asInt()</strong>: 返回整数值,如果不能转换返回null。</li> <li><strong>asDouble()</strong>: 返回 Double 值,如果不能转换则返回null。</li> <li><strong>asLong()</strong>: 返回Long 值,如果不能转换则返回null。</li> <li><strong>asString()</strong>: 返回String值,如果不能转换则返回null。</li> <li><strong>asDate()</strong>: 返回 Date值,如果不能转换则返回null。 必须是一个数字日期 (Unix 系统时间戳). 注意,JWT标准指定所有的数字日期值必须以秒为单位。</li> </ul> <h4>自定义类型和集合:</h4> 要获得作为集合的声明,您需要提供要转换的内容的类类型 <ul> <li>as(class): 返回 Class Type 的解析值. 对于集合,您应该使用asArray和asList方法。</li> <li>asMap(): 返回被转换为 Map<String, Object>的值</li> <li>asArray(class): 返回被转换成元素类型的 Class Type, or null if the value isn't a JSON Array.</li> <li>asList(class): 返回集合元素的 Class Type, or null if the value isn't a JSON Array.</li> </ul> <em>如果不能将值转换为给定的类类型,则会抛出JWTDecodeException异常</em><br /> <br /> <em>翻译的不标准的后续更近,欢迎提供宝贵意见或者翻译,联系leftso@qq.com</em>
  • java编程基础数组ArrayList使用详解

    java编程基础数组ArrayList使用详解<p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">Java编程基础中的ArrayList用于存储动态大小的元素集合。与大小固定的数组相反,ArrayList会在添加新元素时自动增大其大小。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">ArrayList是Java集合框架的一部分,它实现了Java的<code>List</code>接口。<img alt="list" class="img-thumbnail" src="/resources/assist/images/blog/3a58de20c693483dba6ea4d6a42b7e2a.jpg" /></span></span></span><br /> <br />  </p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">以下几点需要注意Java中的ArrayList -</span></span></span></p> <ul style="margin-left:30px; margin-right:0px"> <li> <p style="margin-left:0px; margin-right:0px">ArrayList是一个可调整大小的数组,也称为动态数组。它的尺寸越来越大,以适应新的元素,并在元素被移除时缩小尺寸。</p> </li> <li> <p style="margin-left:0px; margin-right:0px">ArrayList内部使用数组来存储元素。就像数组一样,它允许您通过索引来检索元素。</p> </li> <li> <p style="margin-left:0px; margin-right:0px">Java ArrayList允许重复值和空值。</p> </li> <li> <p style="margin-left:0px; margin-right:0px">Java ArrayList是一个有序的集合。它维护元素的插入顺序。</p> </li> <li> <p style="margin-left:0px; margin-right:0px">您不能创建原始类型,如一个ArrayList <code>int</code>,<code>chat</code>等你需要用盒装的类型,如<code>Integer</code>,<code>Character</code>,<code>Boolean</code>等。</p> </li> <li> <p style="margin-left:0px; margin-right:0px">Java ArrayList不同步。如果多个线程同时尝试修改ArrayList,那么最终结果将是非确定性的。如果多个线程要修改它,你必须显式同步对ArrayList的访问。</p> </li> </ul> <h2 style="margin-left:0px; margin-right:0px; text-align:start">创建一个ArrayList并添加新的元素</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">这个例子显示:</span></span></span></p> <ul style="margin-left:30px; margin-right:0px"> <li>如何使用<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#ArrayList--" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>ArrayList()</code></a>构造函数创建ArrayList 。</li> <li>使用该<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#add-E-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>add()</code></a>方法向ArrayList添加新元素。</li> </ul> <pre> <code class="language-java">import java.util.ArrayList; import java.util.List; public class CreateArrayListExample { public static void main(String[] args) { // Creating an ArrayList of String List<String> animals = new ArrayList<>(); // Adding new elements to the ArrayList animals.add("Lion"); animals.add("Tiger"); animals.add("Cat"); animals.add("Dog"); System.out.println(animals); // Adding an element at a particular index in an ArrayList animals.add(2, "Elephant"); System.out.println(animals); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><br /> <span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出</span></span></span></p> <pre> <code class="language-html">[Lion, Tiger, Cat, Dog] [Lion, Tiger, Elephant, Cat, Dog]</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">从另一个集合创建一个ArrayList</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">这个例子显示:</span></span></span></p> <ul style="margin-left:30px; margin-right:0px"> <li> <p style="margin-left:0px; margin-right:0px">如何使用<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#ArrayList-java.util.Collection-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>ArrayList(Collection c)</code></a>构造函数从另一个ArrayList创建一个ArrayList 。</p> </li> <li> <p style="margin-left:0px; margin-right:0px">如何使用该<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#addAll-java.util.Collection-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>addAll()</code></a>方法将现有ArrayList中的所有元素添加到新的ArrayList中。</p> <pre> <code class="language-java">import java.util.ArrayList; import java.util.List; public class CreateArrayListFromCollectionExample { public static void main(String[] args) { List<Integer> firstFivePrimeNumbers = new ArrayList<>(); firstFivePrimeNumbers.add(2); firstFivePrimeNumbers.add(3); firstFivePrimeNumbers.add(5); firstFivePrimeNumbers.add(7); firstFivePrimeNumbers.add(11); // Creating an ArrayList from another collection List<Integer> firstTenPrimeNumbers = new ArrayList<>(firstFivePrimeNumbers); List<Integer> nextFivePrimeNumbers = new ArrayList<>(); nextFivePrimeNumbers.add(13); nextFivePrimeNumbers.add(17); nextFivePrimeNumbers.add(19); nextFivePrimeNumbers.add(23); nextFivePrimeNumbers.add(29); // Adding an entire collection to an ArrayList firstTenPrimeNumbers.addAll(nextFivePrimeNumbers); System.out.println(firstTenPrimeNumbers); } }</code></pre> </li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><br /> <span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">访问ArrayList中的元素</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">这个例子显示:</span></span></span></p> <ul style="margin-left:30px; margin-right:0px"> <li>如何使用该<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#isEmpty--" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>isEmpty()</code></a>方法检查ArrayList是否为空。</li> <li>如何使用该<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#size--" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>size()</code></a>方法找到ArrayList的大小。</li> <li>如何使用该<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#get-int-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>get()</code></a>方法访问ArrayList中特定索引处的元素。</li> <li>如何使用该<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#set-int-E-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>set()</code></a>方法修改ArrayList中特定索引处的元素。</li> </ul> <pre> <code class="language-java">import java.util.ArrayList; import java.util.List; public class AccessElementsFromArrayListExample { public static void main(String[] args) { List<String> topCompanies = new ArrayList<>(); // Check is an ArrayList is empty System.out.println("Is the topCompanies list empty? : " + topCompanies.isEmpty()); topCompanies.add("Google"); topCompanies.add("Apple"); topCompanies.add("Microsoft"); topCompanies.add("Amazon"); topCompanies.add("Facebook"); // Find the size of an ArrayList System.out.println("Here are the top " + topCompanies.size() + " companies in the world"); System.out.println(topCompanies); // Retrieve the element at a given index String bestCompany = topCompanies.get(0); String secondBestCompany = topCompanies.get(1); String lastCompany = topCompanies.get(topCompanies.size() - 1); System.out.println("Best Company: " + bestCompany); System.out.println("Second Best Company: " + secondBestCompany); System.out.println("Last Company in the list: " + lastCompany); // Modify the element at a given index topCompanies.set(4, "Walmart"); System.out.println("Modified top companies list: " + topCompanies); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">Is the topCompanies list empty? : true Here are the top 5 companies in the world [Google, Apple, Microsoft, Amazon, Facebook] Best Company: Google Second Best Company: Apple Last Company in the list: Facebook Modified top companies list: [Google, Apple, Microsoft, Amazon, Walmart]</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">从ArrayList中移除元素</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">这个例子显示:</span></span></span></p> <ol style="margin-left:30px; margin-right:0px"> <li> <p style="margin-left:0px; margin-right:0px">如何删除ArrayList |中给定索引处的元素 <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#remove-java.lang.Object-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">delete</a><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#remove-int-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">(int索引)</a></p> </li> <li> <p style="margin-left:0px; margin-right:0px">如何从ArrayList |中删除元素 <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#remove-java.lang.Object-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">delete(Object o)</a></p> </li> <li> <p style="margin-left:0px; margin-right:0px">如何从给定集合中存在的ArrayList中移除所有元素| <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#remove-java.lang.Object-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">delete</a>All<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#removeAll-java.util.Collection-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">()</a></p> </li> <li> <p style="margin-left:0px; margin-right:0px">如何删除所有匹配给定谓词|的元素 <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#removeIf-java.util.function.Predicate-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">removeIf()</a></p> </li> <li> <p style="margin-left:0px; margin-right:0px">如何清除ArrayList | <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#clear--" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">clear()</a></p> </li> </ol> <pre> <code class="language-java">import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; public class RemoveElementsFromArrayListExample { public static void main(String[] args) { List<String> programmingLanguages = new ArrayList<>(); programmingLanguages.add("C"); programmingLanguages.add("C++"); programmingLanguages.add("Java"); programmingLanguages.add("Kotlin"); programmingLanguages.add("Python"); programmingLanguages.add("Perl"); programmingLanguages.add("Ruby"); System.out.println("Initial List: " + programmingLanguages); // Remove the element at index `5` programmingLanguages.remove(5); System.out.println("After remove(5): " + programmingLanguages); // Remove the element "Kotlin" (The remove() method returns false if the element does not exist in the ArrayList) boolean isRemoved = programmingLanguages.remove("Kotlin"); System.out.println("After remove(\"Kotlin\"): " + programmingLanguages); // Remove all the elements belonging to the collection scriptingLanguages List<String> scriptingLanguages = new ArrayList<>(); scriptingLanguages.add("Python"); scriptingLanguages.add("Ruby"); scriptingLanguages.add("Perl"); programmingLanguages.removeAll(scriptingLanguages); System.out.println("After removeAll(scriptingLanguages): " + programmingLanguages); // Remove all the elements that satisfy the given predicate programmingLanguages.removeIf(new Predicate<String>() { @Override public boolean test(String s) { return s.startsWith("C"); } }); /* The above removeIf() call can also be written using lambda expression like this - programmingLanguages.removeIf(s -> s.startsWith("C")) */ System.out.println("After Removing all elements that start with \"C\": " + programmingLanguages); // Remove all elements from the ArrayList programmingLanguages.clear(); System.out.println("After clear(): " + programmingLanguages); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">Initial List: [C, C++, Java, Kotlin, Python, Perl, Ruby] After remove(5): [C, C++, Java, Kotlin, Python, Ruby] After remove("Kotlin"): [C, C++, Java, Python, Ruby] After removeAll(scriptingLanguages): [C, C++, Java] After Removing all elements that start with "C": [Java] After clear(): []</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">迭代ArrayList</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">以下示例显示如何使用迭代遍历ArrayList</span></span></span></p> <ol style="margin-left:30px; margin-right:0px"> <li>Java 8 <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#forEach-java.util.function.Consumer-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>forEach</code></a>循环。</li> <li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#iterator--" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>iterator()</code></a>。</li> <li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#iterator--" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>iterator()</code></a>和Java 8 <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html#forEachRemaining-java.util.function.Consumer-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">forEachRemaining()</a>方法。</li> <li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#listIterator-int-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>listIterator()</code></a>。</li> <li>每个循环都很简单。</li> <li>用索引循环。</li> </ol> <pre> <code class="language-java">import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public class IterateOverArrayListExample { public static void main(String[] args) { List<String> tvShows = new ArrayList<>(); tvShows.add("Breaking Bad"); tvShows.add("Game Of Thrones"); tvShows.add("Friends"); tvShows.add("Prison break"); System.out.println("=== Iterate using Java 8 forEach loop ==="); tvShows.forEach(tvShow -> { System.out.println(tvShow); }); System.out.println("\n=== Iterate using an iterator() ==="); Iterator<String> tvShowIterator = tvShows.iterator(); while (tvShowIterator.hasNext()) { String tvShow = tvShowIterator.next(); System.out.println(tvShow); } System.out.println("\n=== Iterate using an iterator() and Java 8 forEachRemaining() method ==="); tvShowIterator = tvShows.iterator(); tvShowIterator.forEachRemaining(tvShow -> { System.out.println(tvShow); }); System.out.println("\n=== Iterate using a listIterator() to traverse in both directions ==="); // Here, we start from the end of the list and traverse backwards. ListIterator<String> tvShowListIterator = tvShows.listIterator(tvShows.size()); while (tvShowListIterator.hasPrevious()) { String tvShow = tvShowListIterator.previous(); System.out.println(tvShow); } System.out.println("\n=== Iterate using simple for-each loop ==="); for(String tvShow: tvShows) { System.out.println(tvShow); } System.out.println("\n=== Iterate using for loop with index ==="); for(int i = 0; i < tvShows.size(); i++) { System.out.println(tvShows.get(i)); } } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">=== Iterate using Java 8 forEach loop === Breaking Bad Game Of Thrones Friends Prison break === Iterate using an iterator() === Breaking Bad Game Of Thrones Friends Prison break === Iterate using an iterator() and Java 8 forEachRemaining() method === Breaking Bad Game Of Thrones Friends Prison break === Iterate using a listIterator() to traverse in both directions === Prison break Friends Game Of Thrones Breaking Bad === Iterate using simple for-each loop === Breaking Bad Game Of Thrones Friends Prison break === Iterate using for loop with index === Breaking Bad Game Of Thrones Friends Prison break</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">在遍历期间需要修改ArrayList时,<code>iterator()</code>和<code>listIterator()</code>方法很有用。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">考虑下面的例子,在<code>iterator.remove()</code>遍历它的时候我们使用方法从ArrayList中移除元素-</span></span></span></p> <pre> <code class="language-java">import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ArrayListIteratorRemoveExample { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); numbers.add(13); numbers.add(18); numbers.add(25); numbers.add(40); Iterator<Integer> numbersIterator = numbers.iterator(); while (numbersIterator.hasNext()) { Integer num = numbersIterator.next(); if(num % 2 != 0) { numbersIterator.remove(); } } System.out.println(numbers); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">[18, 40]</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">在ArrayList中搜索元素</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">下面的例子显示了如何:</span></span></span></p> <ul style="margin-left:30px; margin-right:0px"> <li> <p style="margin-left:0px; margin-right:0px">检查ArrayList是否包含给定的元素|  <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#contains-java.lang.Object-" rel="external nofollow" target="_blank">contains</a><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#contains-java.lang.Object-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">()</a></p> </li> <li> <p style="margin-left:0px; margin-right:0px">查找ArrayList |中第一次出现元素的索引 <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#indexOf-java.lang.Object-" rel="external nofollow" target="_blank">indexOf</a><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#indexOf-java.lang.Object-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">()</a></p> </li> <li> <p style="margin-left:0px; margin-right:0px">查找ArrayList |中最后一次出现元素的索引 <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#lastIndexOf-java.lang.Object-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank">lastIndexOf()</a></p> </li> </ul> <pre> <code class="language-java">import java.util.ArrayList; import java.util.List; public class SearchElementsInArrayListExample { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("John"); names.add("Alice"); names.add("Bob"); names.add("Steve"); names.add("John"); names.add("Steve"); names.add("Maria"); // Check if an ArrayList contains a given element System.out.println("Does names array contain \"Bob\"? : " + names.contains("Bob")); // Find the index of first occurrence of an element in an ArrayList System.out.println("indexOf \"Steve\": " + names.indexOf("Steve")); System.out.println("indexOf \"Mark\": " + names.indexOf("Mark")); // Find the index of the last occurrence of an element in an ArrayList System.out.println("lastIndexOf \"John\" : " + names.lastIndexOf("John")); System.out.println("lastIndexOf \"Bill\" : " + names.lastIndexOf("Bill")); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">Does names array contain "Bob"? : true indexOf "Steve": 3 indexOf "Mark": -1 lastIndexOf "John" : 4 lastIndexOf "Bill" : -1</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">用户定义对象的ArrayList</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">由于ArrayList支持泛型,因此可以创建<strong>任何</strong>类型的ArrayList 。它可以是简单的类型,如<code>Integer</code>,<code>String</code>,<code>Double</code>或复杂类型等的ArrayLists的ArrayList,或包含HashMap的ArrayList或任何用户定义的对象的ArrayList。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">在以下示例中,您将学习如何创建用户定义对象的ArrayList。</span></span></span></p> <pre> <code class="language-java">import java.util.ArrayList; import java.util.List; class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public class ArrayListUserDefinedObjectExample { public static void main(String[] args) { List<User> users = new ArrayList<>(); users.add(new User("Rajeev", 25)); users.add(new User("John", 34)); users.add(new User("Steve", 29)); users.forEach(user -> { System.out.println("Name : " + user.getName() + ", Age : " + user.getAge()); }); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">Name : Rajeev, Age : 25 Name : John, Age : 34 Name : Steve, Age : 29</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">排序ArrayList</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">对ArrayList进行排序是您在程序中遇到的一个非常常见的任务。在本节中,我会告诉你如何 -</span></span></span></p> <ul style="margin-left:30px; margin-right:0px"> <li>使用<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#sort-java.util.List-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>Collections.sort()</code></a>方法对ArrayList进行排序。</li> <li>使用<a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#sort-java.util.Comparator-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>ArrayList.sort()</code></a>方法对ArrayList进行排序。</li> <li>用自定义比较器对用户定义对象的ArrayList进行排序。</li> </ul> <h4 style="margin-left:0px; margin-right:0px; text-align:start">1.使用Collections.sort()方法对ArrayList进行排序</h4> <pre> <code class="language-java">import java.util.ArrayList; import java.util.Collections; import java.util.List; public class ArrayListCollectionsSortExample { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); numbers.add(13); numbers.add(7); numbers.add(18); numbers.add(5); numbers.add(2); System.out.println("Before : " + numbers); // Sorting an ArrayList using Collections.sort() method Collections.sort(numbers); System.out.println("After : " + numbers); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">Before : [13, 7, 18, 5, 2] After : [2, 5, 7, 13, 18]</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">2.使用ArrayList.sort()方法对ArrayList排序<br />  </p> <pre> <code class="language-java">import java.util.ArrayList; import java.util.Comparator; import java.util.List; public class ArrayListSortExample { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("Lisa"); names.add("Jennifer"); names.add("Mark"); names.add("David"); System.out.println("Names : " + names); // Sort an ArrayList using its sort() method. You must pass a Comparator to the ArrayList.sort() method. names.sort(new Comparator<String>() { @Override public int compare(String name1, String name2) { return name1.compareTo(name2); } }); // The above `sort()` method call can also be written simply using lambda expressions names.sort((name1, name2) -> name1.compareTo(name2)); // Following is an even more concise solution names.sort(Comparator.naturalOrder()); System.out.println("Sorted Names : " + names); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">输出:</span></span></span></p> <pre> <code class="language-html">Names : [Lisa, Jennifer, Mark, David] Sorted Names : [David, Jennifer, Lisa, Mark]</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">3.使用自定义比较器对对象的ArrayList进行排序<br />  </p> <pre> <code class="language-java">import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; class Person { private String name; private Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class ArrayListObjectSortExample { public static void main(String[] args) { List<Person> people = new ArrayList<>(); people.add(new Person("Sachin", 47)); people.add(new Person("Chris", 34)); people.add(new Person("Rajeev", 25)); people.add(new Person("David", 31)); System.out.println("Person List : " + people); // Sort People by their Age people.sort((person1, person2) -> { return person1.getAge() - person2.getAge(); }); // A more concise way of writing the above sorting function people.sort(Comparator.comparingInt(Person::getAge)); System.out.println("Sorted Person List by Age : " + people); // You can also sort using Collections.sort() method by passing the custom Comparator Collections.sort(people, Comparator.comparing(Person::getName)); System.out.println("Sorted Person List by Name : " + people); } }</code></pre> 输出: <pre> <code class="language-html">Person List : [{name='Sachin', age=47}, {name='Chris', age=34}, {name='Rajeev', age=25}, {name='David', age=31}] Sorted Person List by Age : [{name='Rajeev', age=25}, {name='David', age=31}, {name='Chris', age=34}, {name='Sachin', age=47}] Sorted Person List by Name : [{name='Chris', age=34}, {name='David', age=31}, {name='Rajeev', age=25}, {name='Sachin', age=47}]</code></pre>   <h2 style="margin-left:0px; margin-right:0px; text-align:start">同步对ArrayList的访问</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">ArrayList类不同步。如果多个线程同时尝试修改一个ArrayList,那么最终的结果变得不确定,因为一个线程可能会覆盖另一个线程所做的更改。</span></span></span></p> <h4 style="margin-left:0px; margin-right:0px; text-align:start">示例演示ArrayList在多线程环境中的不可预知行为</h4> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">以下示例显示了当多个线程同时尝试修改ArrayList时发生的情况。</span></span></span></p> <pre> <code class="language-java">import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class UnsafeArrayListExample { public static void main(String[] args) throws InterruptedException { List<Integer> unsafeArrayList = new ArrayList<>(); unsafeArrayList.add(1); unsafeArrayList.add(2); unsafeArrayList.add(3); // Create a thread pool of size 10 ExecutorService executorService = Executors.newFixedThreadPool(10); // Create a Runnable task that increments the each element of the ArrayList by one Runnable task = () -> { incrementArrayList(unsafeArrayList); }; // Submit the task to the executor service 100 times. // All the tasks will modify the ArrayList concurrently for(int i = 0; i < 100; i++) { executorService.submit(task); } executorService.shutdown(); executorService.awaitTermination(60, TimeUnit.SECONDS); System.out.println(unsafeArrayList); } // Increment all the values in the ArrayList by one private static void incrementArrayList(List<Integer> unsafeArrayList) { for(int i = 0; i < unsafeArrayList.size(); i++) { Integer value = unsafeArrayList.get(i); unsafeArrayList.set(i, value + 1); } } }</code></pre> 上述程序的最终输出应该相等,<code>[101, 102, 103]</code>因为我们将ArrayList中的值增加了100次。但是如果你运行这个程序,它会在每次运行时产生不同的输出 -<br /> 输出: <pre> <code class="language-html">[96, 96, 98]</code></pre>   <h4 style="margin-left:0px; margin-right:0px; text-align:start">演示如何将并发修改同步到ArrayList的示例</h4> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">好吧!现在让我们看看我们如何<code>ArrayList</code>在多线程环境中同步访问。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">以下示例显示了上一个示例的同步版本。与以前的程序不同,该程序的输出是确定性的,并且始终是相同的。</span></span></span></p> <pre> <code class="language-java">import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class SynchronizedArrayListExample { public static void main(String[] args) throws InterruptedException { List<Integer> safeArrayList = Collections.synchronizedList(new ArrayList<>()); safeArrayList.add(1); safeArrayList.add(2); safeArrayList.add(3); // Create a thread pool of size 10 ExecutorService executorService = Executors.newFixedThreadPool(10); // Create a Runnable task that increments the each element of the ArrayList by one Runnable task = () -> { incrementArrayList(safeArrayList); }; // Submit the task to the executor service 100 times. // All the tasks will modify the ArrayList concurrently for(int i = 0; i < 100; i++) { executorService.submit(task); } executorService.shutdown(); executorService.awaitTermination(60, TimeUnit.SECONDS); System.out.println(safeArrayList); } // Increment all the values in the ArrayList by one private static void incrementArrayList(List<Integer> safeArrayList) { synchronized (safeArrayList) { for (int i = 0; i < safeArrayList.size(); i++) { Integer value = safeArrayList.get(i); safeArrayList.set(i, value + 1); } } } }</code></pre> 输出: <pre> <code class="language-html">[101, 102, 103]</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">以上示例使用<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedList-java.util.List-" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>Collections.synchronizedList()</code></a>方法来获取ArrayList的同步视图。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff">而且,对<code>incrementArrayList()</code>方法内的ArrayList的修改被封装在一个<code>synchronized</code>块中。这确保了两个线程不能同时增加ArrayList元素。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:rgba(0, 0, 0, 0.87)"><span style="font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif"><span style="background-color:#ffffff"><em><a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html" rel="external nofollow" style="box-sizing:border-box; color:#419be8; text-decoration:none; word-wrap:break-word" target="_blank"><code>CopyOnWriteArrayList</code></a>如果你需要线程安全,你也可以使用。它是ArrayList类的线程安全版本。它通过创建ArrayList的新副本来实现所有的变异操作。</em></span></span></span></p>
  • Java编程软件有哪些_常用Java编程软件下载和安装

    Java编程软件有哪些?常用Java编程软件下载、安装和使用说明Java编程软件下载和安装_Java编程常用软件
  • Java MongoDB驱动程序

    Java MongoDB驱动程序,下载/升级,Java驱动程序兼容性,第三方框架和库<h1>Java MongoDB驱动程序</h1> <p>在这个页面上</p> <ul> <li><a href="https://docs.mongodb.com/ecosystem/drivers/java/#driver-features" id="id3" rel="nofollow" target="_blank">驱动程序特点</a></li> <li><a href="https://docs.mongodb.com/ecosystem/drivers/java/#download-upgrade" id="id4" rel="nofollow" target="_blank">下载/升级</a></li> <li><a href="https://docs.mongodb.com/ecosystem/drivers/java/#java-driver-compatibility" id="id5" rel="nofollow" target="_blank">Java驱动程序兼容性</a></li> <li><a href="https://docs.mongodb.com/ecosystem/drivers/java/#third-party-frameworks-and-libraries" id="id6" rel="nofollow" target="_blank">第三方框架和图书馆</a></li> <li><a href="https://docs.mongodb.com/ecosystem/drivers/java/#additional-resources" id="id7" rel="nofollow" target="_blank">其他资源</a></li> </ul> <p>从3.0版本开始,官方MongoDB Java驱动程序提供与MongoDB的同步和异步交互。有关官方MongoDB Java Driver参考资料,请参阅:</p> <ul> <li><a href="http://mongodb.github.io/mongo-java-driver/" rel="nofollow" target="_blank">MongoDB Java驱动程序文档</a></li> <li><a href="http://api.mongodb.com/java/current" rel="nofollow" target="_blank">MongoDB Java驱动程序API文档</a></li> </ul> <h2>驱动程序特性</h2> MongoDB驱动<br /> 一个更新的Java驱动程序,其中包括传统的API以及符合新的跨驱动程序CRUD规范的新的通用MongoCollection界面。有关Java驱动程序的文档,包括入门指南,请参阅<a href="http://mongodb.github.io/mongo-java-driver/3.2/driver/" rel="nofollow" target="_blank">Java驱动程序文档</a>。<br /> MongoDB异步驱动<br /> 一种新的异步API,可以利用Netty或Java 7的AsynchronousSocketChannel快速和非阻塞IO。有关Async Java驱动程序(包括入门指南)的<a href="http://mongodb.github.io/mongo-java-driver/3.2/driver-async/" rel="nofollow" target="_blank">文档</a>,请参阅<a href="http://mongodb.github.io/mongo-java-driver/3.2/driver-async/" rel="nofollow" target="_blank">Async Java驱动程序文档</a>。<br /> BSON图书馆<br /> 具有新型编解码器基础架构的独立BSON库,可用于构建高性能编码器和解码器,无需中间地图实例。有关BSON Library的文档,请参阅<a href="http://mongodb.github.io/mongo-java-driver/3.2/bson/" rel="nofollow" target="_blank">BSON Library</a>。<br /> 核心驱动<br /> 一个新的核心库,MongoDB驱动程序和异步驱动程序都在其上构建。用户可以使用新的核心库构建替代或实验高级API。 <h2>下载/升级</h2> <p>将驱动程序合并到项目中的推荐方法是使用依赖关系管理系统。有关更多信息,请参阅 <a href="http://mongodb.github.io/mongo-java-driver/" rel="nofollow" target="_blank">MongoDB Java驱动程序</a>。</p> <p>如果从较早版本的Java驱动程序升级,请参阅 <a href="http://mongodb.github.io/mongo-java-driver/3.2/whats-new/upgrading/" rel="nofollow" target="_blank">最新消息</a>。</p> <h2>Java驱动程序兼容性</h2> <h3>MongoDB兼容性</h3> <p>以下兼容性表格指定了与特定版本的MongoDB一起使用的MongoDB Java驱动程序的推荐版本。</p> <p>第一列列出了驱动程序版本。</p> <table border="1"> <thead> <tr> <th>Java驱动程序版本</th> <th>MongoDB 2.4</th> <th>MongoDB 2.6</th> <th>MongoDB 3.0</th> <th>MongoDB 3.2</th> <th>MongoDB 3.4</th> </tr> </thead> <tbody> <tr> <th>版本3.4</th> <td>✓</td> <td>✓</td> <td>✓</td> <td>✓</td> <td>✓</td> </tr> <tr> <th>版本3.3</th> <td>✓</td> <td>✓</td> <td>✓</td> <td>✓</td> <td> </td> </tr> <tr> <th>版本3.2</th> <td>✓</td> <td>✓</td> <td>✓</td> <td>✓</td> <td> </td> </tr> <tr> <th>版本2.14</th> <td>✓</td> <td>✓</td> <td>✓</td> <td>✓<a href="https://docs.mongodb.com/ecosystem/drivers/java/#id2" id="id1" rel="nofollow">[*]</a></td> <td> </td> </tr> </tbody> </table> <p>有关其他驱动程序版本,请参阅<a href="https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#reference-compatibility-mongodb-java" rel="nofollow" target="_blank">Java驱动程序MongoDB兼容性参考</a>。</p> <p>该驱动程序不支持旧版本的MongoDB。</p> <table id="id2"> <tbody> <tr> <td><a href="https://docs.mongodb.com/ecosystem/drivers/java/#id1" rel="nofollow" target="_blank">[*]</a></td> <td>2.14驱动程序不支持所有MongoDB 3.2功能(例如,阅读关注); 但是,如果您当前使用的是2.x版本的驱动程序,并且希望针对MongoDB 3.2运行,但无法升级到驱动程序版本3.2,请使用2.14驱动程序。</td> </tr> </tbody> </table> <h3>语言兼容性</h3> <p>以下兼容性表格指定了与特定版本的Java一起使用的MongoDB Java驱动程序的推荐版本。</p> <p>第一列列出了驱动程序版本。</p> <table border="1"> <thead> <tr> <th>Java驱动程序版本</th> <th>Java 5</th> <th>Java 6</th> <th>Java 7</th> <th>Java 8</th> </tr> </thead> <tbody> <tr> <th>版本3.x</th> <td> </td> <td>✓</td> <td>✓</td> <td>✓</td> </tr> <tr> <th>版本2.x</th> <td>✓</td> <td>✓</td> <td>✓</td> <td>✓</td> </tr> </tbody> </table> <p>有关其他驱动程序版本,请参阅<a href="https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#reference-compatibility-language-java" rel="nofollow" target="_blank">Java驱动程序语言兼容性参考</a>。</p> <h2>第三方框架和库</h2> <h3>POJO贴片</h3> <ul> <li><a href="https://github.com/mongodb/morphia" rel="nofollow" target="_blank">Morphia</a>。带有DAO / Datastore抽象的Type-Safe Wrapper。</li> <li><a href="http://www.springsource.org/spring-data/mongodb" rel="nofollow" target="_blank">Spring MongoDB</a>。为Spring用户提供熟悉的数据访问功能,包括丰富的POJO映射。</li> <li><a href="http://sboesebeck.github.io/morphium/" rel="nofollow" target="_blank">形态</a>。功能丰富的POJO Mapper包括声明缓存,集群感知,验证,部分更新等功能,支持聚合框架。</li> <li><a href="http://github.com/jannehietamaki/mungbean" rel="nofollow" target="_blank">绿豆</a>(w / clojure支持)。</li> <li><a href="http://www.datanucleus.org/products/accessplatform_3_0/mongodb/support.html" rel="nofollow" target="_blank">DataNucleus JPA / JDO</a>。JPA / JDO包装器</li> <li><a href="https://github.com/dadastream/lib-mongomapper" rel="nofollow" target="_blank">LIB-mongomapper</a>。JavaBean Mapper(无注释)。</li> <li><a href="http://mongojack.org/" rel="nofollow" target="_blank">MongoJack</a>。使用杰克逊(注释)来映射到POJO或从POJO映射,并有一个简单的包装<code>DBCollection</code>。</li> <li><a href="http://kundera.googlecode.com/" rel="nofollow" target="_blank">昆德拉</a>。JPA兼容ORM。适用于多个数据存储。</li> <li><a href="http://dbuschman7.github.io/mongoFS/" rel="nofollow" target="_blank">MongoFS</a>。增强的文件存储库,支持文件压缩,加密和Zip文件扩展。可以在GridFS兼容的桶上使用。</li> <li><a href="http://www.jongo.org/" rel="nofollow" target="_blank">琼戈</a>。在Java中查询<code>mongo</code>(在shell中使用字符串),将结果解组成Java对象(使用Jackson)</li> <li><a href="http://mongolink.org/" rel="nofollow" target="_blank">MongoLink</a>。对象文档映射器(ODM。)使用简单的java DSL进行映射声明。</li> <li><a href="http://www.hibernate.org/ogm/" rel="nofollow" target="_blank">休眠OGM</a>。为MongoDB提供Java持久性支持。</li> <li><a href="http://github.com/ParaPenguin/morphix" rel="nofollow" target="_blank">Morphix</a>。轻量级,易于使用的POJO映射器,具有对象缓存和生命周期方法。</li> </ul> <h3>代码生成</h3> <ul> <li><a href="http://java.dzone.com/articles/using-mongodb-sculptor" rel="nofollow" target="_blank">雕塑家</a>。基于MongoDB的DSL - > Java(代码生成器)</li> <li><a href="http://github.com/mattinsler/com.lowereast.guiceymongo/" rel="nofollow" target="_blank">GuicyData</a>。DSL - > Java生成器与Guice集成。</li> </ul> <h3>杂项</h3> <ul> <li><a href="https://github.com/gaillard/mongo-queue-java" rel="nofollow" target="_blank">mongo-queue-java</a>。Java消息队列使用MongoDB作为后端。</li> <li><a href="https://github.com/deftlabs/mongo-java-logging" rel="nofollow" target="_blank">mongo-java-logging</a>。Java日志记录处理程序。</li> <li><a href="http://code.google.com/p/log4mongo/" rel="nofollow" target="_blank">log4mongo</a>。一个log4j appender</li> <li><a href="http://www.allanbank.com/mongodb-async-driver/" rel="nofollow" target="_blank">Allanbank异步Java驱动程序</a></li> <li><a href="http://www.unityjdbc.com/mongojdbc/" rel="nofollow" target="_blank">MongoDB的JDBC驱动</a></li> <li><a href="http://github.com/erh/mongo-jdbc" rel="nofollow" target="_blank">(实验,Type4)JDBC驱动程序</a></li> <li><a href="http://metamodel.eobjects.org/download.html" rel="nofollow" target="_blank">元模型数据挖掘和查询库</a></li> <li><a href="https://sites.google.com/site/mongodbjavarestserver/home" rel="nofollow" target="_blank">Mongodb Java REST服务器</a>基于<a href="http://www.eclipse.org/jetty/" rel="nofollow" target="_blank">Jetty</a></li> </ul> <h3>Clojure的</h3> <ul> <li><a href="https://github.com/michaelklishin/monger" rel="nofollow" target="_blank">贩子</a></li> <li><a href="https://github.com/aboekhoff/congomongo" rel="nofollow" target="_blank">刚果蒙古</a></li> </ul> <h3>Groovy的</h3> <ul> <li><a href="http://github.com/poiati/gmongo" rel="nofollow" target="_blank">GMongo,一个Groovy包装到MongoDB Java驱动程序</a></li> <li><a href="http://blog.paulopoiati.com/2010/06/20/gmongo-0-5-released" rel="nofollow" target="_blank">GMongo 0.5发行编写</a></li> </ul> <h3>JavaScript(Rhino)</h3> <ul> <li><a href="https://github.com/nlloyd/horn-of-mongo" rel="nofollow" target="_blank">蒙戈的号角</a>。一个基于Java的Rhino JavaScript Engine构建的MongoDB shell。</li> <li><a href="http://code.google.com/p/mongodb-rhino" rel="nofollow" target="_blank">MongoDB犀牛</a>。提供JVM和MongoDB的Rhino JavaScript引擎之间的完全集成的工具集。使用MongoDB Java驱动程序。</li> </ul> <h3>Hadoop的</h3> <p><a href="https://docs.mongodb.com/ecosystem/tools/hadoop/#hadoop-connector" rel="nofollow" target="_blank">MongoDB Connector for Hadoop</a></p> <h2>其他资源</h2> <ul> <li><a href="https://university.mongodb.com/courses/M101J/about?jmp=docs" rel="nofollow" target="_blank">M101J:MongoDB for Java开发者免费在线课程</a></li> <li><a href="http://www.mongodb.com/presentations/webinar-mongodb-java-everything-you-need-know?jmp=docs" rel="nofollow" target="_blank">演示:MongoDB + Java - 你需要知道的一切</a></li> <li><a href="http://docs.mongodb.org/getting-started/java" rel="nofollow" target="_blank">MongoDB入门(Java Edition)</a></li> </ul>
  • java多线程编程_java多线程安全_java多线程实现安全锁CAS机制

    java多线程编程_java多线程安全_java多线程实现安全锁CAS机制,CAS在java多线程中相当于数据库的乐观锁,synchronized相当于数据库的乐观锁。<h2>引言</h2>     java多线程编程中难免会遇到资源共享。这里将会讲解一下java多线程中的CAS机制和锁的基础概念。java多线程编程_java多线程安全_java多线程实现安全锁CAS机制,CAS在java多线程中相当于数据库的乐观锁,synchronized相当于数据库的乐观锁。 <h2>一.java多线程编程常见问题</h2> <strong><a rel="external nofollow" target="_blank" id="java多线程1" name="java多线程1">java多线程示例程序</a>:</strong>启动两个线程,每个线程中让静态共享变量count循环累加100次<br /> <br /> <a rel="external nofollow" target="_blank" id="java多线程代码" name="java多线程代码"><strong>java多线程示例代码</strong></a>: <pre> <code class="language-java">package xqlee.net.project.demo.thread.synchronize; public class ForTest { public static int count = 0; public static void main(String[] args) { // 开启两个线程 for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } //每个线程累计加100 for (int j = 0; j < 100; j++) { count++; // System.out.println(count); } } }).start(); } try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } System.out.println("count=" + count); } } </code></pre> <strong>疑惑</strong>:<span style="color:#6600ff">最终输出的count结果是多少呢?两个线程执行完毕一定是200吗?</span><br /> <br /> <strong>答案</strong>:因为这段代码不是线程安装的,所以最终的自增结果很有可能会小于200。<br /> <strong>尝试执行结果</strong>:<br /> <img alt="java多线程演示代码执行结果" class="img-thumbnail" src="/resources/assist/images/blog/00053be4566b4b93acc2f6e7b13e93bf.png" /><br /> 接下来,修改上面的演示代码。通过关键字synchronized在java多线程编程实现中添加一个锁。这个是个重量级的锁。后续详说。<br /> 修改后演示代码如下: <pre> <code class="language-java">package xqlee.net.project.demo.thread.synchronize; public class ForTest { public static int count = 0; public static void main(String[] args) { // 开启两个线程 for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } //每个线程累计加100 for (int j = 0; j < 100; j++) { synchronized (ForTest.class) { count++; } // System.out.println(count); } } }).start(); } try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } System.out.println("count=" + count); } } </code></pre> <br /> 再次执行演示代码,查看结果:<br /> <img alt="java多线程编程加锁后的执行结果" class="img-thumbnail" src="/resources/assist/images/blog/0ef74f747d6c440c8f62513431d9b462.png" /><br />     加了同步锁之后,count自增的操作变成了原子性操作,所以最终的输出一定是<strong>count=200</strong>,代码实现了线程安全。<br /> <br />     但是注意,虽然synchronized确保了线程的安全,但是在某些情况下,却不是一个最优选择。为啥这么说呢?关键在于synchronized存在性能问题。synchronized关键字会让没有得到锁资源的线程进入BLOCKED状态,而后再争夺到锁资源后恢复为RUNNABLE状态,这个过程中涉及到操作系统<strong>用户模式</strong>和<strong>内核模式</strong>的转换,代价比较高。尽管Java1.6为Synchronized做了优化,增加了从<strong>偏向锁</strong>到<strong>轻量级锁</strong>再到<strong>重量级锁</strong>的过度,但是在最终转变为重量级锁之后,性能仍然较低。<br /> <br /> <br /> 那么有啥好的其他解决办法嘛?<br /> 有:原子操作类;<br /> <img alt="JDK中的原子操作类" class="img-thumbnail" src="/resources/assist/images/blog/4a065fca722e4577982931e44fe71839.png" /> <p>  所谓原子操作类,指的是java.util.concurrent.atomic包下,一系列以Atomic开头的包装类。例如<strong>AtomicBoolean</strong>,<strong>AtomicInteger</strong>,<strong>AtomicLong</strong>。它们分别用于Boolean,Integer,Long类型的原子性操作。</p> <p>现在我们尝试在代码中引入AtomicInteger类:</p> <pre> <code class="language-java">package xqlee.net.project.demo.thread.synchronize; import java.util.concurrent.atomic.AtomicInteger; public class ForTest2 { public static AtomicInteger count = new AtomicInteger(0); public static void main(String[] args) { // 开启两个线程 for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } //每个线程累计加100 for (int j = 0; j < 100; j++) { count.incrementAndGet(); // System.out.println(count); } } }).start(); } try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } System.out.println("count=" + count); } } </code></pre> <br /> 演示执行结果:<br /> <img alt="原子操作类进行乐观锁" class="img-thumbnail" src="/resources/assist/images/blog/be44242a5e9340abbe97aa8cd621a55f.png" /><br /> 使用AtomicInteger之后,最终的输出结果同样可以保证是200。并且在<strong>某些情况下</strong>,代码的性能会比Synchronized更好。<br /> <br /> 那么Atomic操作类底层到底利用了什么手段呢?<br /> 其实Atomic就是用到了我们要讲的[CAS机制]<br />   <p><strong>什么是CAS?</strong></p> <p> </p> <p>CAS是英文单词<strong>Compare And Swap</strong>的缩写,翻译过来就是比较并替换。</p> <p> </p> <p>CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。</p> <p>更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。</p> <p>这样说或许有些抽象,我们来看一个例子:</p> <p>1.在内存地址V当中,存储着值为10的变量。</p> <img alt="内存地址V" class="img-thumbnail" src="/resources/assist/images/blog/9da6331c557f46d3ad148fe777a91e5a.png" /><br /> 2.此时线程1想要把变量的值增加1。对线程1来说,旧的预期值A=10,要修改的新值B=11。<br /> <img alt="内存地址V2" class="img-thumbnail" src="/resources/assist/images/blog/761fcd40fb074a66915e845d08139997.png" /><br /> <br /> 3.在线程1要提交更新之前,另一个线程2抢先一步,把内存地址V中的变量值率先更新成了11。<br /> <br /> <img alt="内存地址V3" class="img-thumbnail" src="/resources/assist/images/blog/e247329a723f45c39dd4db9f50b59122.png" /><br /> 4.线程1开始提交更新,首先进行<strong>A和地址V的实际值比较(Compare)</strong>,发现A不等于V的实际值,提交失败。<br /> <img alt="内存地址V4" class="img-thumbnail" src="/resources/assist/images/blog/ea99b78cf5fa414fa481ff39437f310e.png" /><br /> 5.线程1重新获取内存地址V的当前值,并重新计算想要修改的新值。此时对线程1来说,A=11,B=12。这个重新尝试的过程被称为<strong>自旋</strong>。<br /> <br /> <img alt="内存地址V5" class="img-thumbnail" src="/resources/assist/images/blog/f03a795b87884530a02d4247f2e1bd26.png" /><br /> 6.这一次比较幸运,没有其他线程改变地址V的值。线程1进行<strong>Compare</strong>,发现A和地址V的实际值是相等的。<br /> <br /> <img alt="内存地址6" class="img-thumbnail" src="/resources/assist/images/blog/f1d8e07fac864ef9845aed9436d17c7f.png" /><br /> 7.线程1进行<strong>SWAP</strong>,把地址V的值替换为B,也就是12。<br /> <img alt="内存地址7" class="img-thumbnail" src="/resources/assist/images/blog/c407d63f332043bc8c09f4582d66e6dc.png" /><br />     所以从思想上来说,Synchronized属于<strong>悲观锁</strong>,悲观地认为程序中的并发情况严重,所以严防死守。CAS属于<strong>乐观锁</strong>,乐观地认为程序中的并发情况不那么严重,所以让线程不断去尝试更新。<br /> <br /> 两种机制CAS机制和Synchronized,没有绝对的好坏。那么如何抉择呢?<br /> 在并发量非常搞的情况下使用Synchronized同步锁更适合一些。<br /> <br /> <strong>CAS缺点:</strong> <p><strong>1.CPU开销较大</strong></p> <p>在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力。</p> <p><strong>2.不能保证代码块的原子性</strong></p> <p>CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用Synchronized了。</p> <p><strong>3.ABA问题</strong></p> <p>这是CAS机制最大的问题所在。</p> <p>什么是<strong>ABA</strong>问题?怎么解决?我们后面来详细介绍。</p>
  • Java编程之Map与Java bean之间的转换工具类

    Map与Java bean之间的转换工具类,用于java.util.Map与普通javabean直接的相互转换,Java编程Java编程之Map与Java bean之间的转换工具类,用于java.util.Map与普通javabean直接的相互转换<br /> 工具代码清单:<br /> MapUtils.java: <pre> <code class="language-java">import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; public class MapUtils { /** * javaBean 转 Map * * @param object * 需要转换的javabean * @return 转换结果map * @throws Exception */ public static Map<String, Object> beanToMap(Object object) throws Exception { Map<String, Object> map = new HashMap<String, Object>(); @SuppressWarnings("rawtypes") Class cls = object.getClass(); Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); map.put(field.getName(), field.get(object)); } return map; } /** * * @param map * 需要转换的map * @param cls * 目标javaBean的类对象 * @return 目标类object * @throws Exception */ public static Object mapToBean(Map<String, Object> map, @SuppressWarnings("rawtypes") Class cls) throws Exception { Object object = cls.newInstance(); for (String key : map.keySet()) { Field temFiels = cls.getDeclaredField(key); temFiels.setAccessible(true); temFiels.set(object, map.get(key)); } return object; } } </code></pre> <br /> 利用了Java语言的反射机制