-
Java应用层做过滤
2018-01-16 17:23:01数据库对某些条件的过滤支持不是很好,比如LIKE,造成查询效率不高,实践中我们设计了一个工具类,用于Java应用层过滤。 我们基于JFinal的Db+Record实现。 首先设计一个记录过滤器RecordFilter,用于判断某个...数据库对某些条件的过滤支持不是很好,比如LIKE,造成查询效率不高,实践中我们设计了一个工具类,用于Java应用层过滤。
我们基于JFinal的Db+Record实现。
- 首先设计一个记录过滤器RecordFilter,用于判断某个Record是否满足要求。
import com.jfinal.plugin.activerecord.Record; import java.util.Iterator; import java.util.List; import java.util.Objects; /** * @author 熊诗言 2017/01/07 * Record过滤器 */ @FunctionalInterface public interface RecordFilter { /** * 看一条记录是否满足条件 * @param record Record * @return 是否满足 */ boolean accept(Record record); /** * 过滤记录 * @param records 源记录,同时也是过滤后的 * @return 满足条件的记录条数 */ default List<Record> accept(List<Record> records){ Objects.requireNonNull(records); Iterator<Record> iterator = records.iterator(); while (iterator.hasNext()) { Record record = iterator.next(); boolean acc = accept(record); if(!acc){ //不满足的删除 iterator.remove(); } } return records; } }
- 其抽象子类AbstractRecordFilter,主要提供一些判断的方法,另外更好地实现删除一个List的remove。
package cn.zytx.common.db.sqlfilter; import com.jfinal.plugin.activerecord.Record; import java.sql.Time; import java.sql.Timestamp; import java.util.Date; import java.util.List; /** * @author 熊诗言 2017/01/07 * Record过滤器抽象类,提供一些通用的比较方法 */ public abstract class AbstractRecordFilter implements RecordFilter{ /** * 模拟LIKE */ protected boolean attrContains(Record record,String attr,String except){ return null != record.getStr(attr) && record.getStr(attr).contains(except); } protected boolean attrRegexMatch(Record record,String attr,String regex){ return null != record.getStr(attr) && record.getStr(attr).matches(regex); } /** * 比较相等 */ protected boolean attrEquals(Record record,String attr,String except){ return null != record.getStr(attr) && except.equals(record.getStr(attr)); } protected boolean attrEquals(Record record,String attr,int except){ return null != record.getInt(attr) && except == record.getInt(attr); } protected boolean attrEquals(Record record,String attr,long except){ return null != record.getLong(attr) && except == record.getLong(attr); } protected boolean attrEquals(Record record,String attr,float except){ return null != record.getFloat(attr) && except == record.getFloat(attr); } protected boolean attrEquals(Record record,String attr,double except){ return null != record.getDouble(attr) && except == record.getDouble(attr); } protected boolean attrEquals(Record record,String attr,Date except){ return null != record.getDate(attr) && except.getTime() == record.getDate(attr).getTime(); } protected boolean attrEquals(Record record,String attr,Time except){ return null != record.getTime(attr) && except.getTime() == record.getTime(attr).getTime(); } protected boolean attrEquals(Record record,String attr,Timestamp except){ return null != record.getTimestamp(attr) && except.compareTo(record.getTimestamp(attr)) == 0; } /** * Greater than or Equals 比较 >=,reverse就是 < */ protected boolean attrGE(Record record,String attr,int except){ return null != record.getInt(attr) && record.getInt(attr) >= except; } protected boolean attrGE(Record record,String attr,long except){ return null != record.getLong(attr) && record.getLong(attr) >= except; } protected boolean attrGE(Record record,String attr,float except){ return null != record.getFloat(attr) && record.getFloat(attr) >= except; } protected boolean attrGE(Record record,String attr,double except){ return null != record.getDouble(attr) && record.getDouble(attr) >= except; } protected boolean attrGE(Record record,String attr,Date except){ return null != record.getDate(attr) && record.getDate(attr).getTime() >= except.getTime(); } protected boolean attrGE(Record record,String attr,Time except){ return null != record.getTime(attr) && record.getTime(attr).getTime() >= except.getTime(); } protected boolean attrGE(Record record,String attr,Timestamp except){ return null != record.getTimestamp(attr) && record.getTimestamp(attr).getTime() >= except.getTime(); } /** * Less than or Equals 比较 <=,reverse就是 > */ protected boolean attrLE(Record record,String attr,int except){ return null != record.getInt(attr) && record.getInt(attr) <= except; } protected boolean attrLE(Record record,String attr,long except){ return null != record.getLong(attr) && record.getLong(attr) <= except; } protected boolean attrLE(Record record,String attr,float except){ return null != record.getFloat(attr) && record.getFloat(attr) <= except; } protected boolean attrLE(Record record,String attr,double except){ return null != record.getDouble(attr) && record.getDouble(attr) <= except; } protected boolean attrLE(Record record,String attr,Date except){ return null != record.getDate(attr) && record.getDate(attr).getTime() <= except.getTime(); } protected boolean attrLE(Record record,String attr,Time except){ return null != record.getTime(attr) && record.getTime(attr).getTime() <= except.getTime(); } protected boolean attrLE(Record record,String attr,Timestamp except){ return null != record.getTimestamp(attr) && record.getTimestamp(attr).getTime() <= except.getTime(); } @Override public List<Record> accept(List<Record> records) { /** * 从后往前遍历删除,移动的元素更少,效率更高 */ for (int i = records.size()-1; i >= 0 ; i--) { boolean acc = accept(records.get(i)); if(!acc){ records.remove(i); } } return records; } }
- 真正的过滤方法
测试代码:package cn.zytx.common.db.sqlfilter; import com.jfinal.plugin.activerecord.Db; import com.jfinal.plugin.activerecord.Page; import com.jfinal.plugin.activerecord.Record; import java.util.ArrayList; import java.util.List; import java.util.Objects; /** * @author xiongshiyan at 2018/1/7 * 查询表数据,复杂的过滤在Java应用层做,SQL中只写很容易过滤的条件,基于一个事实:数据库过滤复杂条件效率不高 */ public class QueryListWithFilter { /** * 查询数据,传入过滤器,复杂的过滤写在过滤器中,SQL只写容易过滤的条件 * @param sql SQL语句,可以写容易过滤的条件,像时间区间这种;SQL语句中不能包含?方法会自动加上LIMIT ?,?来分批次获取数据 * @param pageNumber 页数 * @param pageSize 每页数量 * @param batchPullDataSize 每次从数据库拉取数量,此值有待测试优化,每次拉取多就可以少拉取几次,每次拉取少就多拉取几次,需要找到这个平衡点 * @param pageTotalDataSize 页面可以放的总记录数量(基于一个事实,页面记录数量太多,也没得价值),此值如果设置很大,就退化为正常的查询。此值不宜过大,否则可能造成内存溢出 * @param filter Java应用层过滤器,比较复杂的过滤放在Java层做,如果传进来null,则不过滤 * @return Page<Record> */ public static Page<Record> query(String sql, int pageNumber, int pageSize, int batchPullDataSize, int pageTotalDataSize, RecordFilter filter){ Objects.requireNonNull(sql); if(sql.toUpperCase().contains("LIMIT")){ throw new IllegalArgumentException("SQL语句中不能包含LIMIT语句"); } sql += " LIMIT ?,?"; if(null == filter){ filter = new AllAcceptRecordFilter(); } List<Record> resultList = getRecords(sql, batchPullDataSize, pageTotalDataSize, filter); //取出最多pageTotalDataSize,没有这么多就实际的条数 /*if(resultList.size() < pageTotalDataSize){ pageTotalDataSize = resultList.size(); } resultList = resultList.subList(0,pageTotalDataSize);*/ //计算总行数、总页数 int totalRow = resultList.size(); int totalPage = totalRow / pageSize; if(totalRow % pageSize != 0){ ++totalPage; } //计算当页开始和结束条数 int thisPage = (pageNumber - 1) * pageSize; int toIndex = thisPage + pageSize; //一般是末页不够的情况 if(toIndex > resultList.size()){ toIndex = resultList.size(); } //获取当前页数据 resultList = resultList.subList(thisPage,toIndex); return new Page<>(resultList, pageNumber, pageSize, totalPage, totalRow); } /** * 多次查询直到找到pageTotalDataSize条记录或者不够 * @param sql SQL语句 * @param batchPullDataSize 每次拉取数量 * @param pageTotalDataSize 页面最多显示条数 * @param filter 过滤器 */ private static List<Record> getRecords(String sql, int batchPullDataSize, int pageTotalDataSize, RecordFilter filter) { List<Record> resultList = new ArrayList<>(); int i=0; while(true){ int thisPage = i * batchPullDataSize; List<Record> dataList = Db.find(sql,thisPage,batchPullDataSize); int dbCountNumber = dataList.size(); dataList = filter.accept(dataList); resultList.addAll(dataList); if(resultList.size() >= pageTotalDataSize || dbCountNumber < batchPullDataSize){ break; } i++; } return resultList; } }
@Test public void testQueryListWithFilter(){ String sql = "SELECT * FROM transaction_log"; int pageNumber = 1; int pageSize = 3; int batchPullDataSize = 3; int pageTotalDataSize = 5; RecordFilter filter = (record)->{ if(record.getInt("success") == 1){ return true; } return false; }; Page<Record> query = QueryListWithFilter.query(sql, pageNumber, pageSize, batchPullDataSize, pageTotalDataSize, filter); System.out.println(query.getPageNumber()); System.out.println(query.getPageSize()); System.out.println(query.getTotalPage()); System.out.println(query.getTotalRow()); List<Record> list = query.getList(); list.forEach(record -> { System.out.println(record); }); }
-
区块链学习之Fabric的Java应用层搭建
2018-08-17 14:58:15一直在尝试搭建出一个Java应用层,好对外提供简单的接口以便将来能够实现一些自己的存储。 此篇博客记录时,CA容器没有单独起,而仅仅是在客户端读取已经生成好的CA文件来成功访问。下面说下一些步骤。 1. 搭建出...自从上篇Java-sdk跑通之后,今天已经是8/17号了,这期间干嘛了呢?一直在尝试搭建出一个Java应用层,好对外提供简单的接口以便将来能够实现一些自己的存储。
此篇博客记录时,CA容器没有单独起,而仅仅是在客户端读取已经生成好的CA文件来成功访问。下面说下一些步骤。
1. 搭建出一个Fabric环境。
1.1 这边需要注意1.3 用工具生成的私钥和证书,我们需要拷贝到工程中去。
channel-artifacts 和 crypto-config(这一个是这一期主要的)
2. 整个工程目录如图,只是一个简单的java项目
3. pom文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tc.fabric</groupId> <artifactId>FabricSdk</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> <dependency> <groupId>org.hyperledger.fabric-sdk-java</groupId> <artifactId>fabric-sdk-java</artifactId> <version>1.0.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
4. CommonUtils
package com.t.fabric; public class CommonUtils { //peer节点的CA文件路径 public static final String cryptoPeerPath = "crypto-config/peerOrganizations/"; //order节点的CA文件路径 public static final String cryptoOrderPath = "crypto-config/ordererOrganizations/"; //peer节点的CA文件路径 public static String peerFilePath = CommonUtils.class.getResource("/").getPath() + cryptoPeerPath; //order节点的CA文件路径 public static String orderFilePath = CommonUtils.class.getResource("/").getPath() + cryptoOrderPath; //org1组织的目录 public static final String org1Path = "org1.example.com/users/"; //org1组织的cert文件目录 public static final String org1CertFilePath = "@org1.example.com/msp/signcerts/"; //org1组织的Key文件目录 public static final String org1KeyFilePath = "@org1.example.com/msp/keystore/"; //org2组织的目录 public static final String org2Path = "org2.example.com/users/"; //org2组织的cert文件目录 public static final String org2CertFilePath = "@org2.example.com/msp/signcerts/"; //org2组织的Key文件目录 public static final String org2KeyFilePath = "@org2.example.com/msp/keystore/"; //链码名称 public static final String chainCodeName = "mycc"; //链码版本 public static final String chaincodeVersion = "1"; //channel名称 public static final String channelId = "mychannel"; //order名称 和 Fabrci-java-sdk保持一致 public static final String orderName = "orderer.example.com"; //peer0org1名称 和 Fabrci-java-sdk保持一致 public static final String peer0Org1Name = "peer0.org1.example.com"; //peer1org1名称 和 Fabrci-java-sdk保持一致 public static final String peer1Org1Name = "peer1.org1.example.com"; //peer0org2名称 和 Fabrci-java-sdk保持一致 public static final String peer0Org2Name = "peer0.org2.example.com"; //peer1org2名称 和 Fabrci-java-sdk保持一致 public static final String peer1Org2Name = "peer1.org2.example.com"; //order地址 public static final String orderLocation = "grpc://localhost:7050"; //peer0org1地址 public static final String peer0Org1Location = "grpc://localhost:7051"; //peer1org1地址 public static final String peer1Org1Location = "grpc://localhost:8051"; //peer0org2地址 public static final String peer0Org2Location = "grpc://localhost:9051"; //peer1org2地址 public static final String peer1Org2Location = "grpc://localhost:10051"; }
5.FabricUtils
package com.t.fabric; import org.apache.log4j.Logger; import org.hyperledger.fabric.sdk.*; import org.hyperledger.fabric.sdk.security.CryptoSuite; import java.util.Collection; import java.util.HashMap; import java.util.Map; import static java.nio.charset.StandardCharsets.UTF_8; /** * FabricUtils,暂时不关注CA方面的东西 */ public class FabricUtils { //日志记录 private static Logger logger = Logger.getLogger(FabricUtils.class); //CA客户端 public static HFClient client = null; public static CryptoSuite cs = null; public static HashMap<String, SOrg> orgHashMap=null; public static ChaincodeID cid = null; public static User peer0org1=null; public static void init()throws Exception{ cs = CryptoSuite.Factory.getCryptoSuite(); cid = ChaincodeID.newBuilder().setName(CommonUtils.chainCodeName).build(); client = HFClient.createNewInstance(); client.setCryptoSuite(cs); orgHashMap = OrgConfig.getSOrg(); peer0org1 = orgHashMap.get("org1").getAdmin(); client.setUserContext(peer0org1); } /* * 实现插入数据 * */ public static void instertFabcar(Channel channel, DataRecord data) throws Exception { TransactionProposalRequest req = client.newTransactionProposalRequest(); req.setChaincodeID(cid); req.setFcn("set"); req.setArgs(data.toStringArray()); Map<String, byte[]> tm2 = new HashMap<>(); //代码来自End2End tm2.put("HyperLedgerFabric", "TransactionProposalRequest:JavaSDK".getBytes(UTF_8)); tm2.put("method", "TransactionProposalRequest".getBytes(UTF_8)); tm2.put("result", ":)".getBytes(UTF_8)); req.setTransientMap(tm2); Collection<ProposalResponse> resps = channel.sendTransactionProposal(req); for (ProposalResponse resp : resps) { String payload = new String(resp.getChaincodeActionResponsePayload()); logger.debug("payload!!!!!!!: "+payload); } channel.sendTransaction(resps); } /* * 实现给定的Key查询数据 * */ public static void queryFabcar(Channel channel, String key) throws Exception { QueryByChaincodeRequest req = client.newQueryProposalRequest(); ChaincodeID cid = ChaincodeID.newBuilder().setName(CommonUtils.chainCodeName).build(); req.setChaincodeID(cid); req.setFcn("get"); req.setArgs(new String[] { key }); Collection<ProposalResponse> resps = channel.queryByChaincode(req); for (ProposalResponse resp : resps) { String payload = new String(resp.getChaincodeActionResponsePayload()); logger.debug("payload!!!!!!!: "+payload); } } }
6. OrgConfig
package com.t.fabric; import org.apache.commons.io.IOUtils; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.hyperledger.fabric.sdk.Enrollment; import java.io.*; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.spec.InvalidKeySpecException; import java.util.HashMap; /** * 模拟peer,order,admin,user等一些配置项 */ public class OrgConfig { /** * 获取Org组织信息, * 代码精简自End2End * @return */ public static HashMap<String,SOrg> getSOrg() throws Exception{ HashMap<String,SOrg> orgMap = new HashMap<>(); SOrg org1=new SOrg("Org1","Org1MSP"); org1.addPeerLocation(CommonUtils.peer0Org1Name,CommonUtils.peer0Org1Location); org1.addPeerLocation(CommonUtils.peer1Org1Name,CommonUtils.peer1Org1Location); org1.addOrdererLocation(CommonUtils.orderName,CommonUtils.orderLocation); SUser adminOrg1 = new SUser("Admin","Org1MSP"); SUser user1Org1 = new SUser("User1","Org1MSP"); adminOrg1.setEnrollment(new SampleStoreEnrollement(getKeyFile(adminOrg1.getName(),adminOrg1.getMspId()) ,getCertificateFile(adminOrg1.getName(),adminOrg1.getMspId()))); user1Org1.setEnrollment(new SampleStoreEnrollement(getKeyFile(user1Org1.getName(),user1Org1.getMspId()) ,getCertificateFile(user1Org1.getName(),user1Org1.getMspId()))); org1.addUser(adminOrg1); org1.addUser(user1Org1); org1.setAdmin(adminOrg1); SOrg org2=new SOrg("Org2","Org2MSP"); org2.addPeerLocation(CommonUtils.peer0Org2Name,CommonUtils.peer0Org2Location); org2.addPeerLocation(CommonUtils.peer1Org2Name,CommonUtils.peer1Org2Location); org2.addOrdererLocation(CommonUtils.orderName,CommonUtils.orderLocation); SUser adminOrg2 = new SUser("Admin","Org2MSP"); SUser user1Org2 = new SUser("User1","Org2MSP"); adminOrg2.setEnrollment(new SampleStoreEnrollement(getKeyFile(adminOrg2.getName(),adminOrg2.getMspId()) ,getCertificateFile(adminOrg2.getName(),adminOrg2.getMspId()))); user1Org2.setEnrollment(new SampleStoreEnrollement(getKeyFile(user1Org2.getName(),user1Org2.getMspId()) ,getCertificateFile(user1Org2.getName(),user1Org2.getMspId()))); org2.addUser(adminOrg2); org2.addUser(user1Org2); org2.setAdmin(adminOrg2); orgMap.put("org1",org1); orgMap.put("org2",org2); return orgMap; } /** * 获取对应用户的私钥Key * @param userName * @param mspId * @return */ public static PrivateKey getKeyFile(String userName,String mspId) throws Exception{ String tempPath = null; String fileName = null; String keyFile = null; if("Org1MSP".equals(mspId)){ tempPath = CommonUtils.peerFilePath +CommonUtils.org1Path + userName + CommonUtils.org1KeyFilePath; fileName = new File(tempPath).listFiles()[0].getName(); keyFile = tempPath + fileName; }else { tempPath = CommonUtils.peerFilePath + CommonUtils.org2Path + userName + CommonUtils.org2KeyFilePath; fileName = new File(tempPath).listFiles()[0].getName(); keyFile = tempPath + fileName; } //来源于ChannelTest return getPrivateKeyFromBytes(IOUtils.toByteArray(new FileInputStream(keyFile))); } /** * 获取对应用户的ceritificate证书 * @param userName * @param mspId * @return * @throws Exception */ public static String getCertificateFile(String userName,String mspId) throws Exception{ String tempPath = null; String fileName = null; String certFile = null; if("Org1MSP".equals(mspId)){ tempPath = CommonUtils.peerFilePath + CommonUtils.org1Path + userName + CommonUtils.org1CertFilePath; fileName = new File(tempPath).listFiles()[0].getName(); certFile = tempPath + fileName; }else { tempPath = CommonUtils.peerFilePath + CommonUtils.org2Path + userName + CommonUtils.org2CertFilePath; fileName = new File(tempPath).listFiles()[0].getName(); certFile = tempPath + fileName; } //来源于ChannelTest return new String(IOUtils.toByteArray(new FileInputStream(certFile)), "UTF-8"); } public static PrivateKey getPrivateKeyFromBytes(byte[] data) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, IOException { final Reader pemReader = new StringReader(new String(data)); final PrivateKeyInfo pemPair; try (PEMParser pemParser = new PEMParser(pemReader)) { pemPair = (PrivateKeyInfo) pemParser.readObject(); } PrivateKey privateKey = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getPrivateKey(pemPair); return privateKey; } static final class SampleStoreEnrollement implements Enrollment, Serializable { private final PrivateKey privateKey; private final String certificate; SampleStoreEnrollement(PrivateKey privateKey, String certificate) { this.certificate = certificate; this.privateKey = privateKey; } @Override public PrivateKey getKey() { return privateKey; } @Override public String getCert() { return certificate; } } }
7. SOrg
package com.t.fabric; import org.hyperledger.fabric.sdk.Peer; import org.hyperledger.fabric.sdk.User; import org.hyperledger.fabric_ca.sdk.HFCAClient; import java.util.*; /** * Java-SDK直接复制得来 */ public class SOrg { private String name; private String mspid; private HFCAClient caClient; //暂时未使用 private Map<String, User> userMap = new HashMap<String, User>(); private Map<String, String> peerLocations = new HashMap<String, String>(); private Map<String, String> ordererLocations = new HashMap<String, String>(); private Map<String, String> eventHubLocations = new HashMap<String, String>(); //暂时未使用 private Set<Peer> peers = new HashSet<Peer>(); //暂时未使用 private SUser admin; private String caLocation; //暂时未使用 private Properties caProperties = null; //暂时未使用 private SUser peerAdmin; //暂时未使用 private String domainName; //暂时未使用 public SOrg(String name, String mspid) { this.name = name; this.mspid = mspid; } public void setName(String name) { this.name = name; } public void setMspid(String mspid) { this.mspid = mspid; } public void setCaClient(HFCAClient caClient) { this.caClient = caClient; } public void setUserMap(Map<String, User> userMap) { this.userMap = userMap; } public void setPeerLocations(Map<String, String> peerLocations) { this.peerLocations = peerLocations; } public void setOrdererLocations(Map<String, String> ordererLocations) { this.ordererLocations = ordererLocations; } public void setEventHubLocations(Map<String, String> eventHubLocations) { this.eventHubLocations = eventHubLocations; } public void setPeers(Set<Peer> peers) { this.peers = peers; } public void setAdmin(SUser admin) { this.admin = admin; } public void setCaLocation(String caLocation) { this.caLocation = caLocation; } public void setCaProperties(Properties caProperties) { this.caProperties = caProperties; } public void setPeerAdmin(SUser peerAdmin) { this.peerAdmin = peerAdmin; } public void setDomainName(String domainName) { this.domainName = domainName; } public String getName() { return name; } public String getMspid() { return mspid; } public HFCAClient getCaClient() { return caClient; } public Map<String, User> getUserMap() { return userMap; } public Map<String, String> getPeerLocations() { return peerLocations; } public Map<String, String> getOrdererLocations() { return ordererLocations; } public Map<String, String> getEventHubLocations() { return eventHubLocations; } public Set<Peer> getPeers() { return peers; } public SUser getAdmin() { return admin; } public String getCaLocation() { return caLocation; } public Properties getCaProperties() { return caProperties; } public SUser getPeerAdmin() { return peerAdmin; } public String getDomainName() { return domainName; } public void addPeerLocation(String name, String location) { peerLocations.put(name, location); } public void addOrdererLocation(String name, String location) { ordererLocations.put(name, location); } public void addEventHubLocation(String name, String location) { eventHubLocations.put(name, location); } public String getPeerLocation(String name) { return peerLocations.get(name); } public String getOrdererLocation(String name) { return ordererLocations.get(name); } public String getEventHubLocation(String name) { return eventHubLocations.get(name); } public void addUser(SUser user) { userMap.put(user.getName(), user); } }
8.SUser
package com.t.fabric; import org.hyperledger.fabric.sdk.Enrollment; import org.hyperledger.fabric.sdk.User; import java.util.HashSet; import java.util.Set; /** * SUser的构造用crypton工具生成的证书本地读取来生成 */ public class SUser implements User { private String userName; private String mspid; private Enrollment enrollment; public SUser(String userName, String mspid) { this.userName = userName; this.mspid = mspid; } public String getName() { return userName; } public Set<String> getRoles() { return new HashSet<String>(); } public String getAccount() { return ""; } public String getAffiliation() { return ""; } public Enrollment getEnrollment() { return this.enrollment; } public String getMspId() { return this.mspid; } public void setEnrollment(Enrollment enrollment) { this.enrollment = enrollment; } }
9. DataRecord
package com.t.fabric; public class DataRecord { private String key; private String value; public DataRecord(String key, String value) { this.key = key; this.value = value; } public String getKey() { return key; } public String getValue() { return value; } public void setKey(String key) { this.key = key; } public void setValue(String value) { this.value = value; } public String[] toStringArray() { return new String[] {this.getKey(),this.getValue()}; } @Override public String toString() { return "Data: key = "+key+" value = " +value; } }
10 .Insert
package com.t.fabric; import org.apache.log4j.Logger; import org.hyperledger.fabric.sdk.Channel; public class TestFabricInsert { private static Logger logger=Logger.getLogger(TestFabricInsert.class); public static void main(String[] args) throws Exception{ FabricUtils.init(); DataRecord dataRecord = new DataRecord("data","{name:\"testName\",address:\"testAddress\"}"); testInsert(dataRecord); } public static void testInsert(DataRecord record) throws Exception { System.out.println("test insert"); Channel channel = FabricUtils.client.newChannel(CommonUtils.channelId); channel.addPeer(FabricUtils.client.newPeer(CommonUtils.peer0Org1Name, CommonUtils.peer0Org1Location)); channel.addOrderer(FabricUtils.client.newOrderer(CommonUtils.orderName, CommonUtils.orderLocation)); channel.initialize(); FabricUtils.instert(channel,record); } }
11 .query
package com.t.fabric; import org.apache.log4j.Logger; import org.hyperledger.fabric.sdk.Channel; public class TestFabricQuery { private static Logger logger=Logger.getLogger(TestFabricQuery.class); public static void main(String[] args) throws Exception{ DataRecord dataRecord = new DataRecord("data",""); FabricUtils.init(); testQuery(dataRecord); } public static void testQuery(DataRecord record) throws Exception { logger.debug("测试Fabric 查询功能"); Channel channel = FabricUtils.client.newChannel(CommonUtils.channelId); channel.addPeer(FabricUtils.client.newPeer(CommonUtils.peer0Org1Name, FabricUtils.orgHashMap.get("org1").getPeerLocation(CommonUtils.peer0Org1Name))); channel.addOrderer(FabricUtils.client.newOrderer(CommonUtils.orderName, FabricUtils.orgHashMap.get("org1").getOrdererLocation(CommonUtils.orderName))); channel.initialize(); FabricUtils.query(channel, record.getKey()); } }
以上就是全部的精简代码了。但是如果直接运行以上代码的话会有一些环境方面的问题,我这边遇到的就是tls问题....
下面是我打开orderer的日志时发现的问题(表明不是一个合法的tls访问,个人推测):
1.错误1
grpc: Server.Serve failed to complete security handshake from "172.18.0.1:41678": tls: first record does not look like a TLS handshake
2. 伴随错误1出现在java日志里的是错误2:
Caused by: io.netty.handler.codec.http2.Http2Exception: First received frame was not SETTINGS. Hex dump for first 5 bytes: 1503010002
暂时解决方案就是关闭tls.....
1. 在e2e/base内的两个文件里面分别关掉
docker-compose-base.yaml ---- > ORDERER_GENERAL_TLS_ENABLED=false
peer-base.yaml ---- > CORE_PEER_TLS_ENABLED=false
2.在e2e/docker-compose-cli.yaml内的文件中关掉 CORE_PEER_TLS_ENABLED=false
然后重新部署环境。
需要额外注意的是,搭建步骤内的4.2 / 5.2 等涉及到tls的参数设置 --tls true 去掉。
insert输出日志:
DEBUG sdk.Channel - Creating channel: mychannel, client context Admin DEBUG sdk.Channel - Channel mychannel adding ordererorderer.example.com, url: grpc://localhost:7050 DEBUG sdk.Channel - Channel mychannel initialize shutdown false DEBUG sdk.Channel - getConfigurationBlock for channel mychannel DEBUG sdk.Channel - getConfigurationBlock for channel mychannel ... DEBUG sdk.OrdererClient - resp status value: 0, resp: UNKNOWN, type case: BLOCK DEBUG sdk.OrdererClient - resp status value: 200, resp: SUCCESS, type case: STATUS DEBUG sdk.Channel - Channel mychannel getLatestBlock returned status 200 DEBUG sdk.Channel - Last config index is 2 DEBUG transaction.ProtoUtils - ChannelHeader: type: DELIVER_SEEK_INFO, version: 1, Txid: 4104f7b6af57f3a9176ed9e6ce5a506304ef9d35f92d675eb8d64335ce43236d, channelId: mychannel, epoch 0 ... .... DEBUG sdk.Channel - Channel mychannel getConfigurationBlock returned DEBUG sdk.Channel - Channel mychannel Got config block getting MSP data and anchorPeers data DEBUG sdk.Channel - Channel mychannel loadCACertificates DEBUG sdk.Channel - loading certificates for MSP : Org2MSP DEBUG sdk.Channel - loading certificates for MSP : Org1MSP DEBUG sdk.Channel - loading certificates for MSP : OrdererMSP DEBUG sdk.Channel - Channel mychannel loadCACertificates completed DEBUG sdk.Channel - Eventque started null DEBUG sdk.Channel - 0 eventhubs initialized DEBUG sdk.Channel - Channel mychannel registerTransactionListenerProcessor starting DEBUG sdk.Channel - Channel mychannel blockListener 32a8ef34-46b6-4d3e-af61-903c2e1f27ba starting DEBUG sdk.Channel - Channel mychannel registerTransactionListenerProcessor completed DEBUG sdk.Channel - Channel mychannel initialized DEBUG transaction.ProposalBuilder - transientMap('result', ':)')) DEBUG transaction.ProposalBuilder - transientMap('method', 'TransactionProposalRequest')) DEBUG transaction.ProposalBuilder - transientMap('HyperLedgerFabric', 'TransactionProposalRequest:JavaSDK')) DEBUG transaction.ProtoUtils - ChannelHeader: type: ENDORSER_TRANSACTION, version: 1, Txid: 7f0dc2e2ef4beca32e50d8115fd154e1347c4e8e85ccc6ea2138013e53d731f9, channelId: mychannel, epoch 0 DEBUG transaction.ProposalBuilder - ChaincodeInvocationSpec type: GOLANG, chaincode name: mycc, chaincode path: , chaincode version: args("set", "data", "{name:"testName",address:"testAddress"}") DEBUG transaction.ProtoUtils - SignatureHeader: nonce: af86713b93d098b8ec2ef7380a2bb584c8355c393ea0d2ab, User:Admin, MSPID: Org1MSP, idBytes: 427d0ae5efdfff9a663a66df1643f9c21130fc4b3b0f668e6d5e8df4cf43a2d6 DEBUG sdk.Channel - Channel mychannel send proposal to peer peer0.org1.example.com at url grpc://localhost:7051 DEBUG sdk.Peer - peer.sendProposalAsync name: peer0.org1.example.com, url: grpc://localhost:7051 .. .. DEBUG sdk.Channel - Channel mychannel got back from peer peer0.org1.example.com status: 200, message: OK DEBUG fabric.FabricUtils - payload!!!!!!!: DEBUG sdk.Channel - Channel mychannel sending transaction to orderer(s) with TxID 7f0dc2e2ef4beca32e50d8115fd154e1347c4e8e85ccc6ea2138013e53d731f9 DEBUG sdk.Orderer - Order.sendTransaction name: orderer.example.com, url: grpc://localhost:7050 .... DEBUG sdk.Channel - Channel mychannel successful sent to Orderer transaction id: 7f0dc2e2ef4beca32e50d8115fd154e1347c4e8e85ccc6ea2138013e53d731f9
query输出日志:
DEBUG helper.Config - Loading configuration from /home/dell/go/javaproject/FabricSdk/config.properties and it is present: false WARN helper.Config - Failed to load any configuration from: config.properties. Using toolkit defaults DEBUG sdk.HFClient - Setting user context to MSPID: Org1MSP user: Admin DEBUG fabric.TestFabricQuery - 测试Fabric 查询功能 DEBUG sdk.Channel - Creating channel: mychannel, client context Admin DEBUG sdk.Channel - Channel mychannel adding ordererorderer.example.com, url: grpc://localhost:7050 DEBUG sdk.Channel - Channel mychannel initialize shutdown false DEBUG sdk.Channel - getConfigurationBlock for channel mychannel DEBUG sdk.Channel - getConfigurationBlock for channel mychannel DEBUG transaction.ProtoUtils - ChannelHeader: type: DELIVER_SEEK_INFO, version: 1, Txid: 7341e25d471cbc614a1a996f896462286a20f9ba78fd72b619fdedfed674255f, channelId: mychannel, epoch 0 DEBUG sdk.Orderer - Order.sendDeliver name: orderer.example.com, url: grpc://localhost:7050 .... DEBUG sdk.OrdererClient - resp status value: 0, resp: UNKNOWN, type case: BLOCK DEBUG sdk.OrdererClient - resp status value: 200, resp: SUCCESS, type case: STATUS DEBUG sdk.Channel - Channel mychannel getLatestBlock returned status 200 .. DEBUG transaction.ProtoUtils - ChannelHeader: type: DELIVER_SEEK_INFO, version: 1, Txid: 21046ed568a93549a16224a977423351d5d7ef0ffe66455210929ab7acc6480f, channelId: mychannel, epoch 0 DEBUG sdk.Orderer - Order.sendDeliver name: orderer.example.com, url: grpc://localhost:7050 ... .. DEBUG sdk.Channel - Channel mychannel getConfigurationBlock returned DEBUG sdk.Channel - Channel mychannel Got config block getting MSP data and anchorPeers data DEBUG sdk.Channel - Channel mychannel loadCACertificates DEBUG sdk.Channel - loading certificates for MSP : Org2MSP DEBUG sdk.Channel - loading certificates for MSP : Org1MSP DEBUG sdk.Channel - loading certificates for MSP : OrdererMSP DEBUG sdk.Channel - Channel mychannel loadCACertificates completed DEBUG sdk.Channel - Eventque started null DEBUG sdk.Channel - 0 eventhubs initialized DEBUG sdk.Channel - Channel mychannel registerTransactionListenerProcessor starting DEBUG sdk.Channel - Channel mychannel blockListener 3d8076a4-fca7-466a-904f-5c104c96ea1f starting DEBUG sdk.Channel - Channel mychannel registerTransactionListenerProcessor completed DEBUG sdk.Channel - Channel mychannel initialized DEBUG transaction.ProtoUtils - ChannelHeader: type: ENDORSER_TRANSACTION, version: 1, Txid: a08572d26702b2bdafe0ac53039e21faadb36e9a0640c9169dd66552af0a1994, channelId: mychannel, epoch 0 DEBUG transaction.ProposalBuilder - ChaincodeInvocationSpec type: GOLANG, chaincode name: mycc, chaincode path: , chaincode version: args("get", "data") DEBUG transaction.ProtoUtils - SignatureHeader: nonce: ebc13657e548bdb8319e689baa9c263e6c8fa712835828b8, User:Admin, MSPID: Org1MSP, idBytes: 427d0ae5efdfff9a663a66df1643f9c21130fc4b3b0f668e6d5e8df4cf43a2d6 DEBUG sdk.Channel - Channel mychannel send proposal to peer peer0.org1.example.com at url grpc://localhost:7051 DEBUG sdk.Peer - peer.sendProposalAsync name: peer0.org1.example.com, url: grpc://localhost:7051 .... .... DEBUG sdk.Channel - Channel mychannel got back from peer peer0.org1.example.com status: 200, message: OK DEBUG fabric.FabricUtils - payload!!!!!!!: {name:"testName",address:"testAddress"}
最后贴一下自己的chaincode001(其实就是以前测试的一个简单的chaincode)
-
从 HAL层 到java应用层重写mini6410 led功能
2012-08-16 11:07:48从HAL层到java应用层重写mini6410 led功能 记录了我从HAL层到应用层如何把led这个设备控制实现的过程。如果有遗漏或者错误,请各位高手指点。 这个事例通过Manager的形式调用Service,但是将LedService加入进...从HAL层到java应用层重写mini6410 led功能
记录了我从HAL层到应用层如何把led这个设备控制实现的过程。如果有遗漏或者错误,请各位高手指点。
这个事例通过Manager的形式调用Service,但是将LedService加入进了SystemSeivice,生成的libandroid_server.so文件是系统启动自动加载的,在应用程序中直接调用ServiceManager找到对应的aidl就可以使用。
led驱动的代码就不说了,以后有空再实现,
第一步,查看linux驱动设备是否工作正常。之后所有的一切,都是在这个leds设备的基础上操作完成的,所以,检查这个设备是不是有用成为了一个很重要的关键。
首先,用adb shell查看android dev下的目录,发现有leds这个设备:
ls -l /dev/leds 这个设备文件就是android中间层用来操作Linux底层led设备的。
回到android2.3.4源代码目录,在 external目录底下建立testDev目录,在下面分别建立Android.mk 和 testDev.c文件
在testDev.c这个文件里,首先写一个测试程序用来测试Leds这个文件设备能否正常运行;
testDev.c,打开设备关键是ioctl这个函数,其中,第二个参数用来控制是否打开一个led设备,第三个参数用来控制打开的是那个led。(testDev.c 和 Android.mk这2个程序可以见附件。)
全部写完之后,用./build-android编译一下,编译的时候,可以指定特定模块编译,这样比较节省时间。也可以用mmm这个命令编译,将build-android中的make改成mmm就行,这样编译了之后product的名称就还是mini6410了,库就不会找不到。编译之后android的out/target/product/mini6410/system/bin/ 目录下面会生成一个叫 testDev的文件,然后将开发板开机,用adb push out/target/product/mini6410/system/bin/testDev system/bin/ 把testDev push到开发板上面去,然后用adb shell命令进入到system/bin/目录下面,运行./testDev (如果这样运行不了,直接在任意目录输入 testDev 就行) 就可以检测leds这个设备是否运行正常。
第二步,为linux的led驱动提供android的HAL层。
HAL是android的硬件逻辑层,在这里,主要是为framework层提供一层Led的操作接口。直接操作leds设备的函数在第一步已经指明了,就是ioctl函数,但是,如何将这个功能增加到android的框架里呢?
首先,增加hardware/libhardware/modules/目录下的mydevice目录,然后在这个目录下再新建Led目录,在led目录下,分别建立led.c和Android.mk文件在mydevice这个目录下,也需要建立Android.mk文件用来搜索mydevice目录下的每个驱动设备目录。在hardware/libhardware/include/hardware 下,建立hardware目录,在下层建立mydevice/led.h,该文件用来实现一些module_id之类的宏和结构体,这里比较重要的是DEVICE_NAME一定要写对,这个就是程序需要读取的设备,还有MODULE_NAME的取名要跟Android.mk里面的LOCAL_MODULE前缀一样,否则程序加载的时候会找不到。硬件结构体是继承hw_device_t这个结构的,在这个结构体里,可以定义leds设备的fd,和这个设备需要操作的一些结构函数,比如这边就增加了set_led,用来控制Led设备的。
最后还要修改hardware/libhardware/ Android.mk,将增加好的led结构添加进去。
include $(addsuffix /Android.mk, $(addprefix $(LOCAL_PATH)/, \
modules/gralloc \
modules/mydevice \ --》增加这行
tests \
))
然后编译一下,out/target/product/mini6410/system/lib/hw目录下会生成led.default.so这个文件,编译就成功了。本层生成一个so文件,作为Android HAL层的Stub。按照Android HAL的要求,此文件必须放在固定的目录下面,并且具有特定的文件名。
规则如下:
# HAL module implemenation, not prelinked and stored in
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
本例中:#defineLED_HARDWARE_MODULE_ID "led"
所以生成:system/lib/hw/led.default.so
在hardware.c文件中有hw_get_module函数有调用hal层.so文件的名字规则!
第三步,增加jni底层对上层的应用接口。
在这一步当中,封装了底层的.c的接口函数,使得上层Java可以调用, 做到这一步,java应用层应该也可以调用这一步生成的.so,友善提供的.so文件应该就是做到这一步生成的。
这一步当中,首先添加framework/base/services/jni目录下的com_android_server_DeviceService.cpp文件,这个文件用来动态加载jni的接口函数。为java上层提供帮助。Method_table这个表提供了底层到Java层的映射,
static const JNINativeMethod method_table[]=
{
{"openLed", "()Z", (void*)led_init}, --》第一个是java层可以调用的函数名,第二个是函数签名,第三个是本层函数名
{"set_Led", "(II)I", (void*)setLed},
};
java层调用映射之后的字符就可以完成对底层的通讯了。全部写完之后,还要在frameworks/base/services/jni/onload.cpp这个文件当中将method_table这个表加载进系统里(JNI_OnLoad),然后在Android.mk下增加com_android_server_DeviceService.cpp文件就可以编译了。
LOCAL_SRC_FILES:= \
com_android_server_AlarmManagerService.cpp \
com_android_server_BatteryService.cpp \
com_android_server_InputManager.cpp \
com_android_server_LightsService.cpp \
com_android_server_PowerManagerService.cpp \
com_android_server_SystemServer.cpp \
com_android_server_UsbService.cpp \
com_android_server_VibratorService.cpp \
com_android_server_location_GpsLocationProvider.cpp \
com_android_server_DeviceService.cpp \ --》增加这行。
onload.cpp
第四步,用aidl增加java services。
Aidl是一个工具,他可以用来增加java的services,首先,在frameworks/base/core/java/android/os/路径下增加IDeviceService.aidl接口,然后,在 frameworks/base/Android.mk里面增加这个aidl文件,编译一下,这个时候就会生成stub,新增frameworks/base/services/java/com/android/server这个路径下的DeviceService.java,这个java文件里需要继承刚才用aidl工具生成出来的IDeviceService.Stub,之后对jni接口进行再一次封装。在frameworks/base/services/java/com/android/servier/SystemServer.java里面需要增加这个服务,之后重新编译程序就可以了。
第五步,在java应用层调用底层编译好的java service服务。
用eclipse新建一个java项目,然后在这个新建的工程里面把操作的button做好,这个界面由于只是测试程序,所以就做了一个button,这个button的功能就是依次打开和关闭led灯
。
资源下载:用到的程序
http://download.csdn.net/download/liwendovo/4503785 -
java应用层协议解析和C中的数据协议解析比较
2017-08-22 21:55:17最近在学习Java的过程中突然想到一个问题:对于C/C++中的数据结构可以非常方便地用struct来封装应用层协议,那么Java中如何做呢? 比如,某应用层协议这样: | 4B | 8B | 4B | 8B | NB最近在学习Java的过程中突然想到一个问题:对于C/C++中的数据结构可以非常方便地用struct来封装应用层协议,那么Java中如何做呢?
比如,某应用层协议这样:
| 4B | 8B | 4B | 8B | NB | 4B |
头部 时间 类型 长度 数据 尾部
在C/C++里可以非常方便地用一个结构体包含:
struct DataProtocal{
int header;
short year;
short month;
short day;
int type;
float len;
char data[];
int end;
}
收到数据之后,直接简单粗暴地强制类型转换:DataProtocal* data = (DataProtocal*)receive;然后就可以很简单地数据结构性输出了。
Java中目前想到一种:就是分隔插入的方式,就是把协议字段的各部分之间加上分隔符,这样做比C++确实是麻烦了不止一倍。这个方法中注意,最简单的办法是分段提取,但是不提取数据字段,也就是说把协议头段和尾段单独提取解析,然后再去校验数据字段。
今天先想到这里吧,后续有新的办法,再贴出来
-
从HAL层到java应用层重写mini6410 led功能
2014-01-26 15:51:34重写 HAL层到java应用层的 hello : 编译 hello.default.so 的时候,第一次没有编译成功,是因为Amdroid.mk文件中没有添加编译hello文件夹的内容。添加了就好了。 nclude $(addsuffix /Android.mk, $... -
Android 键盘驱动移植呆板手册(从kernel到Java应用层简单描述)
2013-09-15 16:17:43Android 键盘驱动移植呆板手册 --write by fpga_dsp (以前一直没有写博客习惯,近来发现博客不仅能够和别人分享知识,同时也是自己的笔记,所以计划将多年来的一些技术经验,拿出来和大家分享一下。... -
Android camera摄像头对焦,zoom的通知事件回调,告诉java应用层已经对焦完成
2012-11-22 15:34:02在vendor/sec/sec_proprietary/smdkc110/libcamera/SecCameraHWInterface.cpp中,当对硬件设置完毕后,通知packages/apps/Camera/src/com/android/camera/Camera.java,zoom已经完成。 status_t ... -
android 摄像头对焦,zoom的通知事件回调,告诉java应用层已经对焦完成
2010-06-14 14:33:00在vendor/sec/sec_proprietary/smdkc110/libcamera/SecCameraHWInterface.cpp中,当对硬件设置完毕后,通知packages/apps/Camera/src/com/android/camera/Camera.java,zoom已经完成。status_t CameraHardwareSec::... -
Java三层架构实际应用
2018-09-28 20:31:11应用:利用Java三层架构以及MVC完成页面商品显示 1、明确业务逻辑 想出三层架构如何实现 2、导入相关的jar包以及配置文件和建立对应的架构包 3、完成除了三层架构之外的domain包和utils包的实现 4、完成Web层的... -
java三层框架基础搭建应用
2020-07-29 19:53:07java三层框架基础搭建应用: 在src文件夹下建立如下系列包名及类 view视图层调用service业务逻辑层代码 service层调用dao持久数据层代码: dao层方法搭建: dao数据层MySQL数据库连接及测试代码: ... -
Android Jni层调用应用层(Java)的方法
2015-12-28 12:16:07android的应用层java能够调用jni层的函数,那么jni层也做了能够调用应用层java的方法,其实这个东西还真的涉及程序的编译原理方面的,不过这个直接说就是利用了反射,之前见过最多的是java反射java类中的方法,我的博客中... -
在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务
2011-07-02 14:35:20我们在Android系统增加硬件服务的目的是为了让应用层的APP能够通过Java接口来访问硬件服务。那么, APP如何通过Java接口来访问Application Frameworks层提供的硬件服务呢?在这一篇文章中,我们将在Android系统的... -
Java EE应用程序的层次
2012-06-05 12:48:25Java EE应用程序的层次Sun给出的Java EE规范和相关文档把Java EE平台描述为一个由3个层次构成的分布式应用程序环境: 客户层、业务层和企业信息系统(Enterprise Information System,EIS)层或数据层。尽管这是一个... -
MediaRecorder流程分析 java层到stagefright层
2012-11-08 17:41:17MediaRecorder流程分析 MediaRecorder流程分析 ...java应用层主要是一些接口的调用,它并没有具体功能代码的实现,java应用层的代码路径为: android/packages/apps/SoundRecorder/src/com/android/ -
JAVA应用案例
2019-07-12 11:37:36为了对JAVA基础知识进行复习并实战使用,本课程讲解了如何使用JAVA知识实现反射、RPC、SOCKET、文件、JSON、二维码、JAVA MAIL、加密等案例。 本课程对每个知识的讲解都带有核心的知识点复习,以及详尽的案例讲解。... -
android 用eclipse调试framework java层或者应用层代码
2012-12-11 16:05:57下面的方法,调试中无法查看变量值,推算是由于代码不完整,并且包含错误,所以下面的方法只针对流程调试。...2.其次要有你当前手机版本的framework层或者app层源码,并且保持一致,否则会出现代码错位。 3.直接导 -
使用Java代码在应用层获取Android系统属性
2016-05-11 18:35:45之前使用Native代码的property_get()/property_set()来获取Android系统属性,现在需要改写到Java上面,但是Java里面的getProperty()/setProperty()所操作的属性与上面的是不同的。好在Google提供了一个隐藏类android... -
Android中在native层对java层应用程序发送广播方法及原理
2017-04-25 12:22:03Android中在native层对java层应用程序发送广播方法及原理详解Android从native发送数据给上层应用接收,常用的有JNI的形式,同样用广播也可以实现,本文正是基于广播实现native与上层应用通信,参考Android的Native... -
为Android系统内置Java应用程序测试Application Frameworks层的硬件服务
2016-09-29 18:16:44我们在Android系统增加硬件服务的目的是为了让应用层的APP能够通过Java接口来访问硬件服务。那么, APP如何通过Java接口来访问Application Frameworks层提供的硬件服务呢?在这一篇文章中,我们将在Android系统的... -
为Android 系统内置Java 应用程序测试Application Frameworks 层的硬件服务
2013-10-23 10:38:49系统增加硬件服务的目的是为了让应用层的APP 能够通过Java接口来访问硬件服务。那么, APP 如何通过Java 接口来访问ApplicationFrameworks 层提供的硬件服务呢?在这一篇文章中,我们将在Android 系统的应用层... -
Java Web---HTTP应用层协议
2016-06-28 09:12:17一、网络通讯1....TCP传输层协议,HTTP应用层协议。2.HTTP协议(1)超文本传输协议(2)通过客户端IE访问自定义服务端演示请求规则(3)Http1.0和Http1.1的区别:–》1.0在一次连接断开中只有一个请求和应答– -
java应用于二叉树层次输出和之字形输出的非递归实现
2016-12-08 17:02:53下面实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。 import java.util.ArrayList; import java.util.... -
java应用技术5
2015-11-06 15:36:55网络模型:应用层,表示层,会话层,传输层,网络层,数据连接层,物理层。 应用层,表示层,会话层都是应用层(TCP/IP协议),传输层是传输层。网络层为IP层,数据链接层和物理层是网络接口层。 网络编程... -
用TikeSwing框架开发Java应用的表现层程序
2005-06-28 09:32:00JavaWorld发表的一篇文章介绍了如何借助TikeSwing框架开发Java应用的表现层程序。TikeSwing是一个开源的Swing框架,提供了高层级的“模型-视图-控制器”(MVC)架构,并且简化了Swing的使用。TikeSwing框架支持普通... -
Java多层应用中Exception的处理
2005-04-30 22:23:00作了一段时间的多层应用的开发了,觉得在异常处理上一直在兜圈子。最初的做法就是用printStackTrace函数显示信息,后来使用System.out.println自己编写一些容易懂得文字输出,后来用了log库来记录。这么做的话对于... -
Android分应用层、应用框架层、系统应用层、核心层
2018-08-22 11:27:29应用层(Java Application),包括了Android各种应用程序 应用框架层(Java Frameworks),是Google发布的核心应用所使用的API框架 系统运行库层(User Libraries),包含了手机系统平台必须的C/C++核心库、... -
Java 应用性能调优实践
2016-11-23 11:30:00Java 应用性能优化是一个老生常谈的话题,笔者根据个人经验,将 Java 性能优化分为 4 个层级:应用层、数据库层、框架层、JVM 层。通过介绍 Java 性能诊断工具和思路,给出搜狗商业平台的性能优化案例以供参考。 ...