位运算那些事儿

基础

​ 计算机以二进制补码存储数据(有符号位)。

​ 正数的原码,反码,补码是其本身。

​ 针对于负数:

  • 原码:符号位(1为负数,0为正数)。

  • 反码:(除符号位外)按位取反,符号位不变。

  • 补码:在反码的基础上加1。

    为什么用补码?

    a-b=a+(-b); 为了让符号位参与计算,先出现了反码,来解决减法:

    1-1 = 1+(-1)=[0000 0001]+[1000 0001]=[0000 0001]+[1111 1110]=[1111 1110]=[1000 000]=-0

    此时,0有两个编码表示法+0[0000 0000] -0[1000 000]。然后补码的出现解决了0的符号和编码问题。

    1-1 = 1+(-1)=[0000 0001]+[1000 0001]=[0000 0001]+[1111 1111]=[1111 1110]=[0000 0000]=0

    此时0用[0000 0000]表示,而[1000 0000]表示-128

    由理可知,4个字节的int的在机器中用补码表示范围为[-231,231-1]. (比正反码表示还多1个)

more >>

sso基础

工作上最近要做几个系统的SSO单点登录,先整理一下知识储备

Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式。(缺点:Cookie多时,会增加客户端与服务端的数据传输量)
Key/Value形式保存于user-agent

Name=Value name是unique的,值只能是ASSIC字符,
           (中文可通过URLEncoder编码)
Expires    过期时间
Max-Age    最大失效时间
Domain     生成该Cookie的域名
Path       生成路径
Secure     设置表示只会在SSH连接时才回传该Cookie
Port       在什么端口下回传服务器
Comment    注释项:用途
CommentURL 服务器提供的URI注释

more >>

离线资源包的简单实现

工作上遇到一个需求,给移动端提供离线资源包,使其能够离线使用,访问资源。
简单的拆分为两方面:

  1. 资源包的准备,对服务器上的资源进行打包
  2. 准备相应的json数据,离线时匹配资源

这个需求不依托于现有的后台及接口程序,所以构建只用了mybatis处理数据的获取(不想写jdbc,蛋疼),最终打包成了一个可执行jar,在服务器上充当脚本的角色。

more >>

The current request is not a multipart request

描述

Android端使用okhttp,后台接口springmvc,当遇到一个功能模块,上传文件是非必须的条件时,在只传递字符串参数,不带files时报错:”The current request is not a multipart request”

错误代码:

1
2
3
4
@RequestMapping("release")
public Result release(@RequestParam("params") String params,
@RequestParam(value = "files", required = false) MultipartFile[] files) {
}

原因显而易见,未传递文件信息。解决办法,判断请求,从request中获取files

1
2
3
4
5
6
7
@RequestMapping("release")
public Result updateUserInfo(@RequestParam("params") String params, HttpServletRequest request) {
MultipartFile file = null;
if (request instanceof MultipartHttpServletRequest) {
file = ((MultipartHttpServletRequest) request).getFile("files");
}
}

—— END. Kugin on 11.03

云存储地址转换

之前把项目的存储搬到了七牛云(公有空间),今天把其改为了私有空间,私有空间的访问下载地址是经过计算的,其间写了些逗逼代码。

网站程序

后台是个SSM程序,将uploadToken的获取,downloUrl转换放在了一个工具action中,返回JSON。在前台全局util.js中写了工具function,ajax请求得到后台的数据,对url的获取同步请求async=true,为了在js中直接转换,不再暂存于标签中(前台请求转换url是个很逗逼的事,稍后说明)。

util.js

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
util={
getUploadServer: function () {
return "http://up-z2.qiniu.com";
},
initQiNiu:function (){
$.post(util.getRootPath()+"/qiniu/qiniu_queryUploadToken.action",function(result){
if (result){
var token = result.resultBean.message;
$('#token').val(token);
console.log("token:"+token);
}
});
$.post(util.getRootPath()+"/qiniu/qiniu_queryDomain.action",function(result){
if(result){
var domain= result.resultBean.message;
$('#domain').val(domain);
console.log("domain:"+domain);
}
});
},
getDownloadUrl:function (baseUrl){
var src;
$.ajax({
url:util.getRootPath()+"/qiniu/qiniu_queryDownloadUrl.action",
data:{"baseUrl":baseUrl},
async:false,
success:function(result){
if(result){
src = result.resultBean.message;
}
}
});
return src;
}
};

这种实现,使得在前台请求得到后台数据(数据库中存储的是计算前的实际上传地址eg:http://
ofn4xb4zs.bkt.clouddn.com/test.jpg)后,需在js中调用getDownlodUrl(url)转换,数据过多且未做分页时网页加载缓慢。

more >>

Java8--Stream

今天在构建菜单的代码中发现了一段很有意思的写法:

1
2
3
4
5
sysMenus.stream().filter(sysMenu -> sysMenu.getChildCount() > 0).forEach(sysMenu -> {
List<SysMenu> tempList = queryChildSysMenuByParentId(sysMenu.getMenuId());
sysMenu.setChildMenu(tempList);
this.checkToGetNextChlidSysMenu(tempList);
});

先mark一下Lambda 表达式,待后续填坑。

简单的讲:Java8中的Stream是对Collection的增强,专注于聚合操作、大批量数据操作。提供串行和并发两种模式。其并发操作依赖于Fork/Join框架。

  • Stream如似高级的Iterator,单向,不可往复。(数据源本身可以是无限的)

Stream Pipeline : Source –> Transforming values –>Operations

主要操作类型:

  • Intermediate :一个流可以跟随0+个intermediate操作,映射/过滤后,返回一个新的的流,这类操作是惰性的(lazy),调用这类方法,并没有开始遍历。
  • Terminal : 一个流只能有1个terminal操作,当这个操作执行后,流无法继续被操作。这类操作的执行,才开始流的遍历,产生一个结果或一个side effect。
  • short-circuiting :是在有限时间内完成对无限大的Stream处理的充分非必要条件。

基本用法:

more >>

Kugin。<br>末流码农~<br><br>面朝大海,春暖花开~