athrunwang

纪元
数据加载中……

使用Struts 2防止表单重复提交

  用户重复提交表单在某些场合将会造成非常严重的后果。例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次。因此,重复提交表单会对你的系统带来逻辑影响,必须采取一些措施防止这类情况的发生。

  用户重复提交同一个HTML表单的原因有: 一、快速多次点击了提交按钮;二、提交表单后按下浏览器的刷新按钮。


设置Struts 2的预防表单重复提交的功能 

      Struts 2已经内置了能够防止用户重复提交同一个HTML表单的功能。它的工作原理:让服务器生成一个唯一标记,并在服务器和表单里各保存一份这个标记的副本。此后,在用户提交表单的时候,表单里的标记将随着其他请求参数一起发送到服务器,服务器将对他收到的标记和它留存的标记进行比较。如果两者匹配,这次提交的表单被认为是有效的,服务器将对之做出必要的处理并重新设置一个新标记。随后,提交相同的表单就会失败,因为服务器上的标记已经重置。 

  Struts 2标签中的token标签,可以用来生成一个独一无二的标记。这个标记必须嵌套在form标签中使用,它会在表单里插入一个隐藏字段并把标记保存到HttpSession对象里。toke标签必须与Token或Token Session拦截器配合使用,两个拦截器都能对token标签进行处理。Token拦截器遇到重复提交表单的情况,会返回一个"invalid.token"结果并加上一个动作级别的错误。Token Session拦截器扩展了Token拦截器并提供了一种更复杂的服务,它采取的做法与Token拦截器不同,它只是阻断了后续的提交,这样用户不提交多少次,就好像只是提交了一次。 


示例:使用Token拦截器预防表单重复提交

1.  配置struts.xml文件,声明动作

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
<struts>
<package name="avoidPackage" extends="struts-default">
<action name="avoid" class="struts2.action.AvoidAction">
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>

<result name="invalid.token">/error.jsp</result>
<result name="input">/input.jsp</result>
<result name="success">/output.jsp</result>
</action>
</package>
</struts>

此时,需要在动作的声明中,为动作添加token拦截器,因为token拦截器不在defaultStack拦截器栈中,注意,需要将拦截器放在拦截器栈的第一位,这是因为判断表单是否被重复提交的逻辑应该在表单处理前。

2. 创建动作类

public class AvoidAction extends ActionSupport {
private static final long serialVersionUID = 2676453800249807631L;

private String username;
private Date birthday;

public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}

@Override
public String execute()
{
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}

return SUCCESS;
}

}

这个动作逻辑处理为挂起4秒钟,让我们有机会多次点击提交按钮,测试效果。

3. 创建页面:

input.jsp

<s:form action="avoid">
<s:token></s:token>
<s:textfield name="username" label="Enter your name"></s:textfield>
<s:textfield name="birthday" label="Enter your birthday"></s:textfield>
<s:submit value="submit"></s:submit>
</s:form>

要使用Struts 2的防止表单重复提交功能,需要在form标签中使用token标签,他会产生一个唯一的标识符,与其他参数一起提交到服务器,服务器会根据token标签所产生的标识符判断表单是否为重复提交的表单,这个功能是由Token拦截器完成的。

error.jsp

<body>
do not duplicate submissions form!
</body>

当表单重复提交,Token拦截器会返回一个"invalid.token"结果,结果将页面转到这个页面,提示用户错误信息。

output.jsp

<body>
Your Name : <s:property value="username"/>
<br />
Your Birthday : <s:property value="birthday"/>
</body>

若没有重复提交表单,那么就显示正确的页面。

4. 测试

在浏览器中输入:http://localhost:8081/AvoidDuplicateSubmissions/input.jsp,得到如下界面

连续多次点击"submit"按钮,查看效果

可以看到,token拦截器的设置生效了,他阻止了表单的重复提交,并给出了错误提示

这次我们只点击一次提交(请重新输入URL,或后退到输入页面后刷新一下,这是因为token的标示在提交一次后已被修改,不刷新标示符是不可能与服务器存留的标示符一致的)

可以看到,表单被正确的处理了。

处理表单重复提交的另一个拦截器是 tokenSession,使用该拦截器与使用token拦截器并没有什么差异只需要,引用该拦截器,其他与token拦截器完全一致

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
<struts>
<package name="avoidPackage" extends="struts-default">
<action name="avoid" class="struts2.action.AvoidAction">
<interceptor-ref name="tokenSession"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>

<result name="invalid.token">/error.jsp</result>
<result name="input">/input.jsp</result>
<result name="success">/output.jsp</result>
</action>
</package>
</struts>

posted @ 2011-11-18 10:43 AthrunWang 阅读(151) | 评论 (0)编辑 收藏
Struts 2的调试与性能分析功能

Struts 2标签库里的debug标签以及Struts 2提供的Debugging拦截器大大简化了Web应用程序的调试工作,Profiling拦截器可以分析应用程序中的性能瓶颈。

使用debug标签获取调试信息

debug标签的用途是显示ValueStack栈和其他对象的内容,它非常易用,只需要在需要调试的页面插入如下语句:

<s:debug></s:debug>

示例:

index.jsp

<body>
<s:debug></s:debug>
</body>

在浏览器中输入:http://localhost:8081/DebugAndProfiling/index.jsp,获得如下页面:

点击"[Debug]",会获得如下界面

可以看到获取了各种栈对象和ContextMap里的对象。这些信息可以帮助我们快速排查Web应用程序里的潜在隐患。


使用Debugging拦截器获取调试信息

      Debugging拦截器是默认拦截器栈defaultStack的一员,若引用了默认拦截器栈,则不需要特意去引用。使用该拦截器可以使我们查看ValueStack和其他一些对象内容。触发这个拦截器的方法是在用来触发某个动作的URL地址栏里添加debug=xml或者debug=console参数。

  debug=xml参数将会导致产生一个XML文件,它包含ValueStack和其他一些对象的值:

示例:

input.jsp

<body>
<s:form action="debug.action?debug=xml">
<s:textfield name="username" label="Enter your name"></s:textfield>
<s:submit value="submit"></s:submit>
</s:form>
</body>

struts.xml

<struts>
<constant name="struts.devMode" value="true"></constant>

<package name="debugAndProfilingPackage" extends="struts-default">
<action name="debug" class="struts2.action.DebugAction">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>

struts.devMode的默认值为false,需要将其修改为true,才可以使该功能生效。

动作类:

public class DebugAction extends ActionSupport {
private static final long serialVersionUID = -1345567815879866335L;

private String username;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

@Override
public String execute()
{
return SUCCESS;
}
}

index.jsp

<body>
<s:property value="username"/>,Welcome
</body>

在浏览器中输入:http://localhost:8081/DebugAndProfiling/input.jsp,获得如下页面:

点击"submit"按钮,查看结果:

可以看到,ValueStack和其他对象的信息。debug=console的设置与xml一致,只是好像IE不支持console选项。


使用Profiling拦截器分析应用程序的性能

      Struts 2自带的性能分析功能可以帮助我们找出应用程序里的瓶颈。该功能是由com.opensymphony.xwork2.util.profiling.UtilTimerStack类提供的支持,让Struts 2可以跟踪记录它的过滤器调度程序、每一个拦截器、每个动作和每个结果的执行用时情况。Profiling拦截器可以帮助我们激活性能分析功能。

  激活Profiling拦截器与激活Debugging拦截器相似,也是在某个动作的URL地址里加上profiling=true或profiling=yes请求参数。还必须将struts.devMode属性设置为true才能使用这个功能,否则设置不会生效。

示例:

修改上面例子的struts.xml文件

<struts>
<constant name="struts.devMode" value="true"></constant>

<package name="debugAndProfilingPackage" extends="struts-default">
<action name="debug" class="struts2.action.DebugAction">
<interceptor-ref name="profiling"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>

<result name="success">/index.jsp</result>
</action>
</package>
</struts>

因为profiling拦截器不属于defaultStack拦截器栈,需要特别引用,还需要注意Profiling拦截器所处的的位置,决定了它分析性能的范围。

修改input.jsp

<body>
<s:form action="debug.action?profiling=true">
<s:textfield name="username" label="Enter your name"></s:textfield>
<s:submit value="submit"></s:submit>
</s:form>
</body>

其他不用修改,在浏览器输入: http://localhost:8081/DebugAndProfiling/input.jsp,获得如下页面:

点击"submit"按钮,查看结果:

      该结果是在我的IDE(MyEclipse9.0)的控制台页面获取的.可以看到我们设置的Profiling拦截器生效了,它打印出了每一个流程所花费的时间。每一行代表一个活动。每行最左边的数字是截止到即将触发这个活动时已经耗用的时间。

posted @ 2011-11-18 10:42 AthrunWang 阅读(792) | 评论 (0)编辑 收藏
为Struts 2应用程序创建进度条(等待页面)

Struts 2模拟进度条的原理

      对于一些需要较长时间才能完成的任务,在Web开发中,会由HTTP协议会因为超时而断开而面临许多风险,这是在桌面开发不曾遇到的。Struts 2提供的execAndWait拦截器就是为了处理和应付这种情况而设计的。注意,该拦截器不在"defaultStack"中,所以必须在使用它的动作里声明它,并且必须放在拦截器栈的最后一个。

      使用了该拦截器后,动作依然正常执行,只是该拦截器会分配一个后台线程处理动作的运行,并在动作完成之前把用户带到一个"等待"页面。,该页面每隔一段时间刷新一次,直到那个后台线程执行完毕为止。如果用户随后又触发了同一个动作,但顶一个动作尚未执行完毕,这个拦截器将继续向用户发送"等待"结果;如果他已经执行完毕,用户会看到该动作的最终结果。

      "等待"结果的行为与"dispatcher"结果的行为很相似,但是要注意的是,"等待"结果对应的视图带有如下的meta标签:

<meta http-equiv="refresh" content="5;url=/Struts2/default_progressbar.action"/>

该标签的作用就每隔多少秒就重新加载一次同样的URL。这里"5"表示5秒,"url=/Struts2/default_progressbar.action"表示要加载的URL。

   Struts 2是一个灵活强大的框架,如果你不喜欢Struts 2提供的默认"等待页面",你也可以自己设计自己的等待页面,若在动作声明中,没有找到"等待"结果,将使用默认值。


execAndWait拦截器

execAndWait拦截器 可以接收以下参数:

  • threadPriority:分配给相关线程的优先级,默认值为Thread.NORM_PRIORITY。
  • delay:向用户发送"等待"结果前的毫秒数,默认值为0。如果你不想立刻发送"等待"结果,可以将该参数设置为一个值。例如,你想让动作超过2秒还未完成时才发送"等待"结果,需要将其值设置为2000.
  • delaySleepInterval:每隔多少毫秒唤醒主线程(处理动作的后台线程)去检查后台线程是否已经处理完成,默认值是100。这个值设为0时无效。

示例:使用默认视图与自定义视图

创建一个动作类,该动作类的工作为挂起30秒:

public class ProgressbarAction extends ActionSupport
{
private static final long serialVersionUID = 7441785390598480063L;

private int complete = 0;

// 获取进度值
public int getComplete()
{
complete += 10;
return complete;
}

@Override
public String execute()
{
try
{
Thread.sleep(30000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return SUCCESS;
}
}

配置struts.xml文件:

<package name="progressbar" extends="struts-default">
<action name="default_progressbar" class="struts2.suxiaolei.progressbar.action.ProgressbarAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="execAndWait">
<param name="delay">1500</param>
</interceptor-ref>
<result name="success">/state_ok.jsp</result>
</action>

<action name="customer_progressbar" class="struts2.suxiaolei.progressbar.action.ProgressbarAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="execAndWait">
<param name="delay">1500</param>
</interceptor-ref>
<result name="wait">/customer_wait.jsp</result>
<result name="success">/state_ok.jsp</result>
</action>
</package>

测试页面:

<body>
<s:a href="/Struts2/default_progressbar.action">default_view</s:a>
<br />
<s:a href="/Struts2/customer_progressbar.action">customer_view</s:a>
</body>

自定义等待页面:

<html>
<head>
<base href="<%=basePath%>">

<title>My JSP 'customer_wait.jsp' starting page</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">

<!-- 下面的meta元素才是重点,其他的没什么影响,是IDE自带的 -->
<meta http-equiv="refresh" content="3;url=/Struts2/customer_progressbar.action">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>
<div>
Please wait...(<s:property value="complete"/>)% complete
</div>
</body>
</html>

最终结果页面:

<body>
OK!
</body>

在浏览器中输入:http://localhost:8081/Struts2/test.jsp,获得如下页面

首先点击,"default_view"链接:


查看它的源代码:

<html>
<head>
<meta http-equiv="refresh" content="5;url=/Struts2/default_progressbar.action"/>
</head>
<body>
Please wait while we process your request...
<p/>

This page will reload automatically and display your request when it is completed.
</body>
</html>

这次点击"customer_view"链接:

...

...

这是自定义界面,最后动作执行完毕后,都会获得最终页面

我们使用Struts 2模拟进度条就完成了!

posted @ 2011-11-18 10:40 AthrunWang 阅读(1009) | 评论 (0)编辑 收藏
LinkedHashMap/HashMap(数҉据҉缓҉存҉准҉备҉)

顾名思义LinkedHashMap是比HashMap多了一个链表的结构。与HashMap相比LinkedHashMap维护的是一个具有双重链表的HashMap,LinkedHashMap支持2中排序一种是插入排序,一种是使用排序,最近使用的会移至尾部例如 M1 M2 M3 M4,使用M3后为 M1 M2 M4 M3了,LinkedHashMap输出时其元素是有顺序的,而HashMap输出时是随机的,如果Map映射比较复杂而又要求高效率的话,最好使用LinkedHashMap,但是多线程访问的话可能会造成不同步,所以要用Collections.synchronizedMap来包装一下,从而实现同步。其实现一般为: 
    Map<String String> map = Collections.synchronizedMap(new LinkedHashMap(<String String));

HashMap,LinkedHashMap,TreeMap都属于Map

Map 主要用于存储键(key)值(value)对,根据键得到值,因此键不允许键重复,但允许值重复。

HashMap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力。

LinkedHashMap LinkedHashMap也是一个HashMap,但是内部维持了一个双向链表,可以保持顺序

TreeMap 不仅可以保持顺序,而且可以用于排序

HashMap例子:

    public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("a3", "aa");
map.put("a2", "bb");
map.put("b1", "cc");
for (Iterator iterator = map.values().iterator(); iterator.hasNext();) {
String name = (String) iterator.next();
System.out.println(name);
}
}

LinkedHashMap例子:

    public static void main(String[] args) {
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("a3", "aa");
map.put("a2", "bb");
map.put("b1", "cc");
for (Iterator iterator = map.values().iterator(); iterator.hasNext();) {
String name = (String) iterator.next();
System.out.println(name);
}
}

TreeMap例子:

    public static void main(String[] args) {
Map<String, String> map = new TreeMap<String, String>(new Comparator<Object>(){
Collator collator = Collator.getInstance();
public int compare(Object o1, Object o2) {
CollationKey key1 = collator.getCollationKey(o1.toString());
CollationKey key2 = collator.getCollationKey(o2.toString());
return key1.compareTo(key2);
//return collator.compare(o1, o2);
}});
map.put("a3", "aa");
map.put("a2", "bb");
map.put("b1", "cc");
for (Iterator iterator = map.values().iterator(); iterator.hasNext();) {
String name = (String) iterator.next();
System.out.println(name);
}
}

运行这三个例子,体会一下它们之间的区别。

posted @ 2011-11-18 10:30 AthrunWang 阅读(157) | 评论 (0)编辑 收藏
浅谈Http之Get Post请求的区别

1. get是从服务器上获取数据,post是向服务器传送数据。 
2.get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP 
post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。 
3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。 
4. get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。 
5. get安全性非常低,post安全性较高。

posted @ 2011-11-18 10:28 AthrunWang 阅读(152) | 评论 (0)编辑 收藏
[笔记]war,jar包是啥

经常听开发说war,jar,car,这些是个什么东东呢?

.jar :
java archive;
包含:class、properties文件,是文件封装的最小单元;
部署文件:application-client.xml ;
级别:小;

.war :
Web Archive;
包含: Servlet、JSP页面、JSP标记库、JAR库文件、HTML/XML文档和其他公用资源文件,如图片、音频文件等;
部署文件: web.xml;
级别:中;
war包生成:
a.用eclipse等IDE,可以再项目上右击选择“导出”,即可;
b.手工制作:执行jar -cvf 将要生成的包名.war 要压缩的目录名
war包其实就是经过zip压缩的文件,用winrar压缩成zip格式,修改扩展名为war即可。


.ear :
Enterprise Archive;
包含:除了包含JAR、WAR以外,还包括EJB组件;
部署文件:application.xml;
级别:大;

以最终客户的角度来看,.jar文件就是一种封装,他们不需要知道.jar文件中有多少个.class文件,每个文件中的功能与作用,同样可以得到他们希望的结果。
war包:是做好一个web应用后,通常是网站,打成包部署到容器中。
jar包:通常是开发时要引用通用类,打成包便于存放管理。
ear包:企业级应用,通常是EJB打成ear包。
所有的包都是用jar打的,只不过目标文件的扩展名不一样

jar--封装类
war--封装web站点
ear--封装ejb

一个web组件开发者执行以下的任务来传递一个包含web组件的WAR文件:
| 编写并编译servlet源代码
| 编写jsp、html文件
| 指定web的开发描述符
| 邦定.class,.jsp,.html和部署描述符到一个WAR文件。

war包可以放在webapps或者work目录下都可以,随着tomcat的启动,它可以自动被解压.
或者通过tomcat的管理页面,也可以发布war包,发布实际上就是把war包复制到webapps目录下. 


最后关于war、jar包的打包方法,命令行方式和使用 jbuilder或者eclipse,点这里http://www.iteye.com/topic/254141

posted @ 2011-11-18 10:05 AthrunWang 阅读(7421) | 评论 (1)编辑 收藏
使用eclipse统计项目代码行数

在eclipse中, 

打开File Search对话框, 
选中正则表达式,在搜索文本框输入 \n 
文件名称输入 *.java 
在范围里选中Enclosing projects 
然后就可以统计出整个项目的代码行数。 

posted @ 2011-11-16 12:58 AthrunWang 阅读(367) | 评论 (0)编辑 收藏
applicationContext.xml

<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:configuration.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>${jndi}</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(public * com.a.b.service.*.*(..))"
id="myPointcut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" />
</aop:config>

posted @ 2011-11-02 19:12 AthrunWang 阅读(158) | 评论 (0)编辑 收藏
spring 委派Servlet代理类

import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class DelegatingServletProxy extends GenericServlet implements Servlet {
private String targetBean;
private Servlet proxy;
public void init() throws ServletException {
this.targetBean = getServletName();
getServletBean();
proxy.init(getServletConfig());
}
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
proxy.service(req, res);
}
private void getServletBean() {
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(getServletContext());
this.proxy = (Servlet) wac.getBean(targetBean);
}
}

posted @ 2011-11-02 19:11 AthrunWang 阅读(438) | 评论 (0)编辑 收藏
J2EE的核心API与组件

 J2EE平台由一整套服务(Services)、应用程序接口(APIs)和协议构成,它对开发基于Web的多层应用提供了功能支持,下面对J2EE中的13种技术规范进行简单的描述(限于篇幅,这里只能进行简单的描述):

JDBC(Java Database Connectivity)

  JDBC API为访问不同的数据库提供了一种统一的途径,象ODBC一样,JDBC对开发者屏蔽了一些细节问题,另外,JDBC对数据库的访问也具有平台无关性。

JNDI(Java Name and Directory Interface)

  JNDI API被用于执行名字和目录服务。它提供了一致的模型来存取和操作企业级的资源如DNS和LDAP,本地文件系统,或应用服务器中的对象。

EJB(Enterprise JavaBean)

  J2EE技术之所以赢得媒体广泛重视的原因之一就是EJB。它们提供了一个框架来开发和实施分布式商务逻辑,由此很显著地简化了具有可伸缩性和高度复杂的企业级应用的开发。EJB规范定义了EJB组件在何时如何与它们的容器进行交互作用。容器负责提供公用的服务,例如目录服务、事务管理、安全性、资源缓冲池以及容错性。但这里值得注意的是,EJB并不是实现J2EE的唯一途径。正是由于J2EE的开放性,使得有的厂商能够以一种和EJB平行的方式来达到同样的目的。

RMI(Remote Method Invoke)

  正如其名字所表示的那样,RMI协议调用远程对象上的方法。它使用了序列化方式在客户端和服务器端传递数据。RMI是一种被EJB使用的更底层的协议。

Java IDL/CORBA

  在Java IDL的支持下,开发人员可以将Java和CORBA集成在一起。他们可以创建Java对象并使之可在CORBA ORB中展开, 或者他们还可以创建Java类并作为和其它ORB一起展开的CORBA对象的客户。后一种方法提供了另外一种途径,通过它Java可以被用于将你的新的应用和旧的系统相集成。

JSP(Java Server Pages)

  JSP页面由HTML代码和嵌入其中的Java代码所组成。服务器在页面被客户端所请求以后对这些Java代码进行处理,然后将生成的HTML页面返回给客户端的浏览器。

Java Servlet

  Servlet是一种小型的Java程序,它扩展了Web服务器的功能。作为一种服务器端的应用,当被请求时开始执行,这和CGI Perl脚本很相似。Servlet提供的功能大多与JSP类似,不过实现的方式不同。JSP通常是大多数HTML代码中嵌入少量的Java代码,而servlets全部由Java写成并且生成HTML。

XML(Extensible Markup Language)

  XML是一种可以用来定义其它标记语言的语言。它被用来在不同的商务过程中共享数据。
  XML的发展和Java是相互独立的,但是,它和Java具有的相同目标正是平台独立性。通过将Java和XML的组合,您可以得到一个完美的具有平台独立性的解决方案。

JMS(Java Message Service)

  JMS是用于和面向消息的中间件相互通信的应用程序接口(API)。它既支持点对点的域,有支持发布/订阅(publish/subscribe)类型的域,并且提供对下列类型的支持:经认可的消息传递,事务型消息的传递,一致性消息和具有持久性的订阅者支持。JMS还提供了另
  一种方式来对您的应用与旧的后台系统相集成。

JTA(Java Transaction Architecture)

  JTA定义了一种标准的API,应用系统由此可以访问各种事务监控。
  11. JTS(Java Transaction Service):
  JTS是CORBA OTS事务监控的基本的实现。JTS规定了事务管理器的实现方式。该事务管理器是在高层支持Java Transaction API (JTA)规范,并且在较底层实现OMG OTS specification的Java映像。JTS事务管理器为应用服务器、资源管理器、独立的应用以及通信资源管理器提供了事务服务。

JavaMail

  JavaMail是用于存取邮件服务器的API,它提供了一套邮件服务器的抽象类。不仅支持SMTP服务器,也支持IMAP服务器。

JAF(JavaBeans Activation Framework)

  JavaMail利用JAF来处理MIME编码的邮件附件。MIME的字节流可以被转换成Java对象,或者转换自Java对象。大多数应用都可以不需要直接使用JAF。

posted @ 2011-10-25 14:51 AthrunWang 阅读(127) | 评论 (0)编辑 收藏
仅列出标题
共8页: 上一页 1 2 3 4 5 6 7 8 下一页