iframe无缝集成web应用程序
本文假定访问iframe所嵌的web app的 SSO 方式是使用 url 附加认证信息(如用户名和密码)。让内嵌 web app 记住自己的最后一次被访问的 url 是最好的也是最简单的方式,因为如果由主程序记录,牵扯到2个 web app 间的通信,简单点的,如使用 javascript 获取内嵌 web app 的地址,跨域会是个问题。
我们为内嵌 web app 增加一个身份验证的 servlet, 目的是为了恢复上次访问的 url。在每次访问内嵌 web app 时,这个 servlet 首先检查当前请求用户是否是有效用户(即 session 是否存在),如果是,则从这个用户的 session 中取出上次访问的 url,并 dispatcher 到这个页面;否则,验证并登录这个用户,从数据库中取出上次访问的 url,并放到 session 中,dispatcher 到这个 url 页面。
在 session 过期时,使用 session listener,将当前用户最后一次访问的 url (应为存于 session 中)放入数据库中。
但是有一个问题,就是在登陆外围系统的时候,用户希望看到内嵌系统的页面是默认的页面,而不是上次访问的 url。如何解决这个问题呢?因为对于内嵌程序来说,用户是不是首次登录,它自然是无从知晓了,这一点只有外围系统才能获知,所以,解决方法就是动态改变 iframe 的 src url的参数,仅在刚登录时告诉内嵌的 web app,“用户刚登录,这是第一次访问你”。
Categorized in: Java · Tagged with: Java
运用Filter,ThreadLocal和Reflection,实现form到bean的填充
© 2006 版权声明
1. 本文作者为 javafuns
2. 本文可经/不经作者许可,任意转载
3. 转载时请表明原作者及修改者,并附带本版权声明
4. 本文未经实践检验,故对由采用本文所述操作而引起的任何后果,本文作者均不作任何担保,亦不承担任何责任
做过web开发的人可能都有这种感觉,不时的需要从request中提取参数及数据,如果有一种方式可以省却这一步骤,是否会令你的开发工作更愉悦呢?本文在此做了如下的探讨。
很显然,从request中提取参数需要一个尽职尽责的,但是又很优雅的让我们感觉不到它的辛苦工作的模块来实现,它的任务就是,1)截取所有的request,2)从request取出数据并填充到bean留给其他人使用。大概你也会想到Filter,它的特性符合要求。
Filter截取了请求如何处理呢? 我想到了2种方式(当然,还有其它的),
1)request参数需要指明本次提交的数据要填充至哪个bean,且参数与bean的field严格匹配,这样利用 Reflection ,取出bean的field,然后从request.getParameter(field)取得数据进行填充。
2)采取配置文件进行request 的form数据到bean的映射,方式也是采用Reflection来完成填充工作。
2种方式各有优缺点,方式1不够灵活,方式2则对于某些人看来则是烦琐,毕竟还需要配置,也失去了本文简化request form处理的目的。因此本人推荐第一种方式,即使存在某些情况,也可以在bean中增加新方法来处理。
数据的有效性检查也放在bean里做,将数据无效的信息放在bean的error hashmap里,在filter填充完bean后,检查bean是否有效,有无效的数据,则直接返回客户端;否则,调用chain.doFilter(request, response)继续处理,并将这个bean放入ThreadLocal中,留待后续class访问,当这个线程结束后,bean会被垃圾收集器清除。
Filter样例:
/*
* SimpleFilter.java
*
* Created on 2006年9月20日, 下午2:54
*/
package org.openthoughts.testings;
import Java.io.*;
import Java.lang.reflect.Field;
import Java.lang.reflect.InvocationTargetException;
import Java.lang.reflect.Method;
import Java.util.HashMap;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.openthoughts.util.Form2BeanUtil;
/**
* Stuff a bean specified by request with form data.
*
* @author <a href="guangquanzhang@gmail.com" mce_href="guangquanzhang@gmail.com">javafuns</a>
* @version
*/
public class SimpleFilter implements Filter {
// The filter configuration object we are associated with. If
// this value is null, this filter instance is not currently
// configured.
private FilterConfig filterConfig = null;
public SimpleFilter() {
}
/**
* Init method for this filter
*
*/
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
/**
* Do actual work for filling.
*
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String beanName = ((HttpServletRequest)request).getParameter("formbean");
System.err.println(" form bean is " + beanName);
Class beanClazz = null;
Object beanObject = null;
boolean isValid = false;
if(beanName != null) {
try {
beanClazz = Class.forName(beanName);
if(beanClazz != null) {
beanObject = beanClazz.newInstance();
}
} catch (ClassNotFoundException ex) {
request.setAttribute("MainErrMsg", beanName + " not found");
this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
return;
} catch (InstantiationException ex) {
request.setAttribute("MainErrMsg", beanName + " can not be instantiated");
this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
return;
} catch (IllegalAccessException ex) {
request.setAttribute("MainErrMsg", beanName + " not access");
this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
return;
}
}
if(beanObject != null) {
Field[] fields = beanClazz.getDeclaredFields();
for(Field field : fields) {
Method beanMethod = null;
String fieldName = field.getName();
String fieldValue = ((HttpServletRequest)request).getParameter(fieldName);
StringBuilder sb = new StringBuilder();
sb.append("set");
sb.append(fieldName.substring(0, 1).toUpperCase());
sb.append(fieldName.substring(1));
try {
beanMethod = beanClazz.getDeclaredMethod(sb.toString(), String.class);
} catch (SecurityException ex) {
request.setAttribute("MainErrMsg", " Security reason ");
this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
return;
} catch (NoSuchMethodException ex) {
request.setAttribute("MainErrMsg", beanName + " does not have method named " + sb.toString());
this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
return;
}
if(beanMethod != null) {
try {
beanMethod.invoke(beanObject, fieldValue);
} catch (IllegalArgumentException ex) {
request.setAttribute("MainErrMsg", "illegal argument for the method " + sb.toString() + " of " + beanName);
this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
return;
} catch (InvocationTargetException ex) {
request.setAttribute("MainErrMsg", beanName + " invoke target exception ");
this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
return;
} catch (IllegalAccessException ex) {
request.setAttribute("MainErrMsg", beanName + " illegal access to " + sb.toString());
this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
return;
}
}
}
Form2BeanUtil.put(beanObject);
Method getAllErrors = null;
try {
getAllErrors = beanClazz.getDeclaredMethod("getAllErrors");
} catch (SecurityException ex) {
System.err.println("Security exception when call getAllErrors()");
} catch (NoSuchMethodException ex) {
System.err.println("No such method named getAllErrors()");
}
if(getAllErrors != null) {
try {
isValid = ((HashMap)getAllErrors.invoke(beanObject)).isEmpty();
} catch (IllegalArgumentException ex) {
System.err.println("Illegal argument for getAllErrors()");
} catch (IllegalAccessException ex) {
System.err.println("Illegal Access to getAllErrors()");
} catch (InvocationTargetException ex) {
System.err.println("Invocation target exception");
}
}
}
if(beanName == null || isValid) {
chain.doFilter(request, response);
} else {
if(beanObject != null) {
request.setAttribute("formbean", beanObject);
}
this.filterConfig.getServletContext().getRequestDispatcher(getRequestURI(request)).forward(request, response);
}
}
/**
* Destroy method for this filter
*
*/
public void destroy() {
}
public String getRequestURI(ServletRequest request) {
String requestURI = ((HttpServletRequest)request).getRequestURI();
String queryString = ((HttpServletRequest)request).getQueryString();
return requestURI + queryString;
}
/**
* Return a String representation of this object.
*/
public String toString() {
if (filterConfig == null) return ("SimpleFilter()");
StringBuffer sb = new StringBuffer("SimpleFilter(");
sb.append(filterConfig);
sb.append(")");
return (sb.toString());
}
}
Bean样例:
/*
* SimpleBean.java
*
* Created on 2006年9月20日, 下午5:51
*/
package org.openthoughts.beans;
import Java.io.Serializable;
import Java.util.HashMap;
/**
* @author Administrator
*/
public class SimpleBean implements Serializable {
private String userName;
private String password;
public SimpleBean() {
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
//错误信息
public HashMap getAllErrors() {
return new HashMap();
}
}
ThreadLocal实现:
/*
* Form2BeanUtil.java
*
* Created on 2006年9月20日, 下午4:51
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.openthoughts.util;
/**
* Hold formbean for appropriate thread via ThreadLocal.
*
* @author <a href="guangquanzhang@gmail.com" mce_href="guangquanzhang@gmail.com">javafuns</a>
*/
public class Form2BeanUtil {
private static final ThreadLocal container = new ThreadLocal();
/**
* Put the form bean to ThreadLocal.
*/
public static void put(Object object) {
container.set(object);
}
/**
* Get the current thread's form bean.
*/
public static Object get() {
return container.get();
}
}
后续使用:
/*
* SimpleServlet.java
*
* Created on 2006年9月20日, 下午5:48
*/
package org.openthoughts.testings;
import Java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.openthoughts.beans.SimpleBean;
import org.openthoughts.util.Form2BeanUtil;
/**
*
* @author Administrator
* @version
*/
public class SimpleServlet extends HttpServlet {
/** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
* @param request servlet request
* @param response servlet response
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
SimpleBean sb = (SimpleBean)Form2BeanUtil.get();
if(sb != null) {
request.setAttribute("formbean", sb);
}
this.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/** Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/** Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/** Returns a short description of the servlet.
*/
public String getServletInfo() {
return "Short description";
}
// </editor-fold>
}
PS: 类似的方式在很多框架都有实现,比如struts的formbean
Categorized in: Java · Tagged with: Java
(转载)UTF-8 字符处理在 Web 开发中的应用
殷健软件工程师,IBM CSDL,
2006 年 7 月 27 日
Web 应用要适应多语言的需求。不同国家的用户应该可以输入本国语言的字符, 同时 Web 应用又应该可以根据不同的区域设置来用多国语言显示页面。当前,不同的语言有不同的编码方式来显示对应的语言信息,例如中文可以用 GB2312 编码来显示,日文可以用 Shift-JIS 编码来显示。但 UTF-8 编码方式几乎可以包括了所有的语言字符。用 UTF-8 编码来处理 Web 应用信息的输入和显示可以使不同 Web 应用之间的信息交互标准化,并且可以简化应用的开发过程。
UTF-8 编码介绍
UTF-8 编码是一种被广泛应用的编码,这种编码致力于把全球的语言纳入一个统一的编码,目前已经将几种亚洲语言纳入。UTF 代表 UCS Transformation Format.
UTF-8 采用变长度字节来表示字符,理论上最多可以到 6 个字节长度。UTF-8 编码兼容了 ASC II(0-127), 也就是说 UTF-8 对于 ASC II 字符的编码是和 ASC II 一样的。对于超过一个字节长度的字符,才用以下编码规范:
左边第一个字节1的个数表示这个字符编码字节的位数,例如两位字节字符编码样式为为:110xxxxx 10xxxxxx; 三位字节字符的编码样式为:1110xxxx 10xxxxxx 10xxxxxx.;以此类推,六位字节字符的编码样式为:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx。 xxx 的值由字符编码的二进制表示的位填入。只用最短的那个足够表达一个字符编码的多字节串。例如:
Unicode 字符: 00 A9(版权符号) = 1010 1001, UTF-8 编码为:11000010 10101001 = 0x C2 0xA9; 字符 22 60 (不等于符号) = 0010 0010 0110 0000, UTF-8 编码为:11100010 10001001 10100000 = 0xE2 0×89 0xA0
HTTP 通讯协议
HTTP 请求
在 HTTP 通讯中,在客户端发出的请求报文中,首先设置的是方法。方法是用来告诉服务器客户端发起的动作请求。在请求的报文头部,客户端还可以同时发送附加的信息,比如客户端使用的浏览器和客户端可以解释的内容类型等。这些信息可以被服务器端应用程序使用以生成响应。下面是一个 HTTP 请求消息的示例:
图1. HTTP 请求消息头GET /intro.html HTTP/1.0
User-Agent: Mozilla/4.0 (compatible; MSIE 4.0; Windows 95)
Accept: image/gif, image/jpeg, text/*, */*
Accept-language : zh
Accept-Charset: iso-8859-1
这个请求通过 GET 方法来获取资源 /intro.htm。User-Agent 提供了客户端浏览器的信息,同时 Accept 提供了客户端可以接受的媒体类型。Accep-language 指出了客户端浏览器的首选语言, Accept-Charset 提供了浏览器的首选字符集,服务器端程序能够根据客户端的要求来生成需要的响应。 用户可以通过配置浏览器来设置首选语言。以 IE 为示例如下:
图2. 浏览器首选语言设置

当浏览器发出请求后,可以通过以下代码来读取客户端浏览器的首选语言和国家代码。
图3. 服务器端 Servlet 读取浏览器首选国家和语言protected void insertproc(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
Locale reqLocal = req.getLocale();
System.out.println(“The country is :” + reqLocal.getCountry());
System.out.println(“The language is :” + reqLocal.getLanguage());
服务器端的输出结果为:
图4. 服务器端 Servlet 读取浏览器首选国家和语言结果[06-3-10 14:56:32:516 CST] 6ce078f9 SystemOut O The country is :CN
[06-3-10 14:56:32:516 CST] 6ce078f9 SystemOut O The language is :zh
HTTP 响应
当服务器端收到请求后,会处理请求并发回应答。服务器通过应答消息的头部来指明诸如服务器软件和相应的内容类型等信息。以下是一个应答消息头的示例:
图5.HTTP 应答消息头Date: Saturday, 23-May-98 03:25:12 GMT
Server: JavaWebServer/1.1.1
MIME-version: 1.0
Content-type: text/html; charset=UTF-8
Content-length: 1029
Last-modified: Thursday, 7-May-98 12:15:35 GMT
Content-type 表明了应答消息的 MIME 类型和应答消息体的字符集,浏览器会用相应的字符集来显示消息内容。例如,在以上示例中字符集是 UTF-8,浏览器会用 UTF-8 编码来解析和现实返回的消息体。同时页面输入也会被用 UTF-8 编码。
Web 页面显示编码
可以通过以下几种方式来设置内容类型。
在 HTML 中设置页面的编码方式
如果被访问的是一个静态的 HTML 页面。可以通过以下方式来设置页面的编码方式。
图6. 设置页面编码的静态 HTML 文件<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<HTML>
<HEAD>
<META http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<TITLE>example.html</TITLE>
</HEAD>
<BODY>
</BODY>
</HTML>
标记”<META http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>” 将应答消息头中 Content_type 设置为”text/html; charset=UTF-8″.
在 Servlet 中设置页面显示编码方式
在 Servlet 中,我们可以通过以下方式来设置应答消息的内容类型。
图7.设置页面编码的 Servlet 片断protected void insertproc(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
resp.setContentType(“text/html;charset=UTF-8″);
代码行”resp.setContentType(“text/html;charset=UTF-8″);”将应答消息头中 Content_type 设置为”text/html; charset=UTF-8″。
在 JSP 中设置页面显示编码方式
我们通过以下示例说明如何在 JSP 中设置页面的编码格式。
图8. 设置业面编码的 JSP 页面指令<%@ page language=”java” contentType=”text/html; charset=UTF-8″ pageEncoding=”UTF-8″%>
在这行的页面指令中的”text/html; charset=UTF-8″将应答消息中的”Content-type” 设置为”text/html; charset=UTF-8″。
“pageEncoding”只是指明了 JSP 页面本身的编码格式,指明了 JSP 是以什么编码方式保存。容器在读取文件时将起转化为内部使用的 Unicode. 当应答发送回至浏览器时,容器会将内部使用的 Unicode 转化为在 Content-type 中指定的字符集。
如果没有指定 PageEncoding,可以通过使用 Content-type 指定的字符集来解释 JSP 页面字节。
为了能正常显示 UTF-8 编码的字符,要满足以下两个条件:
1. 通知浏览器应答消息使用的字符集。
2. 配置浏览器使其能有正常显示 UTF-8 编码的字体。
Web 页面输入编码
HTML 的表单可以接受非西欧语言字符的输入。当需要创建一个需要接受非西欧语言字符输入的表单时,必须通知浏览器应该为用户输入使用哪个字符集,我们可以通过设置 page 指令的 contentType 属性来设置。
我们需要注意的是,当表单被提交后,浏览器会将表单字段值转换为指定字符集对应的字节值,然后根据 HTTP 标准 URL 编码方案对结果字节进行编码。当使用 ISO-8859-1 编码时,任何 a 到 z, A 到 Z 和 0 到 9 之外的字符都会被转化为十六进制格式的字节值,并在前面加上一个百分号(%).例如,如果表单的字符集被设为 UTF-8, 字符”中文”被传递的编码格式为:”%E4%B8%AD%E6%96%87″。为了对输入的信息进行处理,容器必须知道浏览器是使用什么字符集对输入进行编码的。问题是当今多数的浏览器并不提供这种信息,因此你必须自己提供这种信息,并告诉容器用哪个字符集对输入进行解码。
页面输入编码设定
在本文第3部分中说明了如何设置页面的显示编码,在设置页面编码的同时,也就指定了页面的输入方式。如果页面的显示被设置为UTF-8,那么用户所有的页面输入都会按照 UTF-8 编码。
页面输入输出过程编码设置
服务器端程序在读取表单输入之前要设定输入编码。我们可以看一下示例。
以下是一个用来提示用户输入的 JSP 页面:
图9. 用以界面输入的 JSP 页面<%@ page contentType=”text/html; charset=UTF-8″ pageEncoding=”UTF-8″%>
<HTML>
<HEAD>
<TITLE>insertdb.jsp</TITLE>
</HEAD>
<BODY>
<P>
<FORM METHOD=POST ACTION=”./InsertDbProcDs”>
<TABLE>
<TR>
<TD>Name:</TD>
<TD><input type=”text” name=”col2″ value=”"></TD>
<TR>
<TD><INPUT type=”submit” value=”submit”></TD>
</TR>
</TR>
</TABLE>
</RORM>
</P>
</BODY>
</HTML>
页面指令元素的属性 Content-type 值为”text/html; charset=UTF-8″,这会向浏览器指明页面是按照 UTF-8 编码的,并且所有用户通过页面的输入也会按照 UTF-8 编码。被 Action 所触发的 Servlet 如下例所示。
图10. 用以按 UTF-8 读取输入并输出的 Servlet protected void insertproc(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
String test1 = req.getParameter(“col2″);
PrintWriter out = resp.getWriter();
resp.setContentType(“text/html;charset=UTF-8″);
out.println(“<HTML>”);
out.println(“The input is ” + test1);
out.println(“</HTML>”);
通过表单页面输入”中文”并提交表单,得到的结果为:
图11.正确显示结果的页面

如果我们注释掉语句:resp.setContentType(“text/html;charset=UTF-8″),如下例:
图12. 用以按非 UTF-8 读取输入并输出的 Servletprotected void insertproc(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
String test1 = req.getParameter(“col2″);
PrintWriter out = resp.getWriter();
//resp.setContentType(“text/html;charset=UTF-8″)
out.println(“<HTML>”);
out.println(“The input is ” + test1);
out.println(“</HTML>”);
输入”中文”并提交表单,得到的结果为:
图13. 错误显示输入结果的页面

页面不能正确显示 UTF-8 编码的字符。
在被触发的 Servlet 中通过设置 resp.setContentType(“text/html;charset=UTF-8″) 来向浏览器指明输出的编码字符集为 UTF-8,浏览器会用正确的字符集来显示输出。如果 Servlet 中没有显示的调用 resp.setContentType(“text/html;charset=UTF-8″) 来设定输出字符集,浏览器将不能正确的解码和显示输出。
结论
本文给出了一些在 Web 应用开发中如何显示和输入 UTF-8 编码字符的方法。便于读者在开发实践中参考。
参考资料
参考资源:
Java Servlet Programming(O’Reilly Media. Inc)
Java server Pages(O’Reilly Media. Inc)
相关资源:
在developerworks 关于字符编码的文章:
JAVA 编程/WAS 对多语言(双字节)的支持
Java 编程技术中汉字问题的分析及解决
JSP/Servlet 中的汉字编码问题
关于作者
殷健是一位 IBM CSDL 的软件工程师,目前从事企业电子商务应用的开发。
Categorized in: Java · Tagged with: Java
如何让你的iframe高度和宽度随内嵌网页高度和宽度的变化而变化
from http://www.webjx.com
将如下代码置于你的父页面中,而后在父页面的iframe中通过onload事件调用这个方法:
适用性:IE5.5+,mozilla,firefox,opera(后退时有问题)
Categorized in: Java · Tagged with: Javascript
使用axis2访问web service时抛read timed out的解决方法
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.SO_TIMEOUT,new Integer(480000));
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CONNECTION_TIMEOUT, new Integer(480000));
Categorized in: Java · Tagged with: Java
巧妙装载你的properties
详细的,请访问 这里
好几种方式装载 resource 文件:
1. File 类via FileInputStream, FileReader, and RandomAccessFile)
你需要计算文件路径,是否是绝对的或相对的。所以这样做将使你的程序不易移植.
2. ClassLoader.getResourceAsStream (”some/pkg/resource.properties”);
以斜线分割包,路径是绝对的。
3. Class.getResourceAsStream (”/some/pkg/resource.properties”);
以斜线分割包,路径可以是绝对的或相对的.
4. ResourceBundle.getBundle (”some.pkg.resource”);
以点分割包,.properties 是隐含的,因为bundle可以是一个类。
Categorized in: Java · Tagged with: Java

(
(4.00 out of 5)