当从eclipse运行时,Webapp在出现故障时导致行为失败 [英] Webapp behaves as expected when run from eclipse while when exported as war fails

查看:382
本文介绍了当从eclipse运行时,Webapp在出现故障时导致行为失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这让我很开心。



所以我有一个(非常简单的vanilla servlet 3)网络应用程序。当我在eclipse中运行它一切都很好。其中我可以使用Unicode(希腊语)用户名注册一个帐户,然后以站点管理员身​​份登录,然后访问用户的个人资料。当我出口战争到 $ CATALINA_HOME\webapps 时,启动 $ CATALINA_HOME\bin\startup.bat ,打开浏览器中的站点,以管理员身份登录,并尝试访问用户配置文件,用户名等显示为空白。

... \apache-tomcat-7.0中的文件。 32\conf ... \eclipse_workspaces\javaEE\Servers\Tomcat v7.0中的服务器在localhost-config 不同的行(在 server.xml ):

  < Context docBase =ted2012path =/ ted2012oadable =true
source =org.eclipse.jst.jee.server:ted2012/>

这是一个eclipse的东西。



配置文件servlet中的doGet方法(slimmed):

  protected void doGet(HttpServletRequest request,
HttpServletResponse响应)throws ServletException,IOException {

final String username = Helpers.decodeRequest(request
.getParameter(user));
if(username!= null){
User user = null;
尝试{
System.out
.println(ProfileController.doGet()用户名DECODED:
+ username);
user = userService.getUserWithUsername(username); //这个失败
System.out.println(ProfileController.doGet()user:+ user);
request.setAttribute(userToShow,user);
} catch(ServiceExDBFailure e){
log.debug(ProfileController :: doGet,e);
request.setAttribute(ErrorString,e.getMessage());
}
sc.getRequestDispatcher(OTHERPROFILE_JSP)
.forward(请求,响应);
return;
} else {
//不适用
}
}

解码方法是:

  public static String decodeRequest(String parameter)
抛出UnsupportedEncodingException {
if(parameter == null)
return null;
System.out.println(decode - request.getBytes(\iso-8859-1\):
+ new String(parameter.getBytes(iso-8859-1 )));
System.out.println(decode - request.getBytes(\iso-8859-1\)BYTES:
+ parameter.getBytes(iso-8859-1)) ;
for(byte iterable_element:parameter.getBytes(iso-8859-1)){
System.out.println(iterable_element);
}
System.out.println(decode - request.getBytes(\UTF-8\):
+ new String(parameter.getBytes(CHARSET_FOR_URL_ENCODING))) ; // UTF-8
return URLDecoder.decode(new String(parameter.getBytes(iso-8859-1)),
CHARSET_FOR_URL_ENCODING);
}

数据库调用是:

  statement = conn.prepareStatement(query); 
statement.setString(1,username);
System.out.println(ελληναρα);
System.out.println(statement);
set = statement.executeQuery();
if(set.next()){
User user = new User();
// user.setId(set.getInt(ID));
user.setUsername(set.getString(username));
user.setName(set.getString(name));
user.setSurname(set.getString(surname));
user.setPassword(set.getString(password));
user.setEmail(set.getString(email));
user.setRole(RolesENUM.values()[set.getInt(role)]);
返回用户; //如果集合为空,则返回null
}

Tomcat打印:

  decode  -  request.getBytes(iso-8859-1):╧à╧â╧ä╬╡╧?╬╣╬▒ 
decode - request.getBytes(iso-8859-1)BYTES:[B @ 529b9ed
-49
-123
-49
-125
-49
-124
-50
-75
-49
-127
-50
-71
-50
-79
decode - request.getBytes(UTF-8):├?┬à├?┬├┬┬├┬╡┬╡┬├├┬╣┬╣┬╣ Ä┬▒
ProfileController.doGet()用户名DECODED:╧à╧â╧ä╬╡╧?╬╣╬▒
com.mysql.jdbc.JDBC4PreparedStatement@766d7940:SELECT * FROM users WHERE username ='╧à╧â╧ä╬╡╧?╬╣╬▒'
???
ProfileController.doGet()用户:null

而Eclipse打印:

  decode  -  request.getBytes(iso-8859-1):υστερια
decode - request.getBytes(iso-8859- 1)字节:[B @ 4b6a6bdf
-49
-123
-49
-125
-49
-124
- 50
-75
-49
-127
-50
-71
-50
-79
解码 - 请求.getBytes(UTF-8):ÏÏÏÎμÏια
ProfileController.doGet()用户名DECODED:υστερια
com.mysql.jdbc.JDBC4PreparedStatement@37d02427:SELECT * FROM users WHERE username ='υστερια'
ελληναρα
ProfileController.doGet()user:com.ted.domain.User@63144ceb


$ b $我相信由于某种原因,获取到db的查询是一件疯狂的事情 - 请注意,在eclipse中,在tomcat中打印ελληναρα?而unicode用户名(υστερια)打印为╧à╧╬╡╧╬╣╬╬╣╬╬╣╬╬╣╬╬╣╬╬╣╬╬╣╬。。。。。>>>>>>>>>> So>>>>>>问题是 - Eclipse部署和tomcat部署之间有什么变化?为什么数据库返回null?我真的真的试图调试这个无效的



帮助



编辑:替换行 statement.setString(1,username); with statement.setString(1,υστερια); 没有失败。所以在这行运行的时候,这些字节被破坏了 - 注意到字节是一个一个的。



EDIT2: Tomcat v7.0在本地主机上的服务器Eclipse启动VM参数(为了可读性而拆分):

  -Dcatalina.base =C:\ Dropbox\eclipse_workspaces\javaEE\.metadata\.plugins 
\org.eclipse.wst.server.core\tmp1
-Dcatalina.home =C:\_\\ \\apache-tomcat-7.0.32
-Dwtp.deploy =C:\Dropbox\eclipse_workspaces\javaEE\.metadata\.plugins\org.eclipse.wst.server.core\\ \\ tmp1\wtpwebapps
-Djava.endorsed.dirs =C:\_\apache-tomcat-7.0.32\endorsed

NB 动态创建该应用程序的启动



编辑2013.03.30 :现在是在 github - 并且看到我更一般的问题 here

解决方案

最终在此处回复。



答案的要点是,我eclipse具有默认编码UTF-8和Tomcat windows-1252 当我调用新的String()而不指定用于将字节[]转换为chars 的编码。

  new String(parameter.getBytes(iso-8859-1),UTF-8); 

解决问题 - 它不会,但如果tomcat在

  request.getParameter(user)// url解码由tomcat执行 - 使用
// URIEncoding从服务器。 xml或默认ISO-8859

默认情况下不会使用ISO-8859作为另一种编码)将可能(行为未定义,在Java 7 nio之前不可控制)用替换不可解码的字符,因此参数字符串将被破坏(请参阅 ISO-8859-1编码和二进制数据保存)。



所以bravo到tomcat默认使用ISO-8859在其 request.getParameter中进行转换()和boo到Java ee spec家伙甚至没有在文档中提到getParameter将执行URL解码,更不用说让我们指定编码,覆盖server.xml。


This has been driving me nuts.

So I have a (very simple vanilla servlet 3) web app. When I run it in eclipse all is fine. Among others I am able to register an account with Unicode (greek) username and then log in as site admin and visit the user's profile alright. When I export war to $CATALINA_HOME\webapps, launch $CATALINA_HOME\bin\startup.bat, open the site in the browser, login as admin and try to visit the user profile the username etc display as blank.
The files in ...\apache-tomcat-7.0.32\conf and the ones in ...\eclipse_workspaces\javaEE\Servers\Tomcat v7.0 Server at localhost-config differ only in the line (in server.xml) :

<Context docBase="ted2012" path="/ted2012" reloadable="true" 
source="org.eclipse.jst.jee.server:ted2012"/>

which is an eclipse thing.

The doGet method (slimmed) in the profile servlet :

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {

    final String username = Helpers.decodeRequest(request
            .getParameter("user"));
    if (username != null) {
        User user = null;
        try {
            System.out
                    .println("ProfileController.doGet() user name DECODED : "
                            + username);
            user = userService.getUserWithUsername(username); // THIS FAILS
            System.out.println("ProfileController.doGet() user : " + user);
            request.setAttribute("userToShow", user);
        } catch (ServiceExDBFailure e) {
            log.debug("ProfileController::doGet", e);
            request.setAttribute("ErrorString", e.getMessage());
        }
        sc.getRequestDispatcher(OTHERPROFILE_JSP)
                .forward(request, response);
        return;
    } else {
        //does not apply
    }
}

The decode method is :

public static String decodeRequest(String parameter)
        throws UnsupportedEncodingException {
    if (parameter == null)
        return null;
    System.out.println("decode - request.getBytes(\"iso-8859-1\"):"
            + new String(parameter.getBytes("iso-8859-1")));
    System.out.println("decode - request.getBytes(\"iso-8859-1\") BYTES:"
            + parameter.getBytes("iso-8859-1"));
    for (byte iterable_element : parameter.getBytes("iso-8859-1")) {
        System.out.println(iterable_element);
    }
    System.out.println("decode - request.getBytes(\"UTF-8\"):"
            + new String(parameter.getBytes(CHARSET_FOR_URL_ENCODING))); // UTF-8
    return URLDecoder.decode(new String(parameter.getBytes("iso-8859-1")),
            CHARSET_FOR_URL_ENCODING);
}

While the db call is :

            statement = conn.prepareStatement(query);
            statement.setString(1, username);
            System.out.println("ελληναρα");
            System.out.println(statement);
            set = statement.executeQuery();
            if (set.next()) {
                User user = new User();
                // user.setId(set.getInt("ID"));
                user.setUsername(set.getString("username"));
                user.setName(set.getString("name"));
                user.setSurname(set.getString("surname"));
                user.setPassword(set.getString("password"));
                user.setEmail(set.getString("email"));
                user.setRole(RolesENUM.values()[set.getInt("role")]);
                return user; // if the set is empty null is returned
            }

Tomcat prints :

decode - request.getBytes("iso-8859-1"):╧à╧â╧ä╬╡╧?╬╣╬▒
decode - request.getBytes("iso-8859-1") BYTES:[B@529b9ed
-49
-123
-49
-125
-49
-124
-50
-75
-49
-127
-50
-71
-50
-79
decode - request.getBytes("UTF-8"):├?┬à├?┬â├?┬ä├Ä┬╡├?┬?├Ä┬╣├Ä┬▒
ProfileController.doGet() user name DECODED : ╧à╧â╧ä╬╡╧?╬╣╬▒
com.mysql.jdbc.JDBC4PreparedStatement@766d7940: SELECT * FROM users WHERE username='╧à╧â╧ä╬╡╧?╬╣╬▒'
????????
ProfileController.doGet() user : null

while Eclipse prints :

decode - request.getBytes("iso-8859-1"):υστερια
decode - request.getBytes("iso-8859-1") BYTES:[B@4b6a6bdf
-49
-123
-49
-125
-49
-124
-50
-75
-49
-127
-50
-71
-50
-79
decode - request.getBytes("UTF-8"):ÏÏÏεÏια
ProfileController.doGet() user name DECODED : υστερια
com.mysql.jdbc.JDBC4PreparedStatement@37d02427: SELECT * FROM users WHERE username='υστερια'
ελληναρα
ProfileController.doGet() user : com.ted.domain.User@63144ceb

I believe for some reason the query that gets to the db is something crazy - notice that where in eclipse prints ελληναρα in tomcat prints ???????? while the unicode username (υστερια) prints as ╧à╧â╧ä╬╡╧?╬╣╬▒ and not as ???????.

So the question is - what changes between the Eclipse deployment and the tomcat deployment ? Why the hell the DB returns null ? I have really really tried to debug this in vain

Help

EDIT : replacing the line statement.setString(1, username); with statement.setString(1, "υστερια"); there is NO failure. So by the time this line is run the bytes are mangled up - notice though that the bytes are the same one by one

EDIT2 : Tomcat v7.0 Server at localhost Eclipse launch VM args (split for readability) :

-Dcatalina.base="C:\Dropbox\eclipse_workspaces\javaEE\.metadata\.plugins
\org.eclipse.wst.server.core\tmp1" 
-Dcatalina.home="C:\_\apache-tomcat-7.0.32" 
-Dwtp.deploy="C:\Dropbox\eclipse_workspaces\javaEE\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps" 
-Djava.endorsed.dirs="C:\_\apache-tomcat-7.0.32\endorsed"

NB : the launch for the app is created dynamically

EDIT 2013.03.30 : this is now on github - and see my more general question here

解决方案

This was finally answered here.

The gist of the answer is that I eclipse had as default encoding UTF-8 and Tomcat windows-1252 so when I call new String() without specifying the encoding those are used to tranlate the byte[] to chars. Doing

new String(parameter.getBytes("iso-8859-1"), "UTF-8");

solves the problem - it would not though if tomcat in

request.getParameter("user") // url decoding is performed by tomcat - using the
// URIEncoding from server.xml or by default ISO-8859

would not use by default ISO-8859 as another encoding (say ASCII) would probably (behavior undefined and not controllable before Java 7 nio) replace undecodable characters with ? so parameter String would be corrupted (see ISO-8859-1 encoding and binary data preservation).

So bravo to tomcat for performing the conversion by default with ISO-8859 in its request.getParameter() and boo to Java ee spec guys who do not even mention in the docs that getParameter will perform URL decoding, let alone letting us specify the encoding, overriding server.xml.

这篇关于当从eclipse运行时,Webapp在出现故障时导致行为失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆