小不的笔记

时间之外的往事

Java字符串格式化String.Format

每当拼字符串的时候,就会思念C的printf,不过后来才发现Java也实现了类似功能。

示例

代码:String.format("Hello %s, you're the %03d visitor.", "xobo", 7);

输出:Hello xobo, you're the 007 visitor.

默认情况下,参数会依次替换格式说明符。当我们需要重复引用时,就需要对格式说明符进行编号。

代码: String.format("%1$s %1$s %1$s, you are over %2$.2fM tall .", "xobo", 1.0);

输出:xobo xobo xobo, you are over 1.00M tall .

解释

格式说明符

  • %s %03d %1$s %2$.2f等以%开始的字符串被称为格式说明符(format specifiers);

  • 格式说明符的定义为:

    %[argument_index$][flags][width][.precision]conversion_

  • []表示非必填项,也就是说最简单的格式说明符定义为%conversion。

%为格式说明符的起始标志,如果想在字符串中输出%,就需要写成%%;

  • argument_index 可选 是一个整数,它表示参数在参数列表的位置。注意它是从1开始的,第一个参数是1$,第二个参数是2$;

  • flags 可选 是可以改变输出格式的字符。​

    • 如果不提供flag默认格式为:

      • 输出按照width做右对齐
      • 负数以’-‘开始
      • 正数和零不带符号或者前置空格
      • 没有组分隔符​​​

      常用的flag:

      • ‘-‘ 左对齐 (通用)
      • ‘+’ 数字一直带有符号 (数字有效)
      • ‘0’ 用0补空白处 (数字有效)
      • ‘,’
  • width 可选 是一个非负整数​,表示输出的最小字符数。

  • precision 可选 是一个非负整数​,限制输出字符长度。

  • conversion 必填 一个字符,表明参数将如何被格式化。

Dorado、BDF EL表达式

隐式对象

Dorado隐式对象

Dorado共提供了14个隐式对象,我们不需要预先定义就可以直接使用这些隐式对象。

与线程无关

标识符 描述
null 表示null
env 表示获取系统环境变量。${env.JAVA_HOME}或${env[“JAVA_HOME”]}
system Java的系统属性,即System.getProperties()对象。${system.property1}或${system[“property1”]}
configure 用于获取Dorado7的配置信息。${configure[“runMode”]}

与线程有关

标识符 描述
argument 用于获取当前配置文件中的参数值,仅可用于View.xml
context 当前线程中的DoradoContext。
ctx 用于简化对DoradoContext的getAttribute方法的访问。${ctx[“foo”]}相当于${context.getAttribute(“foo”)}
util 基本工具类,见com.bstek.dorado.core.el.ExpressionUtilsObject的javadoc
request 当前的HttpServletRequest对象,与请求作用域属性的名称和值相关联的 Map 类
req 用于简化对request的getAttribute方法的访问。 ${req[“foo”]}相当于${request.getAttribute(“foo”)}

扩展

通过实现 ContextVarsInitializer 接口并通过XML注册到 Spring 上下文,我们就可以添加自定义的隐式对象。
下面一个例子就是注册一个名为dict的隐式对象,通过dict.item('xxx')快捷的调用dictionaryExpressionObject.items('xxx') 并返回结果。

1
2
3
4
5
<bean parent="dorado.expressionVarsInitializerRegister">
<property name="contextInitializer">
<bean class="org.malagu.panda.coke.context.CokeContextVarsInitializer" />
</property>
</bean>
1
2
3
4
5
6
7
8
9
10
11
public class DictionaryContextVarsInitializer implements ContextVarsInitializer {

@Autowired
private DictionaryExpressionObject dictionaryExpressionObject;

@Override
public void initializeContext(Map<String, Object> vars) throws Exception {
vars.put("dict", dictionaryExpressionObject);
}

}
1
2
3
4
5
6
7
8
9
10
@Component
public class DictionaryExpressionObject {

@Autowired
private DictionaryService dictionaryService;

public List<DictionaryItem> items(String code) {
return dictionaryService.getDictionaryItemsBy(code);
}
}
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
package com.bstek.dorado.core.el;

import java.util.Map;

/\*\*
\* EL上下文中隐式变量集合的初始化器。
\* <p>
\* EL上下文中的隐式变量常常被理解为EL表达式的前缀。<br>
\* 例如,假设我们将一个{@link java.util.Date}以<code>Date</code>的前缀放入到隐式变量集合中, 即
\*
\* <pre>
\* vars.put(&quot;Date&quot;, new java.util.Date(););
\* </pre>
\*
\* 。<br>
\* 而后,我们就可以在EL表达式中这样来使用该Date对象了
\*
\* <pre>
\* ${Date.toLocaleString()}
\* </pre>
\*
\* 。
\* </p>
\* @author Benny Bao (mailto:benny.bao@bstek.com)
\* @since Mar 4, 2007
\*/
public interface ContextVarsInitializer {
/\*\*
\* 初始化隐式变量。
\* @param vars 隐式变量映射集合。其中Map的键值为隐式变量的变量名,Map的值为隐式变量自身。
\*/
void initializeContext(Map<String, Object> vars) throws Exception;
}

Reference

DictionaryContextVarsInitializer.java
https://github.com/cellbang/panda/blob/develop/panda-parent/panda-dictionary-ui/src/main/java/org/malagu/panda/dictionary/ui/el/DictionaryContextVarsInitializer.java

Ingress the account xxx@gmail cannot be used

手机科学联网,使用wifi时正常,使用3G的时候就会提示“the account xxx@gmail.com cannot be used”. Ingress运行时,会使用Google账号同步信息,所以我们要保证Google账号同步可用。 我这个情况就是因为流量防火墙禁止了”Google Play服务”在3G下访问网络。 启用之后游戏可以正常运行了。 地址:https://groups.google.com/forum/#!topic/ingress-discuss/E3S6jVMkoTk 源文: We suspect this error occurs for two reasons: 1. [Specified already above] You’re not actively synced to your Google account at the time you launch the app. Visit Menu > Settings > Accounts & sync and make sure your Google account is syncing successfully. You can usually test that sync is on and working by signing into the Google Talk app. 2. A network- or carrier-level issue. For #2, I’d recommend contacting your carrier for troubleshooting/resolution. -Bernini

由SQL where 1=1想到的字符串处理方法

字符串拆成集合简单,集合再合成字符串就有点麻烦. 对于Javascript,一个join方法就可以解决问题,可惜Java的集合没有提供join的方法. 不过强大的Java的三方库提供了类似的功能,例如

//Commons Lang:
org.apache.commons.lang.StringUtils.join(list, conjunction);

//Spring:
org.springframework.util.StringUtils.
collectionToDelimitedString(list, conjunction);

当然也可以自己写一个实现,常见的写法为

public static String join(Collection c, String delim) {
if (c == null c.size()==0) {
return “”;
}
StringBuilder sb = new StringBuilder();
Iterator it = c.iterator();
int i = 0;
while (it.hasNext()) {
if (i++ > 0) {
sb.append(delim);
}
sb.append(it.next());
}
return sb.toString();
}

总觉得循环中的if很别扭,很想把它干掉,于是有了稍稍优雅的写法:

public static String join(String delimiter, Iterable<? extends Object> objs) {
if (objs == null !objs.hasNext()) {
return “”;
}
Iterator<? extends Object> iter = objs.iterator();
StringBuilder buffer = new StringBuilder();
buffer.append(iter.next());
while (iter.hasNext()) {
buffer.append(delimiter).append(iter.next());
}
return buffer.toString();
}

双网卡按指定网卡上网

本机环境: win7 64 场景描述: 在客户公司,可以使用无线网通过http代理上外网,但不能访问内网,有线可以访问内网但是无法访问代理服务器。 代理服务器: 172.16.80.8 需要访问内网数据库:172.16.80.40 有线网网关:192.168.133.254 无线网网关:192.168.127.254 为了实现上外网的同时访问内网数据库,我打起了windows自身的route的主意。 由于代理服务器跟数据库属于同一网段,所以要给他们再划分一下子网。 8,40.我很自然的想到了32. 利用通过主机数计算子网掩码的方法可以得出224,也就是255.255.255.224. 1. 把默认路由删掉。(双网卡,所以有两条默认路由记录) route delete 0.0.0.0 2. 再添加默认路由(如果路由表中没有记录就走这个无线) route add 0.0.0.0 mask 0.0.0.0 192.168.127.254 3. 为数据库添加路由(访问172.16.80.31~172.16.80.63时使用有线) route add 172.16.80.32 mask 255.255.255.224 192.168.133.254 这样就实现同时访问内网数据库及外网。

网页转发及referrer信息

测试环境: Win7 64, IE 9.0, Chrome 21.0.1180.89 m, Firefox 15.0.1 同事制作了一个导航站, 失效点任何链接,都会返回自己的主页,而相同的代码放到本地可以正确导航.由此猜测他的域名被屏蔽了. 这种屏蔽应该是利用浏览器提供的referrer信息以实现的. 只要在网页跳转时把referrer信息清空就好了. 客户端网页跳转方法 1. meta

http://xobo.org”;
or
window.location.replace=”http://xobo.org”;

3. link(a)

jump

方法一,方法二可以轻松在IE及Firefox中, 甩掉referrer信息. 对于Chrome来说, 真是克忠职守,不管我怎么跳转它都记录下正确的referrer信息. 还好Chrome HTML5的rel = “noreferrer”属性, 使浏览器不记录referrer值. 然而IE及Firefox又不支持”noreferrer”这么一属性.把这两种综合一个,就可以了.

卸载千月(BlueSoleil)后,win7 无线网络图标变成红叉叉

蓝牙管理软件本身就不多, windows自身功能又弱, 也就无疑问的尝试了一下千月(BlueSoleil). 但是在一次偶然的卸载操作,千月(BlueSoleil)给我带来了无尽的痛苦–无线网络图标变成红叉叉. 对于功能来说没有任何影响但是就看着那个叉叉不爽, 一定要把它处理掉, 系统还原又被我关掉了. 只能硬处理了. 本以为我卸载了,它出这个叉叉,我再装回去就好了,装回去也不成. 问百度,知道上有人说是重建一下图标缓存.依旧不成. 中文无解去google.com/ncr搜英文,说什么删除设备管理器中的隐藏驱动,依旧无解. … 经无数次尝试均不成, 最后只好重装系统了. 那差不多是年前的事儿了,今天我又手贱的安装了千月(BlueSoleil)又卸载了,红叉叉又出现了,系统还原还是没有开启. 这次发现在千月有用户提出同样的问题,千月的客服回答说这个跟蓝牙个人局域网服务有关, 他们测试的时候没有问题.虽然对问题没有帮助,至少了解到是因为跟什么东西有关了. 继续问Google, 有人说删除驱动就可以了,”将非本地网卡、网线网卡的适配器全部右键卸载掉,可能包括蓝牙、1394、虚拟网卡都逐一卸载掉”.蓝牙的驱动,本地网卡驱动,无线网卡驱动,我早不知删除重装多少遍了.但是虚拟网上的驱动我一直没有动过, 总不会跟这个有关吧. 我本机装有virtualbox及vmware两个虚拟机, 用试试看的方法, 先卸载了virtualbox的网卡驱动. 无线图标闪了闪变了回正常的了.终于好了,再把virtualbox的虚拟网卡安装进来,图标依然正常.重启电脑,也没有复发.原来这个跟虚拟网卡有关. 总结: 1. 永远不要关系统盘的系统还原 2. 尝试卸载虚拟网卡 猜测: 中招的是不是都是virtualBox用户

windows7功能服务慎关闭

Q:windows7开始菜单里的搜索框怎么找回来 A:”控制面板”->”程序”->”程序和功能”->”打开或者关闭windows功能”->选中”Windows Search”,点”确定”保存设置.

Hibernate select count(*)返回值类型Integer vs Long

COUNT 返回Long对象 MAX MIN 返回类型是跟所使用的字段类型有关 AVG 返回Double SUM 如使用字段是整形,返回Long(以前是返回BigInteger),如果是浮点类型那么就返回Double.

由于接触Hibernate较晚, 一直坚定不移的相信select count(*) 的返回值的类型的是Long. 一次很偶然的机会发现在一段分页函数里发现在使用select count(*)之后拿到的对象,居然先判断是Long类型还是Integer类型。心中大惊,总不会是在不同的数据库里它的表示不一样吧,不找出原因心难安。 在csdn上看到有人提出类似问题。其中提到

关于在Hibernate里使用select count(*) 返回值的问题说明 由于我使用的是Hibernate 3.2版本,经确认,这个版本已经把以前返回 Integer的改成了 Long, 因为JPA里面的返回值规定是Long, Hibernate为了兼容这个,所以修改了返回值。 如果你从Hibernate 3.0.x/3.1.x升级到最新的3.2版,一定要注意,3.2版的很多sql函数如count(), sum()的唯一返回值已经从Integer变为Long,如果不升级代码,会得到一个ClassCastException。

应该就是正解了,但是国内的信息太多的复制粘贴了,经过大量的转发,原本正确的信息也可能变成了错误了,加上其中提到的原贴已经打不开了。我就想找到hibernate官方文档,这样才放心。 在Migrating from 3.1 to 3.2的官方文档里找到如下信息

Changed aggregation (count, sum, avg) function return types In alignment with the JPA specification the count, sum and avg function now defaults to return types as specified by the specification. This can result in ClassCastException’s at runtime if you used aggregation in HQL queries. The new type rules are described at http://opensource.atlassian.com/projects/hibernate/browse/HHH-1538 If you cannot change to the JPA compliant type handling the following code can be used to provide “classic” Hibernate behavior for HQL aggregation: Configuration classicCfg = new Configuration(); classicCfg.addSqlFunction( “count”, new ClassicCountFunction()); classicCfg.addSqlFunction( “avg”, new ClassicAvgFunction()); classicCfg.addSqlFunction( “sum”, new ClassicSumFunction()); SessionFactory classicSf = classicCfg.buildSessionFactory();

证明了为了兼容JPA,hibernate确实修改了 aggregation (count, sum, avg) function的返回值,但是文档中并没有提到说,把返回值由Integer改为Long. 根据文件中的链接“http://opensource.atlassian.com/projects/hibernate/browse/HHH-1538”。

The Java type that is contained in the result of a query using an aggregate function is as follows[33]: • COUNT returns Long. • MAX, MIN return the type of the state-field to which they are applied. • AVG returns Double. • SUM returns Long when applied to state-fields of integral types (other than BigInteger); Double when applied to state-fields of floating point types; BigInteger when applied to state-fields of type BigInteger; and BigDecimal when applied to state-fields of type BigDecimal.

这里详细的描述了各个函数的返回值类型的变化 COUNT 返回Long对象 MAX MIN 返回类型是跟所使用的字段类型有关 AVG 返回Double SUM 如使用字段是整形,返回Long(以前是返回BigInteger),如果是浮点类型那么就返回Double… 由此可知我们之后可以放心的去用Long类型来接收count(*)的返回值了。要是还不放心,我们还可以使用Number类型来接收. 没用过Number类型?

java.lang.Number The abstract class Number is the superclass of classes BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, and Short. Subclasses of Number must provide methods to convert the represented numeric value to byte, double, float, int, long, and short.

基本上所有数据类型都继承了这个Number类,而这个类又定义了longValue,doubleValue方法,这样管它Integer还是Long都是没问题的啦,而且我们还能取出我们需要的值。 将对象赋值给接口或者抽象类应该也是Java中经常用法吧。