Unable to convert string [${xxxx}] to class [java.util.Date] for attribute [value]: [Property Editor not registered with the PropertyEditorManager]

 java, tomcat  Unable to convert string [${xxxx}] to class [java.util.Date] for attribute [value]: [Property Editor not registered with the PropertyEditorManager]已关闭评论
4月 162021
 

使用intellj idea 启动tomcat测试一个简单war包,测试里面一个spring mvc 页面, 使用jstl方式时出现一个怪问题,记录下:

 

index.jsp页面内容如下:

<%@ page import="java.util.Date" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Index</title>
</head>
<body>
<p>
    Hello Spring MVC!!!
</p>
<p>
    <%
        Date now1 = new Date();
        %>
    服务器时间1: <fmt:formatDate value="<%=now1%>" pattern="yyyy-MM-dd HH:mm:ss" />
</p>
<p>
    服务器时间2: <fmt:formatDate value="${now2}" pattern="yyyy-MM-dd HH:mm:ss" />
</p>

</body>
</html>

IndexController内容:
@Controller
public class IndexController {

    @RequestMapping(value = {"", "/index"})
    public ModelAndView dicts() {
        ModelAndView mv = new ModelAndView("index");
        mv.addObject("now2", new Date());
        return mv;
    }
}

测试结果,出现错误:
Unable to convert string [${now2}] to class [java.util.Date] for attribute [value]: [Property Editor not registered with the PropertyEditorManager]

如果把jsp页面中  “服务器时间2xxxx”  这行注释掉又一切正常,这就奇怪了。

后来在网上找到解决方案:发现有由于web.xm声明的问题:

原来声明:
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

这样写有问题,修改为:

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         metadata-complete="true" version="3.0">
。。。。
</web-app>

便不会出现这个问题了。网上有说是因为Tomcat的支持web.xml的Servlet是2.5版本。

记录下!

DONE!


 

一次java war包在tomcat启动后服务乱码问题解决

 java, tomcat  一次java war包在tomcat启动后服务乱码问题解决已关闭评论
3月 312021
 

一个运行于tomcat下的war包,忽然服务出现了乱码,问题排查如下:

  • 检查点一:
  • 1. 检查tomcat 的config目录下server.xml 文件:

<Connector ……
redirectPort=”443″ URIEncoding=”UTF-8″ />, 发现问题不在这里

 

  • 检查点二:
  • 2.1. 命令行下执行: ps -ef | grep java  获取java运行所在的pid为6724

[root@ip-172-xx-xx]# ps -ef | grep java
root 6724 1 3 14:30 pts/0 00:01:04 /usr/local/jdk/bin/java –

  • 2.2. 查看问题机器的jvm的编码格式

[root@ip-172-xxxx]# jinfo 6724 |grep enc
sun.jnu.encoding = ANSI_X3.4-1968
file.encoding.pkg = sun.io
sun.io.unicode.encoding = UnicodeLittle
file.encoding = ANSI_X3.4-1968

果然问题出在这里。 可以在tomcat的bin目录下的catalina.sh,添加给 JAVA_OPTS 的多添加两个参数

-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8

重启tomcat,DONE!

 

 

 

tomcat 安装配置apr

 tomcat  tomcat 安装配置apr已关闭评论
12月 302016
 

tomcat的运行模式有3种.修改他们的运行模式.3种模式的运行是否成功,可以看他的启动控制台,或者启动日志.或者登录他们的默认页面http://localhost:8080/查看其中的服务器状态。 

1)bio 

默认的模式,性能非常低下,没有经过任何优化处理和支持. 

2)nio 

利用java的异步io护理技术,no blocking IO技术. 

想运行在该模式下,直接修改server.xml里的Connector节点,修改protocol为 

 <Connector port="80" protocol="org.apache.coyote.http11.Http11NioProtocol" 
	connectionTimeout="20000" 
	URIEncoding="UTF-8" 
	useBodyEncodingForURI="true" 
	enableLookups="false" 
	redirectPort="8443" /> 

启动后,就可以生效。 

3)apr 

安装起来最困难,但是从操作系统级别来解决异步的IO问题,大幅度的提高性能. 

必须要安装apr和native,直接启动就支持apr。下面的修改纯属多余,仅供大家扩充知识,但仍然需要安装apr和native 

如nio修改模式,修改protocol为org.apache.coyote.http11.Http11AprProtoco

tomcat如何支持apr?

需要安装apr, apr-util,   openssl, tomcat-native(tomcat-native包在tomcat目录的bin目录下就有源码的压缩包,解压这个包,注意下版本,也可以在http://tomcat.apache.org/download-native.cgi下载,并在http://tomcat.apache.org/native-doc/miscellaneous/changelog.html中查看下支持的openssl和apr版本,然后到对应的网站下载适合的版本)

1. 从网站 http://apache.spd.co.il/apr/ 中下载apr-xxx.tar.gz

tar zxvf apr-1.xx.xx.tar.gz

cd apr-xxx

./configure

make && make install

默认安装在/usr/local/apr目录下,可以通过命令行参数 –prefix 指定,建议不要改。

2. 从网站 http://apache.spd.co.il/apr/ 中下载apr-util-xxx.tar.gz

tar zxvf apr-util-xxx.tar.gz

cd apr-util-xxx

./configure –with-apr=/usr/local/apr     (此处路径就是上面俺转apr的路径)

make && make install


3.  openssl安装,其实linux版本一般都自带openssl,可以通过命令: openssl version查看版本,如果太低,可以

https://www.openssl.org/source/下载openssl-xx.tar.gz包编译安装

tar zxvf openssl-xx.tar.gz

cd openssl-xx

./config

make && make install (默认安装在/usr/local/ssl/)


4.  安装tomcat-native ,建议使用tomcat自己bin目录下的tomcat-native.tar.gz,

 解压, 

tomcat-native-1.1.27-src的版本进入jni/native目录,查看 BUILDING文件,可以有详细的说明

tomcat-native-1.2.10-src的版本直接进入native目录,查看BUILDING文件,有详细的说明

在native目录下,输入

configure –with-apr=/usr/local/apr –with-ssl=/usr/local/ssl  

其中/usr/local/apr 和 /usr/local/ssl分别是上面安装的apr和openssl目录。

安装完成有提示文字告诉你安装到的位置, 上面路径默认安装在/usr/local/apr/lib


配置tomcat,其实在BUILDING文件有说明,具体是:

Using it in Tomcat
——————

1. In <Connector> use of conf/server.xml:
   protocol=”org.apache.coyote.http11.Http11AprProtocol”
2. In bin/setenv.sh add the following:
   CATALINA_OPTS=”$CATALINA_OPTS -Djava.library.path=/usr/local/apr/lib”
   

 tomcat下没有bin/setenv.sh 文件就新建一个,并有可执行权。



启动tomcat , 看到如下信息: 

信息: Starting ProtocolHandler [“http-apr-8080”]

成功!

关于openssl配置(单向):

单向SSL的概念:

客户端向服务器发送消息,服务器接到消息后,用服务器端的密钥库中的私钥对数据进行加密,然后把加密后的数据和服务器端的公钥一起发送到客户端,客户端用服务器发送来的公钥对数据解密,然后在用传到客户端的服务器公钥对数据加密传给服务器端,服务器用私钥对数据进行解密,这就完成了客户端和服务器之间通信的安全问题,但是单向认证没有验证客户端的合法性。

 

不使用apr情况:

(1)产生密钥库
keytool -genkeypair -alias tomcat -keyalg RSA -keysize 1024 -validity 365 -keystore /usr/local/apache-tomcat-6.0.18/keystore

(2)在Connector上配置密钥库
<Connector port=”8443″ protocol=”HTTP/1.1″ SSLEnabled=”true”
               maxThreads=”150″ scheme=”https” secure=”true”
               clientAuth=”false” sslProtocol=”TLS” keystoreFile=”/usr/local/tomcat/conf/keystore” keystorePass=”123456″/>

 

使用apr情况:

(1)产生密钥库

openssl genrsa -out rsa-private-key.pem 1024
openssl req -new -x509 -nodes -sha1 -days 365 -key rsa-private-key.pem -out self-signed-cert.pem

(2)在Connector上配置密钥库

<Connector port=”8443″ protocol=”HTTP/1.1″ SSLEnabled=”true”
               maxThreads=”150″ scheme=”https” secure=”true”
               clientAuth=”false” sslProtocol=”TLS” 
               SSLCertificateKeyFile=”/usr/local/tomat/rsa-private-key.pem”
               SSLCertificateFile=”/usr/local/tomat/self-signed-cert.pem”/>

 

出现:

Failed to initialize end point associated with ProtocolHandler ["http-apr-8443"]
java.lang.Exception: Connector attribute SSLCertificateFile must be defined when using SSL with APR

可以将: protocol=“HTTP/1.1″修改为  protocol=”org.apache.coyote.http11.Http11Protocol”, 之修改https的端口,不要修改原来支持apr的http的protocol

Intellj IDEA中发布应用, (exploded): Server is not connected. Deploy is not available.问题解决

 tomcat  Intellj IDEA中发布应用, (exploded): Server is not connected. Deploy is not available.问题解决已关闭评论
12月 302016
 

Intellj IDEA中发布应用到tomcat中 出现如下提示:Artifact Gradle : xx.xx : xx.war (exploded): Server (exploded): Server is not connected. Deploy is not available

分析:

由于IDE会设置 JVM 启动参数JAVA_OPTS用于JMX的监听,而启动的tomcat中对JAVA_OPTS有配置参数(比如在setenv.sh/ catalina.sh/ startup,sh), 而且在写参数的过程中使用了下面的写法:


比如在setenv.sh文件中:

错误写法:

export JAVA_OPTS="-XX:MaxPermSize=512m -Xmx1024m"

正确写法:

export JAVA_OPTS="$JAVA_OPTS -XX:MaxPermSize=512m -Xmx1024m"

记得加上

$JAVA_OPTS

这样就不会覆盖了, done。


网上所谓的删除setenv,sh文件方法只是治标不治本。

关于tomcat下无法生成localhost、manage等logging.properties中配置文件问题解决

 tomcat  关于tomcat下无法生成localhost、manage等logging.properties中配置文件问题解决已关闭评论
12月 092016
 

今日有同事提到某机器的tomcat启动后无法产生localhost文件,但catalina.out和localhost.access等访问文件却都可以产生,奇怪了。

比较可以产生和不能产生的两台机器,发现logging.properties等配置都是一样的,但就是logging.properties配置的文件似乎都无法产生,后来经过排查,发现classpath不同, 在不能产生localhost文件的机器上的classpath前多了一些类似“ /usr/local/jdk/lib:/usr/local/jdk/jre/lib ” 的数据。

原来运维为了配置环境变量,在tomcat的bin目录下添加了一个setenv.sh的配置文件,这个文件在catalina.sh运行时会判断如果有这个文件就会执行(见catalina.sh文件), 而setenv.sh配置了这样语句命令export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib。删除这条命令即可, 或者不要使用自定义的setenv.sh。

问题分析:

打开catalina.sh文件, 可以看到tomcat在启动时在catalina.sh中实际会给classpath添加 tomcat-juli.jar包,这个jar包用于解析logging.properties并生成对应的文件如:localhost、manager等文件, 但在如果在classpath中配置了jdk/jre的lib路径, 并且配置在 tomcat-juli.jar之前, 那么估计jdk/jre下默认的logger实现将接管日志打印,因此logging.properties中的配置就失效了,因此也产生不出localhost等文件了



使用tomcat的compression来提高网页加载速度

 tomcat  使用tomcat的compression来提高网页加载速度已关闭评论
11月 172015
 

启用tomcat的压缩,效果不错。

 

当网站从服器端请求的数据较大时,在有限的带宽下就会造成浏览器加载缓慢,有时候会造成页面没有响应,使用户体验变得很差,tomcat为我们提供了有效的解决了办法,就是使用压缩来解决传输问题。

        tomcat使用HTTP/1.1 GZIP 来压缩,以减少带宽压力,
       首先介绍下gzip:
        HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。这一般是指WWW服务器中安装的一个功能,当有人来访问这个服务器中的网站时,服务器中的这个功能就将网页内容压缩后传输到来访的电脑浏览器中显示出来.一般对纯文本内容可压缩到原大小的40%.这样传输就快了,效果就是你点击网址后会很快的显示出来.当然这也会增加服务器的负载. 一般服务器中都安装有这个功能模块的.
      我们使用简单的例子来介绍tomcat的压缩使用:(使用firebug查看请求情况)

 首先是一个简单的servlet:
内容:

public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType(“text/html”);
        PrintWriter out = response.getWriter();
        out
                .println(“<!DOCTYPE HTML PUBLIC \”-//W3C//DTD HTML 4.01 Transitional//EN\”>”);
        out.println(“<HTML>”);
        out.println(”  <HEAD><TITLE>A Servlet</TITLE></HEAD>”);
        out.println(”  <BODY>”);
        out.print(” <select> “);
        for (int i = 0; i < 100000; i++) {
            out.print(“<option>testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest”+i+”</option>”);
        }

        out.println(“</select>”);
        out.println(”  </BODY>”);
        out.println(“</HTML>”);
        out.flush();
        out.close();
    }

我们将输出一个十万个选项的下拉框,在不使用的压缩的时候:

    请求数据达到9m ,大概的计算下我的下载用时(4m长城宽带):9*1024/(4*1024/8)=18m  ,加上多人共享带宽,也就是差不多20m。firebug显示20.96。

    这个速度网站体验肯定是很差的,接下来使用tomcat的压缩以后看看:

   当然是要对其进行配置:
   有以下几个参数可以使用:

    compression=”on” 
是否启用压缩 on为启用(文本数据压缩) off为不启用, force 压缩所有数据
compressionMinSize1=”2048″ 
当超过最小数据大小才进行压缩
 noCompressionUserAgents=”gozilla, traviata” 
哪些客户端发出的请求不压缩,默认是不限制
compressableMimeType=”text/html,text/xml,text/javascript,text/css,text/plain”
配置想压缩的数据类型,默认是 text/html,text/xml,text/plain

配置以后是这样的:

<Connector port=”8088″ protocol=”HTTP/1.1″ 
               connectionTimeout=”20000″ 
               redirectPort=”8443″
               compression=”on” 
               compressionMinSize1=”2048″ 
               noCompressionUserAgents=”gozilla, traviata” 
               compressableMimeType=”text/html,text/xml,text/javascript,text/css,text/plain”/>

启动后再看:

 

这次数据被压缩到274.7k,响应速度也减少了一半,当然,服务器的数据压缩和浏览器的数据解压都需要使用时间。


详细的compression配置可参考tomcat 官网:http://tomcat.apache.org/tomcat-7.0-doc/config/http.html


转自:http://www.blogjava.net/freeman1984/archive/2010/09/15/332121.html

tomcat 7 下修改session默认cookie名JSESSIONID

 apache, tomcat, 未分类  tomcat 7 下修改session默认cookie名JSESSIONID已关闭评论
6月 052015
 

看看下面这个配置:

<Context path=”” docBase=”D:WORKDIRoschinawebapp” reloadable=”false” sessionCookiePath=”/” sessionCookieName=”OUU_SESSION”/>

原来 J2EE 应用所使用的 Session 对应的是一个名为 JSESSIONID 的 Cookie ,现在在 Tomcat 7 中你可以修改这个 Cookie 的名称、PATH了

如没有指定到项目,使用下面到配置:

<Context  sessionCookiePath=”/” sessionCookieName=”OUU_JSESSIONID”>

解决TOMCAT7 JSP AJAX 提交中文乱码

 tomcat  解决TOMCAT7 JSP AJAX 提交中文乱码已关闭评论
3月 242015
 

只要修改tomcat7  目录conf/server.xml文件,

找到<Connector节点,添加URIEncoding=”UTF-8″,就OK了,如下:

 <Connector port=”8080″ protocol=”HTTP/1.1″
               connectionTimeout=”20000″
               redirectPort=”8443″ URIEncoding=”UTF-8″/>

tomcat access log (同时打印header,cookie, attibute等信息)

 java, tomcat  tomcat access log (同时打印header,cookie, attibute等信息)已关闭评论
1月 302015
 

配置tomcat access log

Tomcat的访问日志是靠org.apache.catalina.valves.AccessLogValve来控制的,你可以修改$tomcat/conf/server.xml来启用它 ($tomcat是Tomcat安装的目录)。AccessLogValve默认应该是注释掉的,简单的将其注释去掉,然后重启Tomcat就可以了。

以下是Tomcat默认的配置:

<Valve className=“org.apache.catalina.valves.AccessLogValve”
directory=“logs” prefix=“localhost_access_log.” suffix=“.txt”
pattern=“common” resolveHosts=“false”/>

你可以设置日志保存的目录(directory),日志的文件名的前缀(prefix),后缀(suffix)和日志的具体格式。保存目录,文件名的前缀、后缀都很简单,一般默认设置也就可以了。resolveHost出于性能的考虑,一般也设为false. 但访问日志的格式(pattern)却有很多的选项供你选择。以下列出了一些基本的日志格式项:

  • %a – 远程主机的IP (Remote IP address)
  • %A – 本机IP (Local IP address)
  • %b – 发送字节数,不包含HTTP头,0字节则显示 ‘-’ (Bytes sent, excluding HTTP headers, or ‘-’ if no bytes
    were sent)
  • %B – 发送字节数,不包含HTTP头 (Bytes sent, excluding HTTP headers)
  • %h – 远程主机名 (Remote host name)
  • %H – 请求的具体协议,HTTP/1.0 或 HTTP/1.1 (Request protocol)
  • %l – 远程用户名,始终为 ‘-’ (Remote logical username from identd (always returns ‘-’))
  • %m – 请求方式,GET, POST, PUT (Request method)
  • %p – 本机端口 (Local port)
  • %q – 查询串 (Query string (prepended with a ‘?’ if it exists, otherwise
    an empty string)
  • %r – HTTP请求中的第一行 (First line of the request)
  • %s – HTTP状态码 (HTTP status code of the response)
  • %S – 用户会话ID (User session ID)
  • %t – 访问日期和时间 (Date and time, in Common Log Format format)
  • %u – 已经验证的远程用户 (Remote user that was authenticated
  • %U – 请求的URL路径 (Requested URL path)
  • %v – 本地服务器名 (Local server name)
  • %D – 处理请求所耗费的毫秒数 (Time taken to process the request, in millis)
  • %T – 处理请求所耗费的秒数 (Time taken to process the request, in seconds)

你可以用以上的任意组合来定制你的访问日志格式,也可以用下面两个别名common和combined来指定常用的日志格式:

  • common – %h %l %u %t “%r” %s %b
  • combined –
    %h %l %u %t “%r” %s %b “%{Referer}i” “%{User-Agent}i”

另外你还可以将cookie, 客户端请求中带的HTTP头(incoming header), 会话(session)或是ServletRequest中的数据都写到Tomcat的访问日志中,你可以用下面的语法来引用。

  • %{xxx}i – 记录客户端请求中带的HTTP头xxx(incoming headers)
  • %{xxx}c – 记录特定的cookie xxx
  • %{xxx}r – 记录ServletRequest中的xxx属性(attribute)
  • %{xxx}s – 记录HttpSession中的xxx属性(attribute)
  • %{xxx}o 响应headers的信息

比如下面是实际的一个访问日志格式的配置:

<Valve className=“org.apache.catalina.valves.AccessLogValve”
directory=“logs” prefix=“phone_access_log.” suffix=“.txt”
pattern=“%h %l %T %t %r %s %b %{Referer}i %{User-Agent}i MSISDN=%{x-up-calling-line-id}i”resolveHosts=“false”/>

其中日志格式(pattern)指定为”%h %l %T %t %r %s %b %{Referer}i %{User-Agent}i MSISDN=%{x-up-calling-line-id}i“,则实际的访问日志中将会包括:

  • %h – 远程主机名
  • %l – 远程用户名,始终为 ‘-’
  • %T – 处理请求所耗费的秒数
  • %t – 访问日期和时间
  • %r – HTTP请求中的第一行
  • %s – HTTP状态码
  • %b – 发送字节数,不包含HTTP头(0字节则显示 ‘-’)
  • %{Referer}i – Referer URL
  • %{User-Agent}i – User agent
  • MSISDN=%{x-up-calling-line-id}i – 手机号

实际的访问日志如下:

xxx.xxx.xx.xxx – 0.270 [14/Jul/2008:13:10:53 +0800] POST /phone/xxx/gprs HTTP/1.1 200 91812 – SonyEricssonW890i/R1EA Profile/MIDP-2.1 Configuration/CLDC-1.1 MSISDN=11111111111

… …

xxx.xxx.xx.xxx – 0.083 [14/Jul/2008:21:20:55 +0800] POST /phone/xxx/gprs HTTP/1.1 200 404 – SonyEricssonW910i/R1FA Profile/MIDP-2.1 Configuration/CLDC-1.1 MSISDN=11111111111

更详细的信息,可参考: http://tomcat.apache.org/tomcat-7.0-doc/config/valve.html#Access_Logging

websock的programmatically及 annotations编写方式介绍(tomcat websocket example)

 java, tomcat  websock的programmatically及 annotations编写方式介绍(tomcat websocket example)已关闭评论
1月 212015
 

虽然是英文的资料,但应该都能看懂, 介绍了使用注解和程序方式编写websock。 对于理解tomcat下websock sample会很有帮助

JSR 356 defines Java API for WebSocket 1.0. It defines a standard-based programming model for creating WebSocket client and server endpoint. Both kind of endpoints can be created programmatically or using annotations. This Tip OfThe Day (TOTD) provide short snippets of how to write a WebSocket client and server endpoint programmatically or using annotations.

The complete source code in this sample can be downloaded from here.

Lets start with annotation-based server endpoint.

@ServerEndpoint(“/websocket”)
public class MyEndpoint {
    
  @OnMessage
  public String echoText(String name) {
    return name;
  }
}

@ServerEndpoint marks the POJO as a WebSocket server endpoint. URI of the deployed endpoint is as valueattribute of the annotation.  echoText method is invoked whenever a message with text payload is received by this endpoint. Payload of the message is mapped to the parameter name. A synchronous response is returned to the client using the return value.

Programmatic server endpoint can be defined as:

public class MyEndpoint extends Endpoint {

  @Override
  public void onOpen(final Session session, EndpointConfig ec) {
    session.addMessageHandler(new MessageHandler.Whole<String>() {

      @Override
      public void onMessage(String text) {
        try {
          session.getBasicRemote().sendText(text);
        } catch (IOException ex) {
          Logger.getLogger(MyEndpoint.class.getName()).log(Level.SEVERE, null, ex);
        }
      }
  });
}

A programmatic server endpoint is defined by extending Endpoint abstract class. onOpen method is overridden to be notified of when a new conversation has started. Session captures the other end of the conversation.EndpointConfig identifies the configuration object used to configure this endpoint. Multiple MessageHandlers are registered to handle text, binary, and pong messages. The first parameter of onOpen captures the other end of the conversation. A synchronous response to the client is sent by calling getBasicRemote().sendText(…) method.

Programmatic server endpoint needs to be configured using ServerApplicationConfig.

public class MyApplicationConfig implements ServerApplicationConfig {

  @Override
  public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> set) {
    return new HashSet<ServerEndpointConfig>() {
      {
        add(ServerEndpointConfig.Builder
            .create(MyEndpoint.class, “/websocket”)
            .build());
      }
    };
  }

  @Override
  public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> set) {
    return Collections.emptySet();
  }
}

WebSocket runtime scans the WAR file with all implementations of ServerApplicationConfig and registers the endpoint returned from getEndpointConfigs and getAnnotatedEndpointClasses. The URI of the server endpoint is published using ServerEndpointConfig.Builder.

Now lets take a look at annotated client endpoint.

@ClientEndpoint
public class MyClient {
  @OnOpen
  public void onOpen(Session session) {
    try {
      String name = “Duke”;
      System.out.println(“Sending message to endpoint: ” + name);
      session.getBasicRemote().sendText(name);
    } catch (IOException ex) {
      Logger.getLogger(MyClient.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
}

@ClientEndpoint marks the POJO as a WebSocket client endpoint. onOpen method is invoked whenever a new WebSocket connection is opened and is identified by @OnOpen annotation. Session captures the other end of the conversation. A synchronous message is sent to the server using session.getBasicRemote.sendText() method.

This client can connect to the endpoint as:

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String uri = “ws://localhost:8080” + request.getContextPath() + “/websocket”;
container.connectToServer(MyClient.class, URI.create(uri));

And finally programmatic client endpoint.

public class MyClient extends Endpoint {
  @Override
  public void onOpen(final Session session, EndpointConfig ec) {
    session.addMessageHandler(new MessageHandler.Whole<String>() {

      @Override
      public void onMessage(String text) {
        System.out.println(“Received response in client from endpoint: ” + text);
      }
  });
  try {
    String name = “Duke”;
      System.out.println(“Sending message from client -> endpoint: ” + name);
      session.getBasicRemote().sendText(name);
    } catch (IOException ex) {
      Logger.getLogger(MyClient.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
}

The first parameter of onOpen captures the other end of the conversation.  EndpointConfig identifies the configuration object used to configure this endpoint. Multiple MessageHandlers are registered to handle text, binary, and pong messages. onMessage method is called whenever a message is received from the endpoint. A synchronous request to the server is sent by calling getBasicRemote().sendText(…) method.

This client can connect to the endpoint as:

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String uri = “ws://localhost:8080” + request.getContextPath() + “/websocket”;
container.connectToServer(MyClient.class, 
                null,
                URI.create(uri));

Now go download your GlassFish b82samples source code, and run them.

tomcat启动错误:The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact. 分析解决

 tomcat  tomcat启动错误:The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact. 分析解决已关闭评论
12月 092014
 

启动tomcat是报以下错误:

INFO: Illegal access: this web application instance has been stopped already.  Could not load com.xxx.xxx.xxxxxxx.  The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.

java.lang.IllegalStateException
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1566)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)

看日志以为是“com.xxx.xxx.xxxxxxx”类加载异常,其实这个只是现象,不不是真正引起问题的原因。

可以查看 tomcat目录/logs/localhost.年-月-日.log的文件,这个文件中会描述正真的错误原因, good luck!

eclipse 远程调试 jetty/tomcat

 eclipse, MAVEN, tomcat  eclipse 远程调试 jetty/tomcat已关闭评论
3月 142014
 

A:

1.在eclipse的run configurations中创建一个maven build,选择好Maven工程,在Goals一栏中输入jetty:run。然后进入“jre”Tab,在vm arguments一栏中输入-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n

2.打开debug configuration,创建一个remote java application,在host中输入服务器地址,一般就本机localhost。在port一栏中输入上面配置中端口号8000。这样,当服务器启动后,就可以进行远程debug了。这种debug方式的好外是可以在debug依赖的jar包,并在上面设置断点。(前提是你已经获得了jar包的源代码)

 

B:

如果是Tomcat,只需要在tomcat/bin/的catalina.bat文件的开头加入下面的设置即可:

SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000

然后在eclipse新建一个remote debug,端口填入8000即可。

tomcat使用 websocket时maven配置

 MAVEN, tomcat  tomcat使用 websocket时maven配置已关闭评论
12月 312013
 

最近项目需使用到 tomcat websocket,发现配置时总报错,通过引用外部的lib却报错“The hierarchy of the type ‘Class name’ is inconsistent”。 后来查网上资料有解决,记下来供参考:

<dependency>
   <groupId>org.apache.tomcat</groupId>
   <artifactId>tomcat-catalina</artifactId>
   <version>7.0.39</version>
   <scope>provided</scope>
</dependency>
 
  <dependency>
   <groupId>org.apache.tomcat</groupId>
   <artifactId>tomcat-coyote</artifactId>
   <version>7.0.39</version>
   <scope>provided</scope>
</dependency>

配置tomcat访问日志

 tomcat  配置tomcat访问日志已关闭评论
12月 162013
 

记录下,备用

打开tomcat 的conf目录下server.xml文件,在 <Host> </Host>间添加


 <Valve className=”org.apache.catalina.valves.AccessLogValve”
                 directory=”logs”  prefix=”localhost_access_log.” suffix=”.txt”
                 pattern=”common” resolveHosts=”false”/>

className

实现的Java类名。必须被设置成org.apache.catalina.valves.AccessLogValve。

directory

存放日志文件的目录,可以是相对路径或者绝对路径。如果使用相对路径,是指相对于 $CATALINA_HOME的路径。如果不指定directory属性,缺省值是“logs”(相对于 $CATALINA_HOME)

pattern

需要记录的请求/响应不同信息域的格式布局。如果是“common”或者“combine”,说明选择标准格式。下面会有关于配置这个属性的更多信息。

common的值:%h %l %u %t %r %s %b
combined的值:%h %l %u %t %r %s %b %{Referer}i %{User-Agent}i 

prefix

日志文件名的前缀。如果没有指定,缺省值是“access_log.”。如果不想使用前缀,使用长度为0的字符串。

resolveHosts

将远端主机的IP地址通过DNS查询转换成主机名,设为true。如果为false,忽略DNS查询,报告远端的IP地址。

suffix

日志文件名的后缀。如果没有指定,缺省值是“”。如果不想使用后缀,使用长度为0的字符串。

rotatable

缺省值为true,用来决定日志是否翻转的标志。如果为false,日志文件永远不翻转,并且忽略fileDataFormat。要谨慎使用。

condition

打开条件日志。如果设置了这个属性,只有在ServletRequest.getAttribute()是null的时候,才会为请求创建日志。比如,如果condition设为junk,则只有在Servlet.getAttribute(“junk”)==null的时候,才会记录这个请求。使用过滤器,可以很容易设置(或者取消设置)不同请求的属性。

fileDateFormat

允许在日志文件名称中使用定制的日期格式。日志的格式也决定了日志文件翻转的频率。如果想每个小时翻转一次,将这个值设为yyyy-MM-dd.HH


pattern属性值由字符串常量和pattern标识符加上前缀”%”组合而成。pattern标识符加上前缀”%”,用来代替当前请求/响应中的对应的变量值。目前支持如下的pattern:

·        %a – 远端IP地址

·        %A – 本地IP地址

·        %b – 发送的字节数,不包括HTTP头,如果为0,使用”-”

·        %B – 发送的字节数,不包括HTTP头

·        %h – 远端主机名(如果resolveHost=false,远端的IP地址)

·        %H – 请求协议

·        %l – 从identd返回的远端逻辑用户名(总是返回 ‘-‘)

·        %m – 请求的方法(GET,POST,等)

·        %p – 收到请求的本地端口号

·        %q – 查询字符串(如果存在,以 ‘?’开始)

·        %r – 请求的第一行,包含了请求的方法和URI

·        %s – 响应的状态码

·        %S – 用户的session ID

·        %t – 日志和时间,使用通常的Log格式

·        %u – 认证以后的远端用户(如果存在的话,否则为’-‘)

·        %U – 请求的URI路径

·        %v – 本地服务器的名称

·        %D – 处理请求的时间,以毫秒为单位

·        %T – 处理请求的时间,以秒为单位

其它关于各个参数的资料,供参考:
className 官方文档上说了This MUST be set to org.apache.catalina.valves.AccessLogValve to use the default access log valve. 想配置访问日志?这就必须得写成这样。 


directory 这个东西是日志文件放置的目录,在tomcat下面有个logs文件夹,那里面是专门放置日志文件的,当然你也可以修改,我就给改成了D: prefix 这个是日志文件的名称前缀,我的日志名称为localhost_access_log.2007-09-22.txt,前面的前缀就是这个localhost_access_log suffix 这就是后缀名啦,可以改成别的 pattern 这个是最主要的参数了,具体的咱们下面讲,这个参数的内容比较丰富。 


resolveHosts 如果这个值是true的话,tomcat会将这个服务器IP地址通过DNS转换为主机名,如果是false,就直接写服务器IP地址啦 还有一些参数:
rotatable 默认为true,默认的设置使得你的tomcat生成的文件命为prefix(前缀)+.+时间(一般是按天算)+.+suffix(后缀),参照我的日志名就知道了:localhost_access_log.2007-09-22.txt
使用这个需要谨慎,因为你将其设置为false的话,tomcat会忽略时间,不会新生成文件,最后导致你的文件超级大,这样生成的文件名就是:localhost_access_log.txt 

condition 这个参数不太实用,可以设置任何值,比如咱们设置成condition=”tkq”,那么只有当ServletRequest.getAttribute(“tkq”)为空的时候,才会被记录下来 fileDateFormat 最后的一个参数,很明白,这就是时间格式嘛,但是这个时间格式是针对日志文件起作用的,还记得咱们生成的日志文件全名么:localhost_access_log.2007-09-22.txt,这里面的2007-09-22就是这么来的,如果你想让tomcat每小时生成一个日志文件,也很简单,将这个值设置为:fileDateFormat=”yyyy-MM-dd.HH”,当然也可以按分钟生成什么的,自己改改吧 上面是所有的9个参数,刚才咱们说了,


pattern这个参数的值比较多,咱们拿下来单独说:
pattern可以设置成两种方式,第一种是pattern=”common”,第二种是pattern=”combined”
这就可以控制日志里面的格式,各位说了,pattern就这两种?common和combined又是什么意思,具体是什么格式呢?
别着急,咱们一点一点看,其实pattern是可以设置的,common和combined只是集成了一些显示方式,就是将显示方式给组合了,pattern的实际值有如下几种,都是后面一个字母,前面一个%百分号
咱们先贴出来我的日志里面的一条记录,对应着看
127.0.0.1 192.168.254.108 – -1 127.0.0.1 HTTP/1.1 – GET 80&<60; GET /rightmainima/leftbott4.swf HTTP/1.1 304 5563A67708646B6AA299C33D59BE132A [22/Sep/2007:10:08:52 +0800] – /rightmainima/leftbott4.swf localhost 0 0.000

%a     这是记录访问者的IP,在日志里是127.0.0.1 %A 这是记录本地服务器的IP,在日志里是192.168.254.108 %b 这是发送信息的字节数,不涵括http头,如果字节数为0的话,显示为- %B 看tomcat的解释,没看出来与b%的区别,但我这里显示为-1,没想明白,望知道者告知,我把官方解释贴出来吧 Bytes sent, excluding HTTP headers %h 这个就是服务器名称了,如果resolveHosts为false的话,这里就是IP地址了,我的日志里是127.0.0.1 %H 访问者使用的协议,这里是HTTP/1.1 %l 这个也不太清楚,官方也说这个always return ‘-‘ 官方解释:Remote logical username from identd (可能这样翻译:记录浏览者进行身份验证时提供的名字)(always returns ‘-‘) %m 访问的方式,是GET还是POST,我这是GET %p 本地接收访问的端口,呵呵,我这里是80啦 %q 比如你访问的是aaa.jsp?bbb=ccc,那么这里就显示?bbb=ccc,明白了吧,这个q是querystring的意思 %r 官方解释:First line of the request (method and request URI),不是很明白 %s 这个是http的状态,我这里返回的是304,咱们经常看见访问某个网页报错误500什么的,那也会返回500 %S 用户的session ID,这个session ID大家可以另外查一下详细的解释,反正每次都会生成不同的session ID %t 这就是时间啦,好像有一个Common Log Format可以改,不过我没找到 %u 得到了验证的访问者,否则就是”-” %U 访问的URL地址,我这里是/rightmainima/leftbott4.swf %v 服务器名称,可能就是你url里面写的那个吧,我这里是localhost %D 官方解释:Time taken to process the request, in millis,应该是访问发生的时间,以毫秒记 %T 官方解释:Time taken to process the request, in seconds,应该是访问发生的时间,以秒记


common的值:%h %l %u %t %r %s %b
combined的值:%h %l %u %t %r %s %b %{Referer}i %{User-Agent}i 

Tomcat启用80/443端口的时候提示“java.net.BindException: Permission denied:80”,怎么解决?

 tomcat  Tomcat启用80/443端口的时候提示“java.net.BindException: Permission denied:80”,怎么解决?已关闭评论
9月 112013
 

非root权限用户不能使用1024以下的端口,如需使用,可采取下面方法:

 

方法一:先用命令 sudo su,输入密码后获得sudo权限之后再运行tomcat。

方法二:放弃80/443端口,改为8080/8443等1024以上的端口,这个时候可以不用获取sudo权限就能正常运行tocmat了。

方法三:Linux下可以 改为8080/8443等1024以上的端口, 用命令进行端口绑定。

iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-port 8080
iptables -t nat -A PREROUTING -p tcp –dport 443 -j REDIRECT –to-port 8443