Java实践之路——EJB(一)

下面开始我的EJB之旅

 

学习任何一门技术之前,都必须简单的了解一下该技术的用途的优缺点。所以首先我们来看一下摘自百度百科上面对EJB的定义和说明

==========================================================================

EJB是sun的服务器端组件模型,最大的用处是部署分布式应用程序当然,还有许多方式可以实现分布式应用,类似微软的.net技术。凭借java跨平台的优势,用EJB技术部署的分布式系统可以不限于特定的平台。EJB (Enterprise JavaBean)是J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。 在J2EE里,Enterprise Java Beans(EJB)称为Java 企业Bean,是Java的核心代码,分别是会话Bean(Session Bean),实体Bean(Entity Bean)和消息驱动Bean(MessageDriven Bean)。

一个技术规范:EJB 从技术上而言不是一种"产品" ,EJB 是一种标准描述了构建应用组件要解决的:

  可扩展 (Scalable)

  分布式 (Distributed)

  事务处理 (Transactional)

  数据存储 (Persistent)

  安全性 (Secure)

===========================================================================

 

里面说得很多,其实我理解和关注的却并不多。首先EJB是一个服务器端的组件模型,可以部署分布式应用程序。我主要比较关注部署分布式应用程序。说实话,什么是分布式应用程序,我也是似懂非懂的,所以希望通过学习EJB更深入的了解一下。然后就是关注EJB要解决的问题了:可扩展、分布式、事务处理、数据存储和安全性。我相信,学习完后能够把这几个部分搞懂就差不多了

说起分布式组件,我相信大家会想到微软的DCOM技术,它们的区别在哪呢?跨平台问题?其他?不懂!

远程调用,和webservice有什么区别呢?摸索中

还有一点,相信很多人和我有共同的疑问。都说EJB是重量级的复杂的,然后又有很多声音说spring将会替代它(当然我们这里学习的EJB3.0以上版本的,对于老版本我们这里就不关注了),我不知道这是怎么回事。

带着这么多疑问,我们开始EJB吧


隔了这么久,总觉得难以下手。哈哈,其实也不是那么复杂。下面我们就开发部署一个无状态的提供本地接口和远程接口的Session Bean吧。


首先开发服务端,服务端必须依赖Ejb的API,首先定义本地接口ILocalCalculator.java

package stateless.ejb;

public interface ILocalCalculator {
	double add(double x,double y);
	double minus(double x,double y);
	double mutilply(double x,double y);
	double devide(double x,double y);
}

远程访问接口,IRemoteCalculator.java,继承自本地接口

package stateless.ejb;

public interface IRemoteCalculator extends ILocalCalculator {
	double power(double x,int n);
}
实现一个无状态的Session Bean,CalculatorBean.java

package stateless.ejb;

import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;

@Stateless
@Remote({IRemoteCalculator.class})
@Local({ILocalCalculator.class})
public class CalculatorBean implements IRemoteCalculator {

	@Override
	public double add(double x, double y) {
		return x+y;
	}

	@Override
	public double devide(double x, double y) {
		
		if(y==0)
		{
			return 0;
		}
		return x/y;
	}

	@Override
	public double minus(double x, double y) {
		return x-y;
	}

	@Override
	public double mutilply(double x, double y) {
		return x*y;
	}

	@Override
	public double power(double x,int n) {
		double result=1;
		
		for(int i=1;i<=n;i++)
		{
			result*=x;
		}
		
		return result;
	}

}

接下来时部署,打包这以上三个文件EjbService.jar,放到JBOSS_HOME\server\default\deploy目录下,然后打包一份接口供客户端使用,包含两个接口文件,EjbServiceInterface.jar.


接下来就是客户端调用了,开发EjbBean.java

package bean;

import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import stateless.ejb.ILocalCalculator;
import stateless.ejb.IRemoteCalculator;

public class EjbBean {
	/**
	 * 通过调用ejb服务计算结果
	 * @param x
	 * @param y
	 * @param operator
	 * @param type 1-local,2-remote
	 * @return
	 */
	public double Calc(double x,double y,String operator,int type)
	{
		Properties props = new Properties();        
        props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
        props.setProperty("java.naming.provider.url", "localhost:1099");
        InitialContext ctx =null;
		try {
			ctx = new InitialContext(props);
			if(type==1)
	        {
				ILocalCalculator calculator=(ILocalCalculator)ctx.lookup("CalculatorBean/local");
				if(operator.equals("+"))
				{
					return calculator.add(x, y);
				}
				else if(operator.equals("-"))
				{
					return calculator.minus(x, y);
				}
				else if(operator.equals("*"))
				{
					return calculator.mutilply(x, y);
				}
				else if(operator.equals("/"))
				{
					return calculator.devide(x, y);
				}
	        }
	        else if(type==2)
	        {
	        	IRemoteCalculator calculator=(IRemoteCalculator)ctx.lookup("CalculatorBean/remote");
	        	
	        	if(operator.equals("+"))
				{
					return calculator.add(x, y);
				}
				else if(operator.equals("-"))
				{
					return calculator.minus(x, y);
				}
				else if(operator.equals("*"))
				{
					return calculator.mutilply(x, y);
				}
				else if(operator.equals("/"))
				{
					return calculator.devide(x, y);
				}
				else if(operator.equals("power"))
				{
					return calculator.power(x, (int)y);
				}
	        }
		} catch (NamingException e) {
			e.printStackTrace();
		}
		return 0.0001;
	}
}

这里必须添加EjbServiceInterface.jar依赖,

然后就是开发service,EjbService.java

package service;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Vector;

import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import bean.EjbBean;
import bean.EmailBean;
import entity.Email;

public class EjbService {
	private HttpServletRequest req;
	private HttpServletResponse res;
	
	public HttpServletRequest getReq() {
		return req;
	}

	public void setReq(HttpServletRequest req) {
		this.req = req;
	}

	public HttpServletResponse getRes() {
		return res;
	}

	public void setRes(HttpServletResponse res) {
		this.res = res;
	}

	public EjbService()
	{
		
	}
	
	public EjbService(HttpServletRequest req,HttpServletResponse res)
	{
		this.req=req;
		this.res=res;
	}
	
	public void calc(double x,double y,String operator,int type)
	{
		EjbBean bean=new EjbBean();
		
		double result = bean.Calc(x, y, operator, type);
		
		try {
			PrintWriter out =this.res.getWriter();
			out.print(result);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

然后就是请求处理,EjbServlet.java

package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import service.EjbService;
import service.EmailService;

public class EjbServlet extends HttpServlet {

	private EjbService service;
	/**
	 * Constructor of the object.
	 */
	public EjbServlet() {
		super();
	}

	/**
	 * Destruction of the servlet. 
*/ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet.
* * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); service=new EjbService(request,response); String action=""; action=request.getParameter("action"); if(action==null || action.equals("")) { return; } //集中处理请求类型 if(action.toUpperCase().equals("CALCRESULT")) { double x=Double.parseDouble(request.getParameter("x_value")); double y=Double.parseDouble(request.getParameter("y_value")); String operator=request.getParameter("operator"); String method=request.getParameter("method"); int type=1; if(method.equals("remote")) { type=2; } service.calc(x, y, operator, type); } } /** * The doPost method of the servlet.
* * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } /** * Initialization of the servlet.
* * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here } }

最后就是呈现层的入口


EJB客户端

ajax请求

function calc()
	{
		var x=$("#x").val();
		var y=$("#y").val();
		//必须引入支持select标签的jquery扩展 jquery.select.js
		var oper=$("#operator").getSelectedValue();

		var type="local";

		if(oper=="power")
		{
			type="remote";
		}
		$.get("EjbServlet",{action:"CALCRESULT",x_value:x,y_value:y,operator:oper,method:type},function(data)
		{
				$("#calc_result").val(data);
		});
	}

好,到这里就开发好了。启动jboss服务器,输入数据测试通过。

 

总结:

1、在开发中遇到一个问题,报错信息为

msg:javax.naming.NameAlreadyBoundException: remote

仔细琢磨了一下,发现在导出jar文件给客户端使用时,不能包含实现进去,只能包含提供的接口。在现实开发部署中也正是这样,提供给客户端使用的肯定只有接口,不然EJB就失去了它的意义。而且根据这个错误提示,应该是服务器和客户端在同一台电脑上部署执行才会出现这个错误。猜想是这样的,不知道是否正确

2、这里开发的无状态的Session Bean。那有状态的Session Bean和这个有什么区别呢。

其实有状态的就是会记录用户的状态。举个例子。比如说服务端EJB中有一个成员变量total,实现的功能是每次登陆时加1操作,无状态的就是每个用户登陆一次都会对这个数据进行加1,而有状态的是会分别记录每个用户登陆的次数,而不是所有用户的总登陆次数,现在理解的它们的区别就在这里。其它的待挖掘。如果你有什么更好的理解,请不吝赐教。

你可能感兴趣的:(java,ejb,java,分布式应用,bean,session,string)