Spring Junit 读取WEB-INF下的配置文件

假设spring配置文件为applicationContext.xml

一.Spring配置文件在类路径下面

SpringJava应用程序中,一般我们的Spring的配置文件都是放在放在类路径下面(也即编译后会进入到classes目录下)。

以下是我的项目,因为是用maven管理的,所以配置文件都放在"src/main/resources"目录下,这时候,在代码中可以通过

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

然后获取相应的bean

如果代码想用Junit测试框架来测试,则Spring提供了对Junit支持,还可以使用注解的方式:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext.xml"})

只需要在相应的Test类前面加上此两个注解(第二个注解用来指明Spring的配置文件位置),就可以在Junit Test类使用中Spring提供的依赖注入功能。

二.Spring配置文件在WEB-INF下面

当然在做J2EE开发时,有些人习惯把Spring文件放在WEB-INF目录(虽然更多人习惯放在类路径下面)下面,或者有些Spring配置文件是放在类路径下面,而有些又放在WEB-INF目录下面,如下图:

1336538723_9420

这时候,在代码中就不可以使用ClassPathXmlApplicationContext来加载配置文件了,而应使用FileSystemXmlApplicationContext

ApplicationContext applicationContext = new FileSystemXmlApplicationContext("src/main/webapp/WEB-INF/applicationContext.xml");

然后获取相应的bean

如果代码想用Junit测试框架来测试,则Spring提供了对Junit支持,还可以使用注解的方式:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/applicationContext.xml"})

只需要在相应的Test类前面加上此两个注解(第二个注解用来指明Spring的配置文件位置),就可以在Junit Test类使用中Spring提供的依赖注入功能。

下面是我的一个Spring管理下的Junit测试类:

import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"file:src/main/webapp/WEB-INF/applicationContext.xml"})
public class SuFriendServiceImplOverRMITest {

	@Autowired
	private SuFriendService suFriendService;

	@Test
	public void getUserFollowerListTest(){
		List list = suFriendService.getUserFollowerList("liug_talk@163.com");
		System.out.println("------"+list);
	}
}

参考链接


Spring Junit 读取WEB-INF下的配置文件

d3['default'] is undefined

使用Babel引入d3,即import d3 from 'd3',使用时出现undefined的错误,调试后发现

var _d3 = __webpack_require__(164);

var _d32 = _interopRequireDefault(_d3);

var fill = _d32['default'].schemeCategory20;

_d3有schemeCategory20,d32['default']是undefined,

_interopRequireDefault是什么鬼?

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

就是根据__esModule 的一个if else,__esModule又是什么?

这里有一篇比较具体的解释 http://ryerh.com/javascript/2016/03/27/babel-module-implementation.html

简单来说,default就是我们在class后面写的 export default xxx

翻一翻源码,d3的default是true,但没有export default

Object.defineProperty(exports, '__esModule', { value: true });

 

相关链接:__esModule true in build/d3.js?

Improve docs: ES6 usage example

从这两个链接中,找到了d3的正确用法

import * as d3 from 'd3'

import文档

就是说,把d3的所有模块导出,给d3这个作用域

调试来看,就是

var _d3 = __webpack_require__(164);

var d3 = _interopRequireWildcard(_d3);

可以看到,用了import as后

从_interopRequireDefault转变为_interopRequireWildcard

function _interopRequireWildcard(obj) {
    if (obj && obj.__esModule) {
        return obj; 
    } else {
        var newObj = {}; 
        if (obj != null) {
            for (var key in obj) {
                if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; 
            } 
        } 
        newObj['default'] = obj; return newObj; 
    } 
}

也就是*替换了default

另外,必须再说一下,d3没有default,但d3的插件不一定没有

比如我使用的d3-cloud,还是要用import cloud from 'd3-cloud'

chart.js 绘制雷达图

chart.js是一个很newblity的图标库,支持各种图(柱状、曲线、饼图、雷达图等等),使用起来也很简单,这里先奉上官方文档一份 http://www.bootcss.com/p/chart.js/docs/。

chart.js使用canvas绘制,缺点就是移动端性能有点差(或者是我入门太浅)。

官方文档介绍的不甚详细,这里给一个可以成功的example。

雷达图

1.引入chart.js

1).<script>标签引入    逼格太低

2).npm install chart.js 后,var Chart = require('chart.js')    逼格一般

3).npm install chart.js,使用gulp,import Chart from 'chart.js'  逼格目前最高

2.html文件中,一个canvas元素是必须的

<canvas id="myChart" style="width: 100%;height: 90%;outline: none"></canvas>

style比较简单,就不写css了

3.创建一个图标,只需要new一个chart对象就可以了

this.radarDom = document.getElementById("myChart");
var myNewChart = new Chart(this.radarDom.getContext("2d"), this.radarConfig());

需要两个参数,canvas的context,以及config

主要问题在于config,暂时未能完全了解

radarConfig() {
    var chartColors = {
        red: 'rgb(255, 99, 132)',
        orange: 'rgb(255, 159, 64)',
        yellow: 'rgb(255, 205, 86)',
        green: 'rgb(75, 192, 192)',
        blue: 'rgb(54, 162, 235)',
        purple: 'rgb(153, 102, 255)',
        grey: 'rgb(231,233,237)'
    };

    var color = Chart.helpers.color;
    var config = {
        // 图标类型
        type: 'radar',
        data: {
            // 雷达图的角
            labels: ["0:00", "3:00", "6:00", "9:00", "12:00", "15:00", "18:00", "21:00"],
            color: '#fff',
            datasets: [{
                // 雷达图颜色
                backgroundColor: color(chartColors.red).alpha(0.3).rgbString(),
                borderColor: chartColors.blue,
                pointBackgroundColor: chartColors.red,
                // 数据 如[1, 2, 3, 4, 5, 6, 7, 8]
                data: this.radarData
            }]
        },
        options: {
            fontColor:'#fff',
            custom: {
                fontColor: "#fff",
                color: "#fff"
            },
            legend: {
                display: false,
                position: 'left',
            },
            title: {
                display: true,
                text: '我的观影时段',
                fontColor: '#fff',
                fontSize: 24
            },
            scale: {
                // ticks 0 10 20等标签
                fontColor: '#ffffff',
                ticks: {
                    display: false,
                    beginAtZero: true,
                    fontColor: "#000",
                    maxTicksLimit: undefined,
                },
                //scaleLabel: {
                //    fontColor: "#000",
                //}
                // 线条
                gridLines: {
                    color: '#fff',
                    //zeroLineColor: '#fff'
                }
            }
        }
    };

    return config;
}

HTML5文件实现拖拽上传

通过HTML的文件API ,Firefox、Chrome等浏览器已经支持从操作系统直接拖拽文件,并上传到服务器。

相对于使用了十多年的HTML表单,这是一个革命性的进步。虽然IE的落后让很多开发者还在观望中,但是Gmail邮箱的附件拖拽功能已经给部分用户带来了极大的方便,而需要大量上传文件的CMS(内容管理系统)也将会从中受益。

让我们看一下Firefox 是如何使用拖拽上传功能的:

首先提供一个区域来放置文件

Html代码

<div name="image" id="dropbox" style="min-width:300px;min-height:100px;border:3px dashed silver;"></div>

然后监听拖拽过程中的dragenter,dragleave,drop等事件

Js代码

document.addEventListener("dragenter", function(e){  
    dropbox.style.borderColor = 'gray';  
}, false);  
document.addEventListener("dragleave", function(e){  
    dropbox.style.borderColor = 'silver';  
}, false);  
dropbox.addEventListener("dragenter", function(e){  
    dropbox.style.borderColor = 'gray';  
    dropbox.style.backgroundColor = 'white';  
}, false);  
dropbox.addEventListener("dragleave", function(e){  
    dropbox.style.backgroundColor = 'transparent';  
}, false);  
dropbox.addEventListener("dragenter", function(e){  
    e.stopPropagation();  
    e.preventDefault();  
}, false);  
dropbox.addEventListener("dragover", function(e){  
    e.stopPropagation();  
    e.preventDefault();  
}, false);  
dropbox.addEventListener("drop", function(e){  
    e.stopPropagation();  
    e.preventDefault();  
       
    handleFiles(e.dataTransfer.files);  
       
    submit.disabled = false;  
}, false);

其中最主要的是drop事件中用handleFiles()依次处理所有文件

handleFiles = function(files) {  
    for (var i = 0; i < files.length; i++) {  
        var file = files[i];  
   
    }  
}

对于图片类型的文件可以直接读取内容,显示预览图

if (!file.type.match(/image*/)) {  
    continue;  
}  
   
var img = document.createElement("img");  
img.classList.add("obj");  
img.file = file;  
preview.appendChild(img);  
   
var reader = new FileReader();  
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);  
reader.readAsDataURL(file);

接下来就是核心功能:ajax上传。首先新建一个XHR请求

var xhr = new XMLHttpRequest();  
xhr.open('post', '/file/upload', true);

监听上传进度和完成事件

xhr.upload.addEventListener("progress", function(e) {  
    if (e.lengthComputable) {  
        var percentage = Math.round((e.loaded * 100) / e.total);  
        img.style.opacity = 1-percentage/100.0;  
    }  
}, false);  
   
xhr.upload.addEventListener("load", function(e){  
       
}, false);

最后把数据模拟成multipart/form-data的格式上传

xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary); // simulate a file MIME POST request.  
xhr.setRequestHeader("Content-Length", fileSize);  
   
var body = '';  
body += "--" + boundary + "\r\n";  
body += "Content-Disposition: form-data; name=\""+dropbox.getAttribute('name')+"\"; filename=\"" + fileName + "\"\r\n";  
body += "Content-Type: "+fileType+"\r\n\r\n";  
body += fileData + "\r\n";  
body += "--" + boundary + "--\r\n";  
   
xhr.sendAsBinary(body);

参考链接


HTML5文件实现拖拽上传

Linux ls列出目录下所有文件数量

1.查看统计当前目录下文件的个数

$ ls -l | grep "^-" | wc -l

2.查看统计当前目录下文件的个数,包括子目录里的。

$ ls -lR| grep "^-" | wc -l

3.查看某目录下文件夹(目录)的个数,包括子目录里的。

$ ls -lR| grep "^d" | wc -l

参考链接


linux ls列出目录下所有文件数量

WDMyCloud编译USB网卡MT7601U驱动(小米,小度,360WiFi)

前言


有人留言希望尝试在WDMyCloud上尝试使用USB无线网卡,目标芯片是MT7601U。

经过几天的研究,找到了相关的编译方式。

链接地址 https://github.com/porjo/mt7601u,提示在Linux-4.2以后的版本中已经集成MT7601U芯片的驱动了(drivers/net/wireless/mediatek目录下),但是可惜的是WDMyCloud上的Linux内核版本号是3.2.26,曾经尝试升级到4.2版本之后的Linux内核,可惜尝试之后,发现无法成功编译Mindspeed C2000芯片(WDMyCloud使用的IC芯片,包含CPU,网卡等)驱动,因此只能退而求其次,使用MTK官方提供的驱动程序在3.2.26版本的Linux内核上进行编译。

另外注意,在WDMyCloud提供的默认系统镜像上,没有提供802.11相关的驱动,导致如果使用无线网卡,必须重新编译内核。

具体操作


1.下载MT7601U芯片驱动

驱动程序的下载地址为:http://www.mediatek.com/products/broadbandWifi/mt7601u#product-downloads

也可本站下载

2.下载最新的WDMyCloud的系统源代码

目前最新的下载地址为:http://downloads.wdc.com/gpl/gpl-source-wd_my_cloud-04.04.03-113.zip

3.参照 How to successfully build packages for WD My Cloud from source构建编译环境

4.解压缩下载到的代码中的"packages/kernel_3.2"到"64k-wheezy/build/root"目录下面。

5.执行如下命令,重新编译内核,为驱动的编译准备必备的文件

$ cd ~

$ cd 64k-wheezy

$ sudo chroot build

$ cd root

$ cd kernel_3.2

$ apt-get install uboot-mkimage

修改内核编译文件"/kernel_3.2/linux/arch/arm/configs/sequoia64k-wifi_defconfig",在文件的顶部增加"CONFIG_WEXT_PRIV=y",定义这个宏的目的,是为了编译MT7601U芯片驱动的时候使用的,缺少这个宏会导致芯片驱动编译的时候缺少变量。

6.编译内核

$ make sequoia64k-wifi

编译成功后,在"kernel_3.2/_bld"目录下生成编译文件,在"kernel_3.2/_bin"目录下生成最终的内核镜像和驱动程序。

7.解压缩MT7601U芯片驱动代码到"64k-wheezy/build/root"目录下面,并命名为"MT7601U"。

修改芯片驱动编译文件"Makefile",找到

ifeq ($(PLATFORM),IXP)
LINUX_SRC = /project/stable/Gmtek/snapgear-uclibc/linux-2.6.x
CROSS_COMPILE = arm-linux-
endif

在这行下面增加

ifeq ($(PLATFORM),WDMyCloud)
# Linux 2.6
LINUX_SRC = /root/kernel_3.2/_bld
# Linux 2.4 Change to your local setting
#LINUX_SRC = /usr/src/linux-2.4
LINUX_SRC_MODULE = /root/kernel_3.2/kernel/linux/drivers/net/wireless/
CROSS_COMPILE = arm-linux-gnueabihf-
#export ARCH=arm 
endif

修改"Makefile"中,编译目标系统从PLATFORM = PCPLATFORM = WDMyCloud.

接下来修改"os/linux/config.mk",在文件尾部增加

ifeq ($(PLATFORM),WDMyCloud)
EXTRA_CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -Uarm -fno-common -pipe -march=armv6 -msoft-float -Uarm -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/version.h $(WFLAGS)

export EXTRA_CFLAGS
endif

最后,切换到驱动程序所在的"MT7601U"目录,执行编译。

$ make

编译完成后,在"MT7601U/os/linux/"目录下生成名为"mt7601Usta.ko"的驱动程序文件。

剩下的,参考"MT7601U"目录下的"README_STA_usb"中的说明进行操作即可。

注意,如果要成功使用无线网卡驱动,那么需要用刚刚编译好的Linux内核,替换掉原来的内核,并且把"kernel_3.2/_bin"目录下的驱动也拷贝到系统根目录下面相同的位置即可,这个操作是高风险操作,极可能这么操作之后,系统无法正常运行,因此要提前备份文件,并且做好拆硬盘,挂载到其他机器上撤销刚刚的修改的准备。

参考链接


mt7601驱动使用(三)

IPFire内核升级(Core Update)

IPFire内核有新版本的时候,会在页面的首页底部提示,如下图:
ipfire_core_update
点击链接后,跳转到升级页面,点击升级按钮即可,如下图:
ipfire_core_update_click
但是有时候会出现问题,点击升级是无效的,如下图:
ipfire_core_update_click_invalid
这个时候需要通过远程控制台进行操作了,执行如下命令:

$ pakfire update --force

$ pakfire upgrade

# pakfire 访问的服务器地址为 pakfire.ipfire.org 最近这个地址的访问不是非常稳定
# 如果发生失败,观察日志 cat /var/log/messages

如果发生错误的时候 http://pakfire.ipfire.org/2.21-x86_64/lists/server-list.db 这个地址没办法访问,那么试试 https://pakfire.ipfire.org/2.21-x86_64/lists/server-list.db 看看是不是能正常访问。

如果 `HTTPS` 可以正常访问,那么需要手工修改一下系统的代码,如下:

$ sudo vim /opt/pakfire/lib/functions.pl

搜索找到如下内容:

$proto = "HTTP" unless $proto;

替换为:

$proto = "HTTPS" unless $proto;

这个属于客户端代码没有正确适配,同时服务器上的修改没有进行兼容导致的。

参考链接


How to upgrade to Core Update 62?

如何安装树莓派摄像头模块

树莓派摄像头模块(Pi Cam)发售于2013年5月。其第一个发布版本配备了500万像素的传感器,通过排线链接树莓派上的CSI接口。而Pi Cam的第二个发布版本——也被叫做Pi NoIR中,配备了相同的传感器,但没有红外线过滤装置。因此第二版的摄像头模块就像安全监控摄像机一样,可以观测到近红外线的波长(700 - 1000 nm),不过当然同时也就牺牲了一定的显色性。

本文将会展示如何在树莓派上安装摄像头模块。 我们将使用第一版摄像头模块来演示。在安装完摄像头模块之后,你将会使用三个应用程序来访问这个模块:raspistill, raspiyuv 和raspivid。其中前两个应用用来捕捉图像,第三个应用来捕捉视频。raspistill 工具生成标准的图片文件,例如 .jpg 图像,而 raspiyuv 可以通过摄像头生成未处理的 raw 图像文件。

安装树莓派摄像头模块

按照以下步骤来将树莓派摄像头模块连接搭配树莓派:

  1. 找到 CSI 接口(CSI接口在以太网接口旁边),掀起深色胶带。
  2. 拉起 CSI 接口挡板。
  3. 拿起你的摄像头模块,将贴在镜头上的塑料保护膜撕掉。确保黄色部分的PCB(有字的一面)是安装完美的(可以轻轻按一下黄色的部分来保证安装完美)。
  4. 将排线插入CSI接口。记住,有蓝色胶带的一面应该面向以太网接口方向。同样,这时也确认一下排线安装好了之后,将挡板拉下。

130426pxvuxrqtnpppxx17

好了,现在你的 Pi Cam 已经准备就绪,可以拍摄照片或视频了。

在树莓派上启用摄像头模块

在安装完摄像头模块之后,首先要确认你已经升级了树莓派系统并应用了最新的固件。可以输入以下命令来操作:

$ sudo apt-get update
$ sudo apt-get upgrade 

运行树莓派配置工具来激活摄像头模块:

$ sudo raspi-config 

移动光标至菜单中的 "Enable Camera(启用摄像头)",将其设为Enable(启用状态)。完成之后重启树莓派。

130440dguwh6gwk1vk9jgv

130442rn19igalrfo1rmg5

130443uq0hldn4sfvc0nhs

安装完摄像头模块后的完成照:

130454br44z4dnp2c3zcyr

通过摄像头模块拍照

在重启完树莓派后,我们就可以使用Pi Cam了。要用它来拍摄照片的话,可以从命令行运行raspistill:

$ raspistill -o keychain.jpg -t 2000 

这句命令将在 2000ms 后拍摄一张照片,然后保存为 keychain.jpg。下面就是一张由 Pi Cam 拍摄的我的小熊公仔钥匙链。

130456h516ypyamyo5mst6

raspiyuv 工具用法差不多,只不过拍摄得到的是一张未处理过的raw图像。

通过摄像头模块拍视频

想要用摄像头模块拍一段视频的话,可以从命令行运行 raspivid 工具。下面这句命令会按照默认配置(长度5秒,分辨率1920x1080,比特率 17Mbps)拍摄一段视频。

$ raspivid -o mykeychain.h264

如果你想改变拍摄时长,只要通过 "-t" 选项来设置你想要的长度就行了(单位是毫秒)。

$ raspivid -o mykeychain.h264 -t 10000

使用 "-w" 和 "-h" 选项将分辨率降为 1280x720...

$ raspivid -o mykeychain.h264 -t 10000 -w 1280 -h 720

raspivid 的输出是一段未压缩的 H.264 视频流,而且这段视频不含声音。为了能被通常的视频播放器所播放,这个 raw 的 H.264 视频还需要转换。可以使用 gpac 包中所带有的 MP4Box 应用。

在 Raspbian 上安装 gpac,输入命令:

$ sudo apt-get install -y gpac 

然后将这段 raw 的 H.264 格式的视频流转换为每秒30帧的 .mp4 格式视频:

$ MP4Box -fps 30 -add keychain.h264 keychain.mp4 

视频长度为10秒,使用默认分辨率以及比特率。

如果想要获取 raspistill, raspiyuv 和 raspivid 的完整命令行选项,不加任何选项直接运行以上命令即可。

参考链接


如何安装树莓派摄像头模块

Android Studio 2.2 启用代码混淆

在新版本的Android Studio中开启混淆的方法如下:

buildTypes {
        release {
            minifyEnabled true //是否混淆
            shrinkResources true //是否去除无效的资源文件
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

具体解释一下minifyEnabled用来影响是不是开启混淆,shrinkResources只有在minifyEnabledtrue的情况下,才能有效,用来去除无效的资源文件。proguard-android-optimize.txtAndroid SDK->tools\proguard目录下,Google已经写好默认的混淆模板文件,其中的proguard-android.txt默认没有配置代码优化,而proguard-android-optimize.txt默认配置了代码优化,至于我们自己工程下面的proguard-rules.pro文件,只要配置我们自定义的额外配置即可,其他的用默认配置即可。

顺便讲一下代码混淆的好处:

1.代码安全,不易理解,增加破解难度。

2.减小APK的体积,减少内存开销。

3.缩减类名,方法名的长度,减少CPU开销。

参考链接