咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

描述

multipart/form-data 用以向服务器发送二进制数据,一般用于多个文件和参数一起发送。

服务端接收数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@RequestMapping("/test/multipart")
@ResponseBody
public String handleFileUpload(@RequestPart("file")MultipartFile file,
@RequestPart("describe")String describe){

System.out.println("describe="+describe);
if(!file.isEmpty()){

try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(file.getOriginalFilename())));
out.write(file.getBytes());
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
return e.getMessage();

} catch (IOException e) {
e.printStackTrace();
return e.getMessage();
}
return"OK";
}else{
return"file is null";
}
}

客户端

阅读全文 »

需求

分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。

客户端给服务器发送数据也一样可以使用 Chunk 传输,比如,客户端要上传数据,但是数据没有完全生成,通过chunk分块传输,就可以一边生成数据一边上传,典型的比如:上传录音。

服务端接收数据

1
2
3
4
5
@PostMapping(value = "/upload")
public String upload(@RequestBody byte[] body){

return "PONG:"+body.length;
}
阅读全文 »

微信硬件平台方案

假如我们要有一个WiFi硬件产品,已经有与自己的服务器通讯的私有协议,现在要接入到微信公众号平台,那将如何选择对接方案呢?

《微信硬件平台》 有两大类接入方案:微信硬件云标准接入方案平台基础接入方案

选择接入方案.png

调试工具

阅读全文 »

Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具。Jenkins非常灵活,不过需要自己部署服务器,功能非常强大。可以通过配置插件,实现各种项目的 编译 - 打包 - 部署 等一条龙服务工作。

……篇幅较长,还是看别人的吧 《搭建jenkins实现自动化部署》

travis-ci 是在线托管的CI服务,用Travis来进行持续集成,不需要自己搭服务器,使用方便,对Github开源项目是免费的,支持多数主流语言。

使用

  1. 登录Travis官网 ,用Github账号登录。
  2. 首次登录,授权给Travis访问你的GitHub代码库
  3. 把需要CI的项目(UIAutomatorTest)勾选上
  4. 点击 “hebbely/UiAutomatorTest”,进入该项目”More Options”-“Setting” ,打开选项”Build ..yml” 和 “Build pushed branches”
  5. 添加.travis.yml
1
2
3
4
5
6
7
8
9
10
language: java
jdk:
- oraclejdk8
script: "mvn clean package -Dmaven.test.skip=true"
branches:
only:
- master
notifications:
email:
- xxx@qq.com

在github看到很多项目根目录都有 .editorconfig 文件,所以去了解一下。

这个文件是 EditorConfig 用来统一不同编辑器的代码风格的配置。

各种IDE的风格自然不一样,通过这样一个配置文件定义的标准统一风格,比如缩进用x个空格。再有就是多人一起协同开发一个项目,editorconfig 能起到很好的效果。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# EditorConfig: http://editorconfig.org/

root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

阅读全文 »

自己搜索的内容含有 csdn.net 的,但这个网站要登录才能看,所以这些搜索结果是无用的,所以要过滤掉这些无用的结果。
如某搜索,这样搜索:关键字 -site:csdn.net 就是过滤掉 csdn.net 的搜索结果。

实用的插件,idea默认没有带的,自己可以安装。

.ignore

可以帮助你创建相关项目的.gitignore文件

GsonFormat

快速生成JSON类

阅读全文 »

启动默认不打开项目

Appearance & Behavior –System Setting – Reopen last project on startup

terminal

shell path 设置为 git 安装路径的/bin/bash.exe

keymap

阅读全文 »

目前Android4.x也算是老设备了,今天做的一个项目访问客户的 HTTPS 服务器,在Android4.x一直抛异常

1
javax.net.ssl.SSLException: Connection closed by peer

这是由于 Android4.x 默认关闭 TLS 的支持和 OkHTTP3.x 的问题,这个问题的讨论在于 issues/2372

解决这个问题有两个大方向:

  1. 服务器配置兼容支持TLS1.0、TLS1.1、TLS1.2,这样客户端就不需要做任何处理,完美兼容
  2. Android端开启TLS1.2支持
阅读全文 »

环境和实现效果:

  1. 两台阿里云服务器做集群

    服务器 1 (主):内网(10.0.0.1)外网(118.0.0.1)
    服务器 2 (从):内网(10.0.0.2)外网(118.0.0.2)

  2. 安装emq

    1
    2
    $ wget https://www.emqx.io/static/brokers/emqttd-ubuntu16.04-v2.3.11.zip
    $ unzip emqttd-ubuntu16.04-v2.3.11.zip
  3. 配置

    1
    2
    3
    4
    $ vim emqttd/etc/emq.conf

    node.name = emq@内网IP
    mqtt.allow_anonymous = false
  4. 系统调优

    切换到root账号操作比较方便

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ vim /etc/security/limits.conf
    ubuntu soft nofile 65535
    ubuntu hard nofile 65535
    root soft nofile 65535
    root hard nofile 65535
    * soft nofile 65536
    * hard nofile 65536
    * soft nproc 102400
    * soft memlock unlimited
    * hard memlock unlimited
    1
    2
    3
    4
    $ sysctl -w fs.file-max=2097152
    $ sysctl -w fs.nr_open=2097152
    $ echo 2097152 > /proc/sys/fs/nr_open
    $ ulimit -n 1048576
    1
    2
    3
    4
    $ vim /etc/sysctl.conf
    fs.file-max = 1048576
    $ vim /etc/systemd/system.conf
    DefaultLimitNOFILE=1048576
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    sysctl -w net.core.somaxconn=32768
    sysctl -w net.ipv4.tcp_max_syn_backlog=16384
    sysctl -w net.core.netdev_max_backlog=16384
    sysctl -w net.ipv4.ip_local_port_range='1000 65535'
    sysctl -w net.core.rmem_default=262144
    sysctl -w net.core.wmem_default=262144
    sysctl -w net.core.rmem_max=16777216
    sysctl -w net.core.wmem_max=16777216
    sysctl -w net.core.optmem_max=16777216
    sysctl -w net.ipv4.tcp_rmem='1024 4096 16777216'
    sysctl -w net.ipv4.tcp_wmem='1024 4096 16777216'
  5. 加入集群

    1
    2
    3
    4
    5
    # 以root账号运行
    $ ./bin/emqttd start

    # 在节点运行
    $ ./bin/emqttd_ctl cluster join emq@10.0.0.1
  6. 退出集群

    1
    2
    3
    4
    5
    #本节点退出集群
    $ ./bin/emqttd_ctl cluster leave

    #从集群删除其他节点
    $ ./bin/emqttd_ctl cluster remove emq@s2.emqtt.io
  7. 负载均衡

    省略

环境和实现效果:

  1. 一台虚拟机安装Kafka
  2. 本地基于SpringBoot使用Kafka Client

安装zookeeper

1
2
3
4
5
root@bogon:~# wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz
root@bogon:~# tar zxf zookeeper-3.4.13.tar.gz
root@bogon:~/zookeeper-3.4.13/conf# cp zoo_sample.cfg zoo.cfg
root@bogon:~/zookeeper-3.4.13/conf# cd ../bin/
root@bogon:~/zookeeper-3.4.13/bin# ./zkServer.sh start

安装Kafka

阅读全文 »

环境和实现效果:

  1. 两台服务器安装EMQ实例监听1883端口(两个EMQ节点要做集群)
  2. 一台负载均衡服务器NGINX监听1883端口
  3. 客户端连接负载均衡服务器,连接分配到EMQ服务器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#TCP负载均衡
stream {
upstream mqtt1883{
server 192.168.0.223:1883 weight=1;
server 192.168.0.224:1883 weight=1;
}
server {
listen 1883;
#proxy_send_timeout 2h;
#proxy_read_timeout 2h;
#proxy_connect_timeout 150s;
#proxy_timeout 150s;
proxy_pass mqtt1883;
proxy_buffer_size 3M;
tcp_nodelay on;
}
}

节点加入集群:$ ./bin/emqttd_ctl cluster join emq@192.168.0.88

2018年9月25日 JDK 11 发布,LTS 版本。

新特性: http://openjdk.java.net/projects/jdk/11/

  • 181: Nest-Based Access Control
  • 309: Dynamic Class-File Constants
  • 315: Improve Aarch64 Intrinsics
  • 318: Epsilon: A No-Op Garbage Collector
  • 320: Remove the Java EE and CORBA Modules
  • 321: HTTP Client (Standard)
  • 323: Local-Variable Syntax for Lambda Parameters
  • 324: Key Agreement with Curve25519 and Curve448
  • 327: Unicode 10
  • 328: Flight Recorder
  • 329: ChaCha20 and Poly1305 Cryptographic Algorithms
  • 330: Launch Single-File Source-Code Programs
  • 331: Low-Overhead Heap Profiling
  • 332: Transport Layer Security (TLS) 1.3
  • 333: ZGC: A Scalable Low-Latency Garbage Collector (Experimental)
  • 335: Deprecate the Nashorn JavaScript Engine
  • 336: Deprecate the Pack200 Tools and API

中文

  • 181: 基于嵌套的访问控制
  • 309: 动态类文件常量
  • 315: 改进 Aarch64 Intrinsics
  • 318: Epsilon: 一个无操作的垃圾收集器
  • 320: 删除 Java EE and CORBA Modules
  • 321: HTTP Client (Standard)
  • 323: 用于 Lambda 参数的局部变量语法
  • 324: 新增 Curve25519 and Curve448 算法的密钥协议
  • 327: Unicode 10
  • 328: 飞行记录器 Flight Recorder
  • 329: ChaCha20 and Poly1305 加密算法
  • 330: 启动单一文件的源代码程序
  • 331: 低开销的 Heap Profiling
  • 332: 支持 TLS 1.3
  • 333: ZGC: 可伸缩低延迟垃圾收集器
  • 335: 弃用 the Nashorn JavaScript Engine
  • 336: 弃用 the Pack200 Tools and API
阅读全文 »

环境和实现效果:

  1. 两个Tomcat实例监听8081和8083端口
  2. NGINX监听80端口,通过负载均衡将请求转发到Tomcat实例
  3. 客户端访问80端口,结果是Tomcat响应的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#负载均衡
http {
upstream tomcattest.com {
server localhost:8081;
server localhost:8083;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://tomcattest.com;
}
}
}

配置解析:

  1. tomcattest.com是我随便填的,应该只是内部用的。
  2. upstream有多种负载均衡模式,默认是按照顺序轮询。
阅读全文 »

ERC20:Ethereum Request for Comments 20,是一个基于以太坊代币的接口标准(协议)。所有符合 ERC-20 标准的代币都能立即兼容以太坊钱包,它能让用户和交易所,都能非常方便的管理多种代币,转账、存储、ICO 等等。

StandardToken.sol

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
pragma solidity ^0.4.24;

import "./BasicToken.sol";
import "./ERC20.sol";

/**
* @title 标准 ERC20 token
*
* @dev 实现基础的标准token
* @dev https://github.com/ethereum/EIPs/issues/20
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*/
contract StandardToken is ERC20, BasicToken {
mapping (address => mapping (address => uint256)) internal allowed;

/**
* @dev 从一个地址向另外一个地址转token
* @param _from 转账的from地址
* @param _to address 转账的to地址
* @param _value uint256 转账token数量
*/
function transferFrom(
address _from,
address _to,
uint256 _value
)
public
returns (bool)
{
// 做合法性检查
require(_to != address(0));
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
//_from余额减去相应的金额
//_to余额加上相应的金额
//msg.sender可以从账户_from中转出的数量减少_value
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
// 触发Transfer事件
emit Transfer(_from, _to, _value);
return true;
}

/**
* @dev 批准传递的address以代表msg.sender花费指定数量的token
*
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param _spender 花费资金的地址
* @param _value 可以被花费的token数量
*/
function approve(address _spender, uint256 _value) public returns (bool) {
//记录msg.sender允许_spender动用的token
allowed[msg.sender][_spender] = _value;
//触发Approval事件
emit Approval(msg.sender, _spender, _value);
return true;
}

/**
* @dev 函数检查所有者允许的_spender花费的token数量
* @param _owner address 资金所有者地址.
* @param _spender address 花费资金的spender的地址.
* @return A uint256 指定_spender仍可用token的数量。
*/
function allowance(
address _owner,
address _spender
)
public
view
returns (uint256)
{
//允许_spender从_owner中转出的token数
return allowed[_owner][_spender];
}

/**
* @dev 增加所有者允许_spender花费代币的数量。
*
* allowed[_spender] == 0时approve应该被调用. 增加allowed值最好使用此函数避免2此调用(等待知道第一笔交易被挖出)
* From MonolithDAO Token.sol
* @param _spender 花费资金的地址
* @param _addedValue 用于增加允许动用的token牌数量
*/
function increaseApproval(
address _spender,
uint _addedValue
)
public
returns (bool)
{
//在之前允许的数量上增加_addedValue
allowed[msg.sender][_spender] = (
allowed[msg.sender][_spender].add(_addedValue));
//触发Approval事件
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}

/**
* @dev 减少所有者允许_spender花费代币的数量
*
* allowed[_spender] == 0时approve应该被调用. 减少allowed值最好使用此函数避免2此调用(等待知道第一笔交易被挖出)
* From MonolithDAO Token.sol
* @param _spender 花费资金的地址
* @param _subtractedValue 用于减少允许动用的token牌数量
*/
function decreaseApproval(
address _spender,
uint _subtractedValue
)
public
returns (bool)
{
uint oldValue = allowed[msg.sender][_spender];
if (_subtractedValue > oldValue) {
//减少的数量少于之前允许的数量,则清零
allowed[msg.sender][_spender] = 0;
} else {
//减少对应的_subtractedValue数量
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
}
//触发Approval事件
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}

}

BasicToken.sol

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
pragma solidity ^0.4.24;

import "./ERC20Basic.sol";
import "../../math/SafeMath.sol";


/**
* @title 实现ERC20基本合约的接口
* @dev 基本的StandardToken,不包含allowances.
*/
contract BasicToken is ERC20Basic {
using SafeMath for uint256;

mapping(address => uint256) balances;

uint256 totalSupply_;

/**
* @dev 返回存在的token总数
*/
function totalSupply() public view returns (uint256) {
return totalSupply_;
}

/**
* @dev 给特定的address转token
* @param _to 要转账到的address
* @param _value 要转账的金额
*/
function transfer(address _to, uint256 _value) public returns (bool) {
//做相关的合法验证
require(_to != address(0));
require(_value <= balances[msg.sender]);
// msg.sender余额中减去额度,_to余额加上相应额度
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
//触发Transfer事件
emit Transfer(msg.sender, _to, _value);
return true;
}

/**
* @dev 获取指定address的余额
* @param _owner 查询余额的address.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address _owner) public view returns (uint256) {
return balances[_owner];
}

}
阅读全文 »

Android Studio 下载 gradle 一直很慢,或者是根本下载不了,而通过手动下载,则快很多。

一、使用镜像服务器 (20240121新增)

1
2
3
4
5
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"

改为

distributionUrl = "https://mirrors.cloud.tencent.com/gradle/gradle-$gradleVersion-all.zip"

备注:这个设置可能是Gradle Java 项目的,创建Android项目没生效。但还是可以手动修改的 gradle-wrapper.properties 文件的。

阅读全文 »

为什么要验证合约?

源代码验证为与智能合约交互的用户提供了透明性。通过上传源代码,Etherscan将编译后的代码与区块链上的代码匹配。就像合同一样,“智能合约”应该为最终用户提供更多关于他们“数字签名”的信息,并让用户有机会审计代码,以独立地验证代码实际上做了应该做的事情。

ABI文件公开?目前我的Dapp做法需要将编译的合约 json 文件和WebApp放在一起,通过ajax读取 json 文件初始化合约。

如何验证?

具体就是将代码上传到etherscan.io,只需几步操作。

阅读全文 »