Typename的使用问题
今天发现一个问题,有一个函数
foo(typename list
}
这里如果去掉typename编译有问题。 因为iterator 是一个模版。
template
class list {
typename MyIter iterator;
}
如果类似这样的定义,那么list
今天发现一个问题,有一个函数
foo(typename list
}
这里如果去掉typename编译有问题。 因为iterator 是一个模版。
template
class list {
typename MyIter iterator;
}
如果类似这样的定义,那么list
今天发现一个velocity的问题。 如果传入velocity的对象中没有对某一个field有getter
setter方法,那么即使那个field是public的,velocity也得不到值。 加上getter settter 方法,就ok了。
Win7下显示器经常黑屏。有时候从黑屏进化到蓝屏。并且右下角有如下显示:

现在支持直接黏贴图片了?
这个问题的解决的解决方法就是升级驱动。下个 驱动精灵 什么的,然后就可以修复了。
今天因为需要调用第三方的接口些fake service, 用于testcase. 该第三方使用的是soap的webservice模式。
首先是创建service。
package myws;
import java.io.IOException;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.ws.Endpoint;
/**
*
* @author 帐前卒
*
*/
@WebService(
name="HELLO",
targetNamespace="http://chillyc.info/api",
serviceName="API",
portName="PortName")
public class WebServiceHolder {
@WebMethod
@WebResult(name="return")
public String hello(@WebParam(name="name")String name) {
return "hello" + name;
}
public static void main(String[] args) throws IOException {
Endpoint.publish("http://localhost:80/fake/ws", new WebServiceHolder());
System.in.read();
}
}
这里写System.in.read();是希望服务在那里卡死。基本上所有的server都是类似死循环的写法。所以我这里就偷懒使用IO.
这里要注意的是@WebService annotation. 其中 name是指这个portType 叫什么。
targetNameSpace这个在所有的后续调用中名字都是一致的。serviceName就是服务的名称。portName
其实就是提供服务的端口名称(这里对服务本身的调用没有什么关系)。如果没有name, 那么java会默认使用WebServiceHolder
也就类名称作为name.
运行后,在浏览器中打开
http://localhost:80/fake/ws?wsdl
然后就可以看到wsdl文件。
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<!--
Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6.
-->
<!--
Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6.
-->
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://chillyc.info/api" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://chillyc.info/api" name="API">
<types>
<xsd:schema>
<xsd:import namespace="http://chillyc.info/api" schemaLocation="http://localhost/fake/ws?xsd=1"/>
</xsd:schema>
</types>
<message name="hello">
<part name="parameters" element="tns:hello"/>
</message>
<message name="helloResponse">
<part name="parameters" element="tns:helloResponse"/>
</message>
<message name="getReturnInfo">
<part name="parameters" element="tns:getReturnInfo"/>
</message>
<message name="getReturnInfoResponse">
<part name="parameters" element="tns:getReturnInfoResponse"/>
</message>
<portType name="HELLO">
<operation name="hello">
<input message="tns:hello"/>
<output message="tns:helloResponse"/>
</operation>
<operation name="getReturnInfo">
<input message="tns:getReturnInfo"/>
<output message="tns:getReturnInfoResponse"/>
</operation>
</portType>
<binding name="PortNameBinding" type="tns:HELLO">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="hello">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="getReturnInfo">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="API">
<port name="PortName" binding="tns:PortNameBinding">
<soap:address location="http://localhost/fake/ws"/>
</port>
</service>
</definitions>
大家自己对照刚才的那些name, serviceName等,在wsdl文件中的什么地方。
然后是写一个stub作为调用的接口。
package myws;
import javax.jws.WebParam;
import javax.jws.WebService;
/**
*
* @author 帐前卒
*
*/
@WebService(targetNamespace = "http://chillyc.info/api", name="HELLO")
public interface WebServiceAPI {
String hello(@WebParam(name="name")String name);
}
这里要注意的是 那个hello函数,必须与webService发布的函数名相一致(要看wdsl文件中的名字。)
另外WebParam中的name也需要和发布函数中的参数名字一致。
这里WebService中传入了两个值。其中name就是刚才WebService中的name. 其实就是wsdl中的portType.
如果这里写错了。就会有Undefined port type:{http://chillyc.info/api}Name. 这个错误。所以要小心。
另外写个可执行的类。
package myws;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
/**
*
* @author 帐前卒
*
*/
public class Client {
public static void main(String[] args) throws MalformedURLException {
WebServiceAPI api = Service.create(
new URL("http://localhost:80/fake/ws?wsdl"),
new QName("http://chillyc.info/api", "API"))
.getPort(WebServiceAPI.class);
System.out.println(api.hello("sss"));
}
}
这里URL中的就是wsdl文件的地址。 QName传入的就是targetNamespace 和 serviceName.
另外getPort就填入刚才的stub. 然后直接调用stub中的接口就能得到结果。
done.
简单快速,搭建和写client 也就是10分钟搞定。当然这只是起步
这个方法适用于JDK6及以上,其他版本未知。
开启JVM的远程Debug模式, 在启动JVM的时候加上参数:
// 非阻塞方式,这样启动jvm后,可以再任意时间attach到server上
-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=11312,server=y,suspend=n
// 阻塞debug,启动JVM后,需要远程连接attach到相应的端口,JVM才会继续执行。
-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=11312,server=y,suspend=y
第二条特别适合调试类初始化的程序模块。
在eclipse中,bug项里有Debug Configurations… 选中。然后选中remove java application, 新建一个
Project就是你要远程调试的 JAVA源码文件工程。 HOST就是那个server所在的机器名或者IP。 PORT就是
上面的address项11312。Connection Type就写Standard. 然后点击debug就可以。
如果debug后,有连接错误。 1. 要查看server或者service是否已经启动。 2. 要看是否配置正确。3.检测端口是否被其他程序占用了。
如果上面的检测完毕,还是连接失败。那么重启eclipse 或者 重启server. 这两个方法就可以解决问题。
另外
-Xnoagent
这一个选项在远程debug中一般不需要。其含义为Disables VM support for oldjdb。禁用旧的java debug。
下面是各个options的详解。摘自
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/jdb.html
-Xdebug
Enables debugging support in the VM
-Xrunjdwp:transport=dt_shmem,server=y,suspend=n
Loads in-process debugging libraries and specifies the kind of connection to
be made.
-Xnoagent
Disables VM support for ** oldjdb **
-Djava.compiler=NONE
Disables the JIT compiler. This is required for debugging under the classic VM
有人曾问 帐前卒 一道题:至少需要多少个砝码,才能称出1~50g物体?
这道题有两个变种:
1.至少需要多少砝码(左物右码),才能称出1~50g物体?
2.至少需要多少砝码(砝码可以放在任意一边),才能称出1~50g物体?
第一问可以变为: 至少多少个数字相加,可以表示1~50之间的任意数。又可以演变为:如何快速的从一堆苹果中取出你想要的个数?
第一问对于每个数字其实就是两种状态,加、不加。也就是1,0. 对应的公式就是,对于任意数x
x = 1*a0 + 2*a1 + 4*a2...+2^k*ak (a0...ak 可取0或者1)
也就是计算机界常见的2进制表示法。当全部ai都取1时,那么1+2+4…+2^k = 2^(k+1) - 1 >= x, 将x=50带入,k+1即为所求。
所以第一问的答案就是 log(50+1) 取上整
帐前 卒 这样解决了第一问,那么第二问应该就是第一问的变种。
因为砝码可以放左边、右边、不放。那么就有三种状态(-1,1,0). 这就是如何用三种状态来标示一个数。那么
x = 1*a0 + 3*a1 + 9*a2 + ... + 3^k*ak 其中ai可以取-1,0,1
当全部ai都取1时,那么1+3+9…+3^k = (3^(k+1) - 1)/2 >=x, 把x=50带入,那么k+1即为所求
所以第二问的答案是 log3(x*2+1) 取上整 为 5
帐 前 卒 又想起快速幂级运算
a^k 如果一次乘个a,那么需要乘k次。如果使用二分法 那么 只需要乘log(k)取上整次就可以做完。
a^0
a^1
a^2
a^3
a^4
a^5
1
a^1
a^2
a1*a^2
1*a^4
a^1 * a^4
这样表示就会发现其实a^k 其实就是把k表示为2进制的形式。
5 就是 101 就是 a^1 * a^4
下面写就比较好写程序了。
total=1; // total就是所求,k就是幂,a就是底数
while(k) {
if (k&1) total*=a;
a*=a;
k>>=1;
}
因为新版的采用的HTTPS的方式。更加安全。但是国内的一些DNS运营商,似乎对HTTPS的方法做了特殊处理。
这里要再感谢Google的8.8.8.8 DNS.
如果自家网络实在链接不上 https://note.youdao.com ,
那么配置一下自己的DNS,改为8.8.8.8,而不要使用的默认的。就可以链接成功。
windows 下设置:
对于宽带拨号用户,在“设置”-“网络连接”中找到宽带上网的连接,打开网络连接属性,选择Interner协议( TCP/IP
)(win7与vista的用户请选择TCP/ IPv4
协议)的属性页里,不要选择自动获取DNS,而要选择“使用下面的DNS服务器地址”,首选DNS服务器和备用DNS服务器分别设置为
8.8.8.8和8.8.4.4,完成后断开网络重新连接上网即可。如图所示:
然后就可以访问了…
如果还不行记得清理一下DNS缓存: 命令如下
ipconfig /flushdns
最近在整理登陆模块的数据兼容和服务兼容。有几点值得注意的地方:
1. 数据库表格式不一致。这需要格式转换非常令人头痛。
2. 旧服务不下线,新服务上线后,新的验证机制旧的server不兼容。新验证与旧的验证难以分离。web端和其他各端使用的验证方式不一致,或者说发布/更新速
度不一致。
3. 新的cookie会通过某些途径进入到web端。我x
4. 新的服务在某些情况下,需要依赖旧的服务。
这真是令人头痛的一件事。
解决方法:
1. 新服务在旧服务之前做验证,或者在认证串中加入版本信息。
2. 新server引入旧服务的所有表,但是只读。不能通过引入表解决的。在旧的server上加http等接口同时限制ip.新server访问这些接口。
3. nginx 将旧接口映射到新接口。
另外需要开始时,设计好错误码,错误码一旦冲突,并且各个客户端使用了,这就不好办了。另外各个客户端也需要对新旧认证做兼容处理。悲催呀.
简单的看interrupt其实是设置了一个变量。除非有wait(), join(),
sleep()等方法,否则调用interrupt()方法,是没有什么效果的。
stop()确实是终止一个线程的方法。并且终止后,的确回收了部分资源。这里要看资源是什么,如果是socket, 和IO流等,这里需要自己去close().如
果你觉得自己每次在调用的地方写麻烦,那就在线程的finalize()方法里定义如果回收IO流/Socket流/数据库连接等。
另外如果希望在一个线程中杀掉另外一个线程,还是推荐使用stop()方法,虽然java文档中说这个方法很不安全,并且以后在更高级的版本中不再提供该方法。
终止一个线程的方法, 帐前卒 觉得有如下几种:
1. 设置volatile变量或者普通一个全局变量。volatile的好处是保证了不会被java
compiler优化,也就是不会调整语句的执行顺序。例如:
if (a == null) {
synchronized(a) {
if (a == null) {
a = new instance();
}
}
}
上面的语句很有可能被编译器优化为
if (a == null) {
synchronized(a) {
a = new instance();
if (a == null) {
}
}
}
这个在java 1.6以上版本反正是支持volatile关键字的。
一般这样终止线程
while(value) {
// do something
}
// 另外一个线程,会修改value这个bool变量。
2. 使用wait(), join(), sleep()等方法:
public void run() {
try {
while(true) {
// do something
wait();
}
} catch(Exception e){}
}
外面拿到这个线程的reference就可以执行 thread.interrupt(); 这样线程就终止了。
3. 直接执行thread.stop() 方法。
如果// do something这个执行语句中有一个未知的方法,这个方法执行的时间较长以及消耗内存较大。那么如果监控到内存消耗超过一定值,就应该把这个线程
kill掉。那么上面两种方法是无论如何都做不到的。只能只用stop()方法。但stop()方法的劣势也在java doc中有详尽的说明。 帐 前卒
这里就不多说了。
之前发现4.0.8中可能存在milti-part的数据无法传递到service中。后来就迁移了。
另外发现有时resin中webapp目录中有些文件会自动重建。即使删除了各种cache和数据,只要resin重启,必然,那个目录中的文件就出现了。
解决这种情况的方式:
1. 杀掉resin进程,删除掉xxx.war 和xxx那个文件夹。
2. 将新的xxx.war放入到resin中
3. 重启resin