Java实现区块链小实例

通过本文,你将可以做到:

创建自己的区块链
理解 hash 函数是如何保持区块链的完整性的
如何创造并添加新的块
多个节点如何竞争生成块
通过浏览器来查看整个链
所有其他关于区块链的基础知识
但是,对于比如工作量证明算法(PoW)以及权益证明算法(PoS)
这类的共识算法文章中将不会涉及。同时为了让你更清楚得查看
区块链以及块的添加,我们将网络交互的过程简化了,关于 P2P 
网络比如“对等网络”等内容将在将来的文章中讲解。

让我们开始吧!

设置

我们假设你已经具备一点 Java 语言的开发经验,以及maven项目构建经验。
在安装和配置 Java 开发环境后之后,我们新建maven项目,在pom中增加一些依赖:
<!--超小型web框架-->
  <dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>${spark.version}</version>
  </dependency>
Spark-web Framework是一个基于jetty的超小型框架,我们用它来写http访问的请求处理。
 <dependency>
   <groupId>commons-codec</groupId>
   <artifactId>commons-codec</artifactId>
   <version>${commons.codec.version}</version>
 </dependency>
这个通用包拥有几乎所有加解密算法及常规操作
 <dependency>
 <groupId>com.google.code.gson</groupId>
 <artifactId>gson</artifactId>
 <version>${gson.version}</version>
 </dependency>
Google的json包,当然你可以使用你喜欢的其他json包。

最后,增加log相关的包
<!--log start-->
<dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <version>${log4j.version}</version>
 </dependency>
<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 <version>${slf4j.version}</version>
 </dependency>
<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-log4j12</artifactId>
 <version>${slf4j.version}</version>
 </dependency>
<!-- log end -->
 相关版本属性设置
<properties>
<commons.codec.version>1.9</commons.codec.version>
<spark.version>2.6.0</spark.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.17</log4j.version>
<gson.version>2.8.2</gson.version>
</properties>

数据模型 read more

try-finally中return的执行先后顺序

关于try-finally中return谁先执行,刚开始只记得是一个面试题;
今天遇到了较类似的情况,于是写了个小的事例进行测试
public String getString() {
    try {
      System.out.println("try");
      return "try中return";
    } finally {
      System.out.println("finally");
      return "finally中return";
    }
}
以上是try和finally都有return的情况;
执行结果为:

try
finally
finally中return

如果注释掉finally中的return,执行结果为:

try
finally
try中return

总结:
无论try中是否有return语句,finally内的语句都会执行

Idea自定义类注解

1.点击左上角file找到Settings...并点击
2.搜索file and Code Templates
3.选中file选项卡,找到Class并点击,可看到当前生成类的model
4.在public class ..这行上面添加自己想要的注解model
下面是我的当前model
/**
 * 描述:
 *    ${DESCRIPTION}
 * @author ${USER}
 * @create ${YEAR}-${MONTH}-${DAY} ${TIME}
 */
由于本人方法注解一直使用系统默认样式,所以并没有对方法注解进行自定义处理

Java网络编程

package com.net;

import java.io.*;
import java.net.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JavaNet {

	/**
	 * 根据域名获取IP
	 * 
	 * @param realmName 域名
	 * @return IP
	 */
	public static String GetIP(String realmName) {
		InetAddress address;
		try {
			address = InetAddress.getByName(realmName);
		} catch (UnknownHostException e) {
			return null;
		}
		return address.getHostAddress();
	}

	/**
	 * 获取端口是否被占用
	 * 
	 * @param host IP
	 * @param port 端口号
	 * @return 端口的使用状态
	 */
	public static boolean PortIsUsed(String host, int port) {
		try {
			Socket socket = new Socket(host, port);
			return true;
		} catch (UnknownHostException e) {
		} catch (IOException e) {
		}
		return false;
	}

	/**
	 * 获取本机IP
	 * 
	 * @return 本机IP地址
	 * @throws UnknownHostException 异常
	 */
	public static String LocalHostAddress() throws UnknownHostException {
		InetAddress address = InetAddress.getLocalHost();
		return address.getHostAddress();
	}

	/**
	 * 获取本机的主机名
	 * 
	 * @return 主机名
	 * @throws UnknownHostException 异常
	 */
	public static String LocalHostName() throws UnknownHostException {
		InetAddress address = InetAddress.getLocalHost();
		return address.getHostName();
	}

	/**
	 * 获取远程文件大小
	 * 
	 * @param fileLocal 文件路径
	 * @return 文件大小,单位为bytes
	 * @throws IOException 异常
	 */
	public static int getHostFileSize(String fileLocal) throws IOException {
		int size;
		URL url = new URL(fileLocal);
		URLConnection conn = url.openConnection();
		size = conn.getContentLength();
		conn.getInputStream().close();
		return size;
	}

	/**
	 * 获取文件的最后修改日期
	 * 
	 * @param fileLocal 文件路径
	 * @return 最后修改日期
	 * @throws IOException 异常
	 */
	public static Date getFileLastEditDate(String fileLocal) throws IOException {
		URL url = new URL(fileLocal);
		URLConnection conn = url.openConnection();
		conn.setUseCaches(false);
		long timestamp = conn.getLastModified();
		conn.getInputStream().close();
		Date date = new Date(timestamp);
		return date;
	}

	/**
	 * 网页抓取
	 * 
	 * @param local 抓取的路径
	 * @param htmlName html名 可为空
	 * @return 抓取的结果
	 * @throws IOException 异常
	 */
	public static String getHtmlText(String local, String htmlName) throws IOException {
		if (!local.contentEquals("http://"))
			return "local error,like http://www.xxx.com";
		if (htmlName == null)
			htmlName = "data.html";
		URL url = new URL(local);
		BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
		BufferedWriter writer = new BufferedWriter(new FileWriter(htmlName));
		String line;
		StringBuffer stringBuffer = new StringBuffer();
		while ((line = reader.readLine()) != null) {
			stringBuffer.append("\n" + line);
			writer.write(line);
			writer.newLine();
		}
		String result = stringBuffer.toString().replaceFirst("\n", "");
		reader.close();
		writer.close();
		return result;
	}

	/**
	 * 获取相应头信息
	 * 
	 * @param local 请求路径 携带http://
	 * @return 响应头信息
	 * @throws IOException 异常
	 */
	public static Map getHeaders(String local) throws IOException {
		URL url = new URL(local);
		URLConnection conn = url.openConnection();
		Map headers = conn.getHeaderFields();
		return headers;
	}

	/**
	 * 解析URL
	 * 
	 * @param local 请求路径
	 * @return url信息
	 * @throws MalformedURLException 异常
	 */
	public static Map getURLInfo(String local) throws MalformedURLException {
		URL url = new URL(local);
		Map map = new HashMap();
		map.put("url", url.toString());
		// 协议
		map.put("protocol", url.getProtocol());
		// 文件名
		map.put("file", url.getFile());
		// 主机
		map.put("host", url.getHost());
		// 路径
		map.put("path", url.getPath());
		// 端口号
		map.put("port", url.getPort());
		// 默认端口号
		map.put("defaultPort", url.getDefaultPort());
		return map;
	}

}


Java发送邮件

		String to = "收件人邮箱";
		String host = "smtp.163.com";
		String name = "发件人邮箱";
		String pwd = "发件人邮箱密码";
		//获取系统属性
		Properties properties = System.getProperties();
		//设置邮箱服务器
		properties.setProperty("mail.smtp.host", host);
		properties.put("mail.smtp.auth", "true");
		try {
			MailSSLSocketFactory sf = new MailSSLSocketFactory();
			sf.setTrustAllHosts(true);
			properties.put("mail.smtp.ssl.enable", "true");
			properties.put("mail.smtp.ssl.socketFactory", sf);
			//获取Session对象
			Session session = Session.getDefaultInstance(properties, new Authenticator() {
				@Override
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(name, pwd);
				}
			});
			//创建MimeMessage对象
			MimeMessage message = new MimeMessage(session);
			//设置发件人
			message.setFrom(new InternetAddress(name));
			//设置收件人
			message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
			//设置邮件主题
			message.setSubject("测试标题");
			//设置邮件内容
			message.setText("测试内容");
			//发送消息
			Transport.send(message);
			System.out.println("发送中...");
		} catch (MessagingException mex) {
			mex.printStackTrace();
		} catch (GeneralSecurityException e) {
			e.printStackTrace();
		}
message.setText()该方法用于写入文本,邮件内容可改为其它,如下:
注:替换"message.setText("测试内容");"代码实现
// 1.发送 HTML 消息, 可以插入html标签
         message.setContent("<h1>This is actual message</h1>",
                            "text/html" );

// 2.发送内容携带附件等
// 创建消息部分
         BodyPart messageBodyPart = new MimeBodyPart();
 
         // 消息
         messageBodyPart.setText("This is message body");
        
         // 创建多重消息
         Multipart multipart = new MimeMultipart();
 
         // 设置文本消息部分
         multipart.addBodyPart(messageBodyPart);
 
         // 附件部分
         messageBodyPart = new MimeBodyPart();
         String filename = "file.txt";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         multipart.addBodyPart(messageBodyPart);
 
         // 发送完整消息
         message.setContent(multipart );

JDK8特性之默认方法

//一个接口有默认方法,考虑这样的情况,一个类实现了多个接口,
//且这些接口有相同的默认方法,以下实例说明了这种情况的解决方法:
public interface vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
}
 
public interface fourWheeler {
   default void print(){
      System.out.println("我是一辆四轮车!");
   }
}
//第一个解决方案是创建自己的默认方法,来覆盖重写接口的默认方法:
public class car implements vehicle, fourWheeler {
   default void print(){
      System.out.println("我是一辆四轮汽车!");
   }
}
//第二种解决方案可以使用 super 来调用指定接口的默认方法:
public class car implements vehicle, fourWheeler {
   public void print(){
      vehicle.super.print();
   }
}

//Java 8 的另一个特性是接口可以声明(并且可以提供实现)静态方法
public interface vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
    // 静态方法
   static void blowHorn(){
      System.out.println("按喇叭!!!");
   }
}
//该静态方法可直接调用
class Car implements Vehicle, FourWheeler {
   public void print(){
      Vehicle.super.print();
      FourWheeler.super.print();
      Vehicle.blowHorn();
      System.out.println("我是一辆汽车!");
   }
}
1.接口可以定义一个默认方法
2.接口可以定义静态方法

JDK8特性之Lambda 表达式

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
   }
    
   interface MathOperation {
      int operation(int a, int b);
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
    
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}
要点:
1.通过声明接口实现接口中的方法
2.设置类中的方法参数 传递参数及实现方法的接口对象
3.调用类中的方法实现逻辑功能
----------------------------------------------------
以上实例实现了简单的加减乘数及一个欢迎日志打印
通过对比之前实现该功能的逻辑代码可看出JDK8带来的简洁!