闲暇之余仿照tonmcat中的例子测试了一下websocket,运行时却莫名奇妙的报了一个错误,查找半天无果,与原版例子对照发现了一个特囧的错误,未给构造函数添加public。
报错内容
严重: Error reading request, ignored
java.lang.IllegalArgumentException: Failed to create instance of POJO of type [test.ChatServlet]
at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:53)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:138)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:696)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.InstantiationException
at org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator.getEndpointInstance(DefaultServerEndpointConfigurator.java:38)
at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:50)
... 8 more
Caused by: java.lang.IllegalAccessException: Class org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator can not access a member of class test.ChatServlet with modifiers ""
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator.getEndpointInstance(DefaultServerEndpointConfigurator.java:36)
... 9 more
报错代码
package test;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/ChatServlet")
public class ChatServlet{
//用原子的方式增长int
private static final AtomicInteger connectionIds = new AtomicInteger();
private static final Set<ChatServlet> connections = new CopyOnWriteArraySet<ChatServlet>();
private String nickname;
private Session session;
ChatServlet(){
//getAndIncrement()以原子方式将当前值加 1
nickname = "" + connectionIds.getAndIncrement();
}
@OnOpen
public void onOpen(Session session){
this.session = session;
connections.add(this);
String msg = String.format("* %s %s", nickname, "has joined.");
//将连接的信息传送给各个客户端
ChatServlet.broadcast(msg);
}
@OnClose
public void onClose(){
connections.remove(this);
String msg = String.format("* %s %s",
nickname, "has disconnected.");
//将连接的信息传送给各个客户端
ChatServlet.broadcast(msg);
}
@OnMessage
public void onMessage(String message){
String htmlString = String.format("%s: %s",
nickname, message);
ChatServlet.broadcast(htmlString);
}
@OnError
public void onError(Throwable t){
System.out.println(t.toString());
}
private static void broadcast(String msg){
for (ChatServlet c : connections) {
try {
synchronized (c){
c.session.getBasicRemote().sendText(msg);
}
} catch (IOException e) {
connections.remove(c);
try {
c.session.close();
} catch (Exception e2) {
// TODO: handle exception
}
String message = String.format("* %s %s",
c.nickname, "has been disconnected.");
ChatServlet.broadcast(message);
}
}
}
}
报错原因
构造函数未添加public!!!
反思
构造函数要注意声明为public,若只需包内类或者子类可访问则不用添加public,构造函数最好由IDE自动生成。