posts - 66,  comments - 11,  trackbacks - 0
Spring提供了对Sun的标准的持久化API-JDO的整合,以及其他开放源码的ORM框架,如Hibernate、ApacheOJB和iBATIS SQL Maps.Spring对这些技术的支持没有像它对JDBC的支持那么广泛。
<?xml version="1.0" encoding="UTF-8"?>
<beans
    
xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        
<property name="jndiName">
            
<value>java:comp/env/jdbc/trainingDatasource</value>
        
</property>
    
</bean>
    
<!-- 管理Hibernate资源,在应用的整个生命周期里,你只要保存一个SessionFactory实例就可以了。-->
    
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        
<!-- 先要知道连接哪个数据源 -->
        
<property name="dataSource">
            
<ref bean="dataSource"/>
        
</property>
        
<!-- Hibernate本身有数十个属性,通过这些属性你就可以控制它的行为。当在Spring之外使用Hibernage的时候,
        Hibernate在应用的class path下的某个地方寻找一个名叫hibernate.properties的文件,并用它来进行配置。
        然而,用Spring就不需要在一个独立的属性文件里管理这些配置。 
-->
        
<property name="hibernateProperties">
            
<props>
                
<prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
            
</props>
        
</property>
        
<!-- 同样,你也要告诉Spring从哪里读取Hibernate.hbm.xml映射文件 -->
        
<property name="mappingResources">
            
<list>
                
<value>Student.hbm.xml</value>
            
</list>
        
</property>
        
<!-- 还有一种简单的方法设置映射文件资源,你可以用你应用的class path下的一个子路径来配置
        mappingDirectoryLocation属性,spring将找到这个路径下的每个*.hbm.xml文件,来配置SessionFactory 
-->
        
<property name="mappingDirectoryLocations">
            
<list>
                
<value>classpath:/com/springinaction/training/model</value>
            
</list>
        
</property>
    
</bean>
    
<!-- 如果把这个模版对象织入到一个个DAOBean中显得很麻烦的时候,可以使用Spring自动连接功能来将模版对象隐士的织入到
    DAObean. 
-->
    
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
        
<property name="sessionFactory">
            
<ref bean="sessionFactory"/>
        
</property>
    
</bean>
    
</beans>
posted @ 2009-11-14 15:59 王永庆 阅读(252) | 评论 (0)编辑 收藏

调用存储过程:
Spring通过实现CallableStatementCallback来支持存储过程。假定有个存储过程的名字是ARCHIVE_STUDENTS,执行代码如下:

package com.testproject.spring.datasource;

import java.sql.CallableStatement;
import java.sql.SQLException;

import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.JdbcTemplate;
/*
 * 为了让JdbcTemplate工作,它所需要的,只是一个DataSource实例。
 
*/

public class StudentDaoImpl implements StudentDao {
    
private JdbcTemplate jdbcTemplate;
    
    
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        
this.jdbcTemplate = jdbcTemplate;
    }

    
/**
     * 调用存储过程,通过CallableStatementCallback来实现
     
*/

    
public void archiveStudentData(){
        CallableStatementCallback cb 
= new CallableStatementCallback(){
            
public Object doInCallableStatement(CallableStatement cs)throws SQLException{
                cs.execute();
                
return null;
            }

        }
;
        jdbcTemplate.execute(
"{ARCHIVE_STUDENTS}",cb);
    }

}


把操作创建成对象:

插入:

package com.testproject.spring.datasource;

import java.sql.Types;

import javax.sql.DataSource;

import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.SqlUpdate;
/**
 * Spring提供了一种真正把数据库操作建模成对象的方法,这样就在的代码和直接JDBC之间又加了一个绝缘层。
 * 首先,这些数据库操作对象是线程安全的,意味着对于每个数据库操作,你只需创建一个实例。
 * 其次,任何数据库操作对象必须在运行前先编译一下,这样就让对象知道什么时候可以预备statement,以便在稍后能执行它们。
 * 使用:
 * private InsertPerson insertPerson;
 * public int insertPerson(Person person){
 *     return insertPerson.insert(person);
 * }
 *
 
*/

public class InsertPerson extends SqlUpdate {
    
public InsertPerson(DataSource ds){
        
//首先要给sqlUpdate提供一个DataSource,用来创建JdbcTemplate
        setDataSource(ds);
        setSql(
"insert into person(id,firstName,lastName) values(?,?,?)");
        
//其次,我们需要为statement中的每个参数调用这个方法,顺序也是很重要的
        declareParameter(new SqlParameter(Types.NUMERIC));
        declareParameter(
new SqlParameter(Types.VARCHAR));
        declareParameter(
new SqlParameter(Types.VARCHAR));
        
//最后编译它,每个数据库操作对象必须在它被使用之前编译好。
        compile();
    }

    
public int insert(Person person){
        Object[] params 
= new Object[]{
                person.getId(),
                person.getFirstName(),
                person.getLastName()
        }
;
        
return update(params);
    }

}

查询:

package com.testproject.spring.datasource;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import javax.sql.DataSource;

import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.MappingSqlQuery;

/**
 * 使用:
 * private PersonByIdQuery personByIdQuery;
 * public person getPerson(Integer id){
 *     Object[] params = new Object[]{id};
 *  return (Person)personByIdQuery.execute(params).get(0);
 * }
 *
 
*/

public class PersonByIdQuery extends MappingSqlQuery {
    
    
public PersonByIdQuery(DataSource ds){
        
super(ds,"select id,first_name,last_name from person where id=?");
        declareParameter(
new SqlParameter("id",Types.INTEGER));
        compile();
    }

    
    
protected Object mapRow(ResultSet rs, int rowNumber) throws SQLException {
        Person person 
= new Person();
        person.setId((Integer)rs.getObject(
"id"));
        person.setFirstName(rs.getString(
"first_name"));
        person.setLastName(rs.getString(
"last_name"));
        
return person;
    }


}

 

posted @ 2009-11-14 15:21 王永庆 阅读(271) | 评论 (0)编辑 收藏
实现WEB服务客户
web服务是跨平台的、跨语言的,所以WEB服务的客户端使用的语言和平台和他的服务端没有必然的关系。比如我们可以在.Net下开发、部署web服务,然后在J2EE平台下调用它,或者使用在J2EE平台下开发、部署web服务,然后使用VB来调用它。
在J2EE平台中,WEB服务客户同EJB客户类似。如下两种方式能够访问到WEB服务:
1、不借助于JNDI查找,即使用单独的JAX-RPC客户访问。
2、借助于JNDI上下文访问WEB服务的J2EE客户
第一种方法称之为静态存根,此时需要在客户端预先生成SOAP客户存根,这同RMI存根类似。第二种方法称之为动态代理。它将在运行时获得WSDL描述,然后创建动态代理。无论采用哪种方式访问WEB服务,客户都需要获得服务Endpoint地址URL,否则单凭JNDI名是很难访问到WEB服务的。
package com.testproject.ejb.web;

import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;

/**
 * 单独JAX-RPC客户代码实例。
 * 它使用了动态代理方法,以获得对远程WEB服务的引用。
 *
 
*/

public class HelloClient {
    
static String host = "localhost";
    
//web服务的名字
    static String serviceURL = "HelloBean";
    
//名称空间
    static String nameSpaceUri = "urn:examples";
    
static String serviceName = "HelloWorldWS";
    
//web服务调用的地址
    static String serviceEndpointAddress = "http://"+host+":8000"+serviceURL;
    
public static void main(String[] args)throws Exception{
        HelloInterface hello 
= null;
        
//动态代理方法
        
//1、指定WSDL文件的位置
        URL url = new URL(serviceEndpointAddress+"?WSDL");
        
//2、创建服务工厂实例
        ServiceFactory serviceFactory = ServiceFactory.newInstance();
        
//3、创建服务对象,以作为代理工厂
        Service HelloService = serviceFactory.createService(url,new QName(nameSpaceUri,serviceName));
        
//4、获得port引用
        hello = (HelloInterface)HelloService.getPort(HelloInterface.class);
        
//调用hello()方法
        System.out.println("Dynamic Proxy:"+hello.hello());
    }

}

posted @ 2009-11-13 16:45 王永庆 阅读(131) | 评论 (0)编辑 收藏
EJB2.1和web服务
1、下载安装服务器后,需要设置环境变量。
Set J2EE_HOME=J2EE安装目录
Set CLASSPATH 
=%CLASSPATH%;%J2EE_HOME%\\lib\\j2ee.jar;.
Set Path =%Path%;%J2EE_HOME%\\bin;.

2、创建初始目录
+HelloBeanService
    +META-INF(application.xml;sun-j2ee-ri.xml )
    +ejb
       +META-INF(ejb-jar.xml; webservices.xml;mapping.xml)
       -*.java文件(EJB相关的类)
       -config.xml
3、定义web服务接口
package com.testproject.ejb.web;

/*
 * Hello服务Endpoint接口
 * 需要注意的是,这里使用的是EJB2.1无状态会话Bean,它作为WEB服务端点时可以不提供Home接口和Remote
 * Locale接口,它提供的是web服务端点接口,这个接口扩展了Remote接口。
 
*/

public interface HelloInterface extends java.rmi.Remote {
    
public String hello()throws java.rmi.RemoteException;
}


4、实现服务端点接口
package com.testproject.ejb.web;

import java.rmi.RemoteException;

import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

/*
 * 定义了服务端点接口,接下来的任务就是开发无状态会话Bean。无状态会话Bean同样需要实现SessionBean接口,
 * 服务端点接口定义的方法在会话Bean中实现。
 
*/

public class HelloBean implements SessionBean {
    
    
public void ejbCreate(){
        
/*
         * 这里不能接收任何参数
         
*/

    }


    
public void ejbActivate() throws EJBException, RemoteException {
    }


    
public void ejbPassivate() throws EJBException, RemoteException {
    }


    
public void ejbRemove() throws EJBException, RemoteException {
    }


    
public void setSessionContext(SessionContext arg0) throws EJBException,
            RemoteException 
{
    }

    
/*
     * 业务方法:输出hello
     
*/

    
public String hello(){
        
return "Hello wyq";
    }


}


5、创建EJB描述
用于部署成Web服务的无状态会话Bean的描述符和普通的无状态会话Bean不同ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="2.1"
xmlns
="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
    
<display-name>HelloBean</display-name>
    
<enterprise-beans>
        
<session>
            
<display-name>HelloBean</display-name>
            
<ejb-name>HelloBean</ejb-name>
            
<service-endpoint>com.testproject.ejb.web.HelloInterface</service-endpoint>
            
<ejb-class>com.testproject.ejb.web.HelloBean</ejb-class>
            
<session-type>Stateless</session-type>
            
<transaction-type>Container</transaction-type>
        
</session>
    
</enterprise-beans>
</ejb-jar>

在这个新的部署描述符中,使用<service-endpoint>指定了服务端点,同时,必须指定EJB为无状态会话Bean
6、生成WEB服务描述

下面的任务就是生成一个Web服务描述,我们通常使用工具来生成这个描述符。在这里使用J2EE提供的wscompile工具来生成。在使用wscompile工具生成web服务描述前,首先手工编写一个简单的XML描述config.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
    
<service 
        
name="MyHelloBeanService" 
        targetNamespace
="urn:HelloBean" 
        typeNamespace
="urn:HelloBean"
        packageName
="helloBeanService">
        
<interface name="com.testproject.ejb.web.HelloInterface"/>
    
</service>
</configuration>

在这个描述中,指定了目标的名称空间、包的名字和Web服务端点接口:HelloInterface。如下命令就可以生成一个web服务描述

c:\\ HelloBeanService\\ejb \\>wscompile -define -d . -nd . -classpath . config.xml
自动生成MyHelloBeanService.wsdl文件。
7、编写一个web服务映射文件:
在ejb\\META-INF目录下新建一个mapping.xml文件,然后编辑这个描述符
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE java-wsdl-mapping PUBLIC
    "-//IBM Corporation,Inc.//DTD J2EE JAX-RPC mapping 1.0//EN"
    "http://www.ibm.com/standards/xml/webservices/j2ee/j2ee_jaxrpc_mapping_1_0.dtd"
>
<java-wsdl-mapping>
    
<package-mapping>
        
<package-type>HelloBeanService</package-type>
        
<namespaceURI>urn:HelloBean</namespaceURI>
    
</package-mapping>
</java-wsdl-mapping>
8、编写webservices.xml文件
另外,还需要提供webservices.xml文件,并存放到Ejb-jar存档的META-INF目录中。各个J2EE产品可能提供相应的部署工具来创建这个文件。
9、EJB打包
另外,web服务部署描述符在EJB-JAR文件中的位置是META-INF/webservices.xml.把生成的HelloBeanService.wsdl拷贝到ejb\\META-INF目录下
c:\\HelloBeanService\\ejb\\jar cvf ejb.jar com META-INF
10、Application打包
HelloBeanService\\MEAT-INF目录下创建2个文件:application.xml和sun-j2ee-ri.xml
application.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC '-//Sun Microsystems,
    Inc.//DTD J2EE Application 1.3//EN'
    'http://java.sun.com/dtd/application_1_3.dtd'
>
<application>
    
<description>Application description</description>
    
<display-name>HelloBeanServiceApp</display-name>
    
<module>
        
<ejb>ejb.jar</ejb>
    
</module>
</application>

最后归档
c:\\ HelloBeanService\\ejb\\>copy ejb.jar ../
c:\\ HelloBeanService\\ejb\\>cd..
c:\\ HelloBeanService\\\\>jar cvf encryptservice.ear ejb.jar META-INF

 


 

posted @ 2009-11-13 16:13 王永庆 阅读(150) | 评论 (0)编辑 收藏
     摘要:     Spring的一个目标就是让你遵循对接口编程的面向对象原则。DAO的存在提供了读写数据库中数据的一种方 法。只要把这个功能通过接口暴露,应用的其他部分就可以通过这些接口访问数据库了。     在Spring的DAO框架里,Connection对象是通过DataSource获得的。     从JN...  阅读全文
posted @ 2009-11-12 19:46 王永庆 阅读(182) | 评论 (0)编辑 收藏
    这次的辞职和以往有些不同,以前的辞职都是怀着迫不及待的心情,而且离职之后心情特别舒畅。但是这次辞职之后总是感觉心里空荡荡的。由于从金钱、从发展、从技术、还有从管理的经验上,我都觉得这里没有我发展的空间,感觉自己有能力带出一个出色的团队,所以离职是必须的。但是这种空荡的源头我还没有找到,是想念以前的那些好兄弟、好姐妹。还是想念那个不知道我在想什么的她。
    感觉自己心里的牵挂太多,不是说她。自己做了10多个场景,有复杂有简单的,离开公司之后,还想着那些接我的人能不能把我的场景接好。就在昨天晚上,还有个新来的小伙问了我些问题,看来接手的不是太顺利。没有办法,公司的开发模式就是这样,有利有弊,接手的人只要能干活就可以了,不需要你思考。我讨厌这种模式,而且他也没有重要的对待我。只有离开是我的选择。担心我们的团队,担心我的主管,担心我的队友。现在团队非常混乱,有很多人提出离职,他们太盲目了,没有目的性,就像我和我好朋友说的,我是谋定而后动,他则是先动而后谋,他的下分工作目标可能是工作轻松点,钱拿的多点,我们公司确实太累了。而我的目标就是项目经理,在这个公司的期间,我每次看到团队遇到困难的时候,我都能看到事情的本质,所以看问题还是很准的,自己也想去尝试一下。
     你的羽翼已经丰满了,就是缺少在蓝天下翱翔的经验,自己慢慢积累吧,在这个项目里我不能在给你什么了,我剩下的只有自己的经验和技术,自己的经验属于自己的。前几天还在哭鼻子的你,坚强点吧,你已经长大了,遇到问题想办法去解决它,不要去回避。不知道你想不想在这个程序的世界里自由翱翔,不知道你的心有没有那么大,我看到的你是不属于程序的这片天空的,所以还在担心走在这条路上的你。多余了,因为飞在路上的你根本就没想到你在成长路上的我。
    希望你们一切都好,我的大家,我也会在自己的道路上努力,我相信我自己,我也相信我们的友谊。
posted @ 2009-11-11 11:35 王永庆 阅读(183) | 评论 (0)编辑 收藏
年终奖"除12"税收优惠

按照《国家税务总局关于调整个人取得全年一次性奖金等计算征收个人所得税方法问题的通知》规定,对个人某个月取得的全年一次性奖金,可以先除以12个月,再按其商数确定适用税率和速算扣除数。

具 体的解释是,行政机关、企事业单位向其雇员发放的一次性奖金(包括:年终加薪、实行年薪制和绩效工资办法的单位,根据考核情况兑现的年薪和绩效工资)可单 独作为一个月工资、薪金所得计算纳税,并按以下计税办法:先将雇员当月内取得的全年一次性奖金,除以12个月,按其商数确定适用税率和速算扣除数。如果雇 员当月工资薪金所得高于(或等于)税法规定的费用扣除额(个税起征点)的,则将一次性奖金全额作为应税所得额,计算应纳税额。适用公式为:应纳税额=雇员 当月取得全年一次性奖金×商数对应的适用税率-速算扣除数。

而在这个规定之前,个人所取得的年终奖金是全额作为应纳税所得额来寻找适用税率及速算扣除数的。具体公式为:应纳税额=雇员当月取得的全年一次性奖金*奖金全额对应的适用税率-对应的速算扣除数。

可别小看这"12",如此这般将年终奖先除以12,所得税率可就大大降低了,能为员工减轻不少税负呢。

比 如,某私营企业主王老板要给自己的得力干将张先生准备年终奖。年终奖为12000元,按原有规定,12000元作为单月收入,对应的适用税率为20%,速 算扣除数为375元,则张先生这笔年终奖应纳个人所得税款为2025元(12000×20%-375)。但若按新办法,张先生12000元年终奖先除以 12,得到商数为1000元,1000元对应的适用税率为10%,速算扣除数为25。因此,新办法下,张先生只需交纳个人所得税1175元 (12000×10%-25)。也就是说,如果采用新办法,张先生可少交850元的个人所得税。换而言之,张先生实际拿到手的税后年终奖可以多850元。

月薪较低者还有"特别"优惠

对于日常每月工资较低的个人,年终奖还会有另一层税收优惠。为此,平常对员工比较"抠门"的老板,可要发发善心,在过年前给员工多些奖金哦。

按 照前述国家税务总局的《通知》规定,如果在发放一次性奖金的当月,雇员工资薪金所得低于税法规定的费用扣除额(即个税起征点,2006年1月1日后全国统 一为1600元),应将全年一次性奖金减去"雇员当月工资薪金所得与费用扣除额的差额"后的余额作为应纳税额,再按前述办法确定全年一次性奖金的适用税率 和速算扣除数。

具体如下:如果雇员当月工资薪金所得低于税法规定的费用扣除额的,适用公式为:应纳税额=(雇员当月取得全年一次性奖金-雇员当月工资薪金所得与费用扣除额的差额)×适用税率-速算扣除数。

比 如,王老板手下有个普通工人蒋某,虽然月薪只有1200元,但平常工作非常卖力,尤其最近大半年来表现特别突出,长进很快。新年到了,王老板准备在年轻工 人中间树立一个学习典型,蒋某正是一个不错的选择。那么,王老板完全可以通过给蒋某多发放一些年终奖,并拉开蒋某所获年终奖与其他同级工人年终奖所得距离 的方式,暗示大家公司是"奖优惩劣"的,由此激励年轻人要奋发图强,多为企业做绩效。若王老板此次给蒋某发放6000元的年终奖,按照原来的老办 法,6000元奖金对应的所得税率为20%,速算扣除数为375元,蒋某需要被缴纳的个人所得税额为825元(6000×20%-375),实际拿到手的 税后奖金为5175元。

而按照新办法,则蒋某这笔年终奖可以先除以12,得到商数为500,对应的所得税率为5%,速算扣除数为0。 同时,由于蒋某当月的工资收入只有1200元,比国家规定的1600元费用扣除额还低400元,因此蒋某这笔年终奖实际的应纳税额为5600元 (6000-400),其应该被缴纳的个人所得税额为108元(5400×5%-0),实际拿到手的税后奖金有5892元。

分次奖金不如归总发放

但是,老板们还必须明确一个概念,国家税务总局对于年终奖这样一次性发放的奖金税收优惠政策,每个员工每年只能享受一次。

因为前述《通知》规定,在一个纳税年度里,对每一个纳税人,该计算办法只允许采用一次。同时,雇员取得除全年一次性奖金以外的其他各种名目奖金,如半年奖、季度奖、加班奖、先进奖、考勤奖等,仍旧是一律与当月工资、薪金合并,按税法规定缴纳个人所得税。

正 是基于这一点,我们在此提出一个发放奖金的窍门,就是如果老板们想为员工尽量减轻税负,应尽量减少季度奖、半年奖等名目繁多的奖金发放次数,而是把这些本 欲发放的奖金先在平时"记账",然后和年终奖一起,一次性发给员工。这样一来,员工全年得到的税后奖金收入,并不会减少,反而会增加。

比 如,作为王老板得力助手的张先生,除了12000元的年终奖,王老板每个季度还会发2000元的季度奖金给他。由于张先生的月工资为6000元,平常每月 的应纳税所得额6000-1600=4400元,对应的适用税率为15%,速算扣除数为125元,应纳税额为535元。但每次发放季度奖时,都必须与其当 月的工资收入合并缴税,所以每次发放季度奖的那个月,也是他最不愿意看到工资明细单的那个月--那个月的所得税率和所得税额令他非常"郁闷"。在那些月份 里,他的当月所得总额为8000元,减去1600元的起征点(费用扣除额),应纳税所得额为6400元,对应的适用税率为20%,对应的速算扣除数为 375元,应纳税额为905元。所以说,2000元的季度奖为他当月增加了370元(905-535)的税收负担。一年四个季度,四次季度奖一共缴税 1480元。加上12000元的单次年终奖所得税为1175元,那么张先生需要全年总共2万元的奖金缴纳所得税2655元。

如果王老板平时不给张先生分次发季度奖,而是将总共8000元的季度奖与12000元的年终奖一起放在元月发放,那么张先生的年度奖金一共需要缴税1975元(20000×10%-25)。

显然,对于张先生而言,一般来说是更乐意接受老板一次性给他发放年终奖2万元,而不是将2万元拆开为季度奖和年终奖分次发放,因为这样可以减少680元的税金负担。

我国个人所得税税率表(工资、薪金所得适用)

级数 全月应纳税所得额 税率(%) 速算扣除数(元)
1 不超过500元的 5 0
2 超过500元至2000元的部分(含2000元) 10 25
3 超过2000元至5000元的部分(含5000元) 15 125
4 超过5000元至20000元的部分(含20000元) 20 375
5 超过20000元至40000元的部分(含40000元) 25 1375
6 超过40000元至60000元的部分(含60000元) 30 3375
7 超过60000元至80000元的部分(含80000元) 35 6375
8 超过80000元至100000元的部分(含100000元) 40 10375
9 超过100000元的部分 45 15375


注:正常月份下,工资,月应纳税所得额= 月工资、薪金所得-1600元;月应纳税额= 月应纳税所得额×适用税率-速算扣除数
posted @ 2009-11-09 10:57 王永庆 阅读(1004) | 评论 (0)编辑 收藏
    Web服务是构建B2B应用最为重要的利器之一,使用它能够构建、集成大型的系统。这一切都是通过发送XML消息给已定义的模块化接口完成的。借助于无状态会话Bean能够构建Web服务。为实现Java客户对Web服务的访问,需要使用到JAX-RPC.Web服务是构建SOA的一种方式。SOA是架构方法,它能够将各种异构应用集成起来,并组成更大的分布式应用,最后通过服务接口的形式将整个应用支撑起来。
    服务提供者创建抽象服务定义,并将它发布到服务注册器中。对于WEB服务而言,服务定义是通过WSDL文件给出的;服务注册器需要遵循UDDI标准。服务请求者可以使用一套查询机制从服务注册器中查找到WSDL文件,如果找到合适的服务定义,请求者将绑定到服务提供者上。
    服务接口类似于对象或EJB接口。但是对于WEB服务而言,服务接口更为灵活。比如服务实现和客户处于松耦合的关系,而这在其他EJB应用或分布式应用中是实现不了的。这种松耦合使得客户和服务实现能够运行在不同平台上,比如Microsoft.NET客户能够访问到J2EE应用服务器中所运行的服务。另外,相比Java对象而言,Web服务实体的粒度更粗。
    通过标准化接口,能够加强SOA的模块化;通过松耦合,能够提高SOA的灵活性;通过XML,能够增强SOA扩展性。在B2B场合,这些都是很重要的因素。WEB服务能够在那些使用了多种异构平台的企业应用中大显身手。所有的WEB服务都是构建在XML和Internet协议上的。EJB只能够采用Java开发。如果使用其他语言开发应用,互操作如何实现?
    组成WEB服务的事实标准可以通过如下等式表达:
    Web服务 = WSDL+SOAP+UDDI

1、WSDL语言比Java更抽象、广度更大。HelloWorldWSDL中存在<service>标签,它能够在具体地址提供若干<port>.<port>代表了服务接口及对具体协议的绑定。
2、服务描述包含了Endpoint地址。WSDL是由Java接口和对象引用构成的。换句话说,Web服务不存在真正的实体,它们不是对象,因此必须将它们按照模块化对待。
3、根据输入、输出定义操作。开发者需要将输入、输出消息表示为XML元素。
4、采用的绑定是SOAP绑定。到目前为止,只能采用SOAP绑定。也请注意,<soap:binding>标签还存在style="rpc"属性,因此可以看出style还存在其他取值,目前,用于交换SOAP消息的另一种风格是文档风格(document-style)。文档风格意味着在SOAP消息体中不在包含对具体操作的描述。

    SOAP协议为Web服务和它们的客户定义了XML消息格式。SOAP消息格式非常简单。它实际包含两部分内容:其一,HTTP POST请求头信息。其二,XML文档,这就是SOAP信封(Envelope)。另外,通过上述两分SOAP消息,我们还想表达Web服务中的另一个重要概念。从SOAP协议的使用过程来看,它非常轻量,因为它对处于交互中的客户和服务没有任何限制。但是,从SOAP协议的大小、性能角度考虑,它并不轻量。如果不压缩SOAP消息,则需要在网络上传递大量的SOAP数据消息。因此,采用二进制更为明智,比如CORAB的IIOP协议。对于含有大量的SOAP数据消息进行压包和解包操作将耗费大量的CPU时间。请不要忘记,WEB服务的诞生背景,它只是为集成应用而来的,而不是替换现有的高性能中间件平台技术。否则,就不需要使用web服务了。

    XML文档和平台无关性,借助于标准化的XML文档,WEB服务能够帮助集成异构的分布式系统。在实际应用开发过程中,它具有许多优势,比如松耦合、平台无关性、遵循XML方面的标准、能够合并不同的XML技术等。借助于XML能够实现应用和中间件平台的松耦合,这是很重要的优势。
    比如在开发EJB组件时,客户和服务器端同事需要使用组件接口。一旦组件接口发生变动,比如需要往方法签名中新增参数,则EJB组件本身需要重新构建、集成、部署。当然,客户也逃脱不了重新编译的命运。因此,它们之间并没有实现松耦合,开发者不能独立的开发应用组件。否则,一旦某些组件发生变动,应用的其他部分也需要变动。我们都希望应用具有良好的扩展性。对基于IIOP的请求消息而言,所有的参与者必须使用相同的类型信息,否则不能够正确对消息进行解包操作。而且,在IIOP技术领域中,应用必须能够理解消息的所有内容。如果基于XML和XML消息开发应用,则这些限制将不复存在。
   
    J2EE平台技术对WEB服务提供了一流的支持能力。无论WEB服务实现,还是WEB服务客户,都可以使用JAVA语言开发完成。在J2EE中,使用WEB服务同RMI、RMI-IIOP并没有多大区别。他们都将具体传输层屏蔽掉,使得开发者能够专注于业务逻辑。
    JSR921规范,即实现企业WEB服务,定义了WEB服务编程模型。它使用术语port组件,描述web服务的服务器端视图。它是服务接口的java实现。而且,它遵循服务接口到Java的映射,并提供了相应的Java实现。需要将它部署并运行在容器中。使用EJB开发WEB服务需要创建若干port组件。其中,还需要提供若干XML部署描述符。当然,直接基于EJB实现WEB服务是J2EE平台中实现WEB服务的最大优势。

    JAX-RPC服务端点接口,现在,来开发另一远程接口,它将企业Bean所提供的业务方法都列举出来,我们称之为服务Endpoint接口(Service Endpoint Interface,SEI),下面给出了代码。
   

package com.testproject.ejb.web;

/*
 * Hello服务Endpoint接口
 * 需要注意的是,这里使用的是EJB2.1无状态会话Bean,它作为WEB服务端点时可以不提供Home接口和Remote
 * Locale接口,它提供的是web服务端点接口,这个接口扩展了Remote接口。
 
*/

public interface HelloInterface extends java.rmi.Remote {
    
public String hello()throws java.rmi.RemoteException;
}

 

    JAX-RPC要求WEB服务提供SEI,EJB容器同WEB服务交互时需要使用它。JAX-RPC规范要求SEI遵循如下规则:
1、接口必须间接或直接继承java.rmi.Remote.
2、所有的方法必须抛出java.rmi.RemoteException.
3、方法参数和返回类型必须是JAX-RPC支持的JAVA类型。
4、SEI中不能包含敞亮。

    在J2EE1.4平台中,可以对EJB技术进行了升级,使得无状态会话Bean可以直接部署为Web服务端点。这样,在J2ee1.4平台下,开发Web服务将更加简单。这样,EJB2.1中的无状态会话Bean可以有3种不同的客户端:本地接口的客户端、远程接口的客户端和web服务客户端。EJB的WEB服务客户端视图通过WSDL文档描述。
    待续......

 


 


    

   
posted @ 2009-11-09 10:22 王永庆 阅读(146) | 评论 (0)编辑 收藏
当我们有很多类需要通知时,显示的创建每个代理就会显得很笨拙。幸运的是,Spring有一个自动代理机制,它可以让容器为我们产生代理。Spring有2个类提供这种服务:BeanNameAutoProxyCreate和DefaultAdvisorAutoProxyCreator.

BeanNameAutoProxyCreate:为匹配一系列名字的Bean自动创建代理。它也允许在名字的2端进行通配符的匹配。
<?xml version="1.0" encoding="UTF-8"?>
<beans
    
xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    
<bean id="performanceThresholdInterceptor" class="com.wyq.spring.common.aopinstance.autoproxy.PerformanceThresholdInterceptor">
        
<constructor-arg>
            
<value>5000</value>
        
</constructor-arg>
    
</bean>
    
<!-- 
        如果Bean是一个Advisor或拦截器,它将应用到代理对象的所有方法上。如果是通知的话,Advisor切入点
        会根据不同Bean将通知应用到不同的地方。
     
-->
    
<bean id="performanceThresholdProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        
<property name="beanNames">
            
<list>
                
<value>*Service</value>
            
</list>
        
</property>
        
<property name="interceptorNames">
            
<value>performanceThresholdInterceptor</value>
        
</property>
    
</bean>
</beans>
更强大的自动代理创建器是DefaultAdvisorAutoProxyCreator.当ApplicationContext读入所有Bean的配置信息后,DefaultAdvisorAutoProxyCreator将扫描上下文,寻找所有的Advisor.它将这些Advisor应用到所有符合Advisor切入点的Bean中。
<?xml version="1.0" encoding="UTF-8"?>
<beans
    
xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    
<bean id="performanceThresholdInterceptor" class="com.wyq.spring.common.aopinstance.autoproxy.PerformanceThresholdInterceptor">
        
<constructor-arg>
            
<value>5000</value>
        
</constructor-arg>
    
</bean>
    
<!-- 
        一个Advisor是一个切入点和一个通知的结合体。不用显示的将Advisor与其他东西结合,现在只要简单的定义他们,然后让他们自动
        应用到他们匹配的地方。这样松耦合Bean以及他们的通知就实现了。你只管写好你的Bean,写好你的通知,让容器来充当媒婆。
     
-->
    
<bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        
<property name="advice">
            
<bean class="com.wyq.spring.common.aopinstance.autoproxy.PerformanceThresholdInterceptor"></bean>
        
</property>
        
<property name="pattern">
            
<value>.+Service\..+</value>
        
</property>
    
</bean>
    
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
    
</bean>
</beans>

posted @ 2009-11-06 16:00 王永庆 阅读(252) | 评论 (0)编辑 收藏
引入与其他类型的通知不同,引入影响的是整个类。他们通过给需要消息的类添加方法和属性来实现。引入让你能够动态地建立复合对象,提供了多态继承的好处。
Spring通过一个特殊的方法拦截器接口IntroductionMethodInterceptor来实现引入。这个接口添加一个方法:
boolean implementsInterface(Class intf);
如果IntroductionMethodInterceptor是为了实现指定接口,那么方法implementsInterface应该返回true.就是说,调用这个接口声明的方法的任何调用将被委派给IntroductionMethodInterceptor的invoke()方法.invoke()方法负责实现这个方法,不能调用MethodInvocation.proceed().他引入了新的接口,调用目标对象是没有用的。

Spring提供了一个方便的类来处理我们的大多数应用:DelegatingintroductionInterceptor.代码:
package com.wyq.spring.base.aopinstance;

import java.util.Date;

/** 
 * 
@author 作者 
 * 
@version 创建时间:2009-11-6 下午02:58:21 
 * 类说明 
 
*/
public interface Auditable {
    
void setLastModifiedDate(Date date);
    Date getLastModifiedDate();
}

package com.wyq.spring.base.aopinstance;

import java.util.Date;

import org.springframework.aop.support.DelegatingIntroductionInterceptor;

/** 
 * 
@author 作者 
 * 
@version 创建时间:2009-11-6 下午03:00:06 
 * 类说明 
 
*/
public class AuditableMixin extends DelegatingIntroductionInterceptor implements
        Auditable {
    
private Date lastModifiedDate;
    
/*
     * 注意我们不用实现invoke()方法了,DelegatingIntroductionInterceptor为我们实现了这
     * 个方法。DelegatingIntroductionInterceptor也要实现你的混合类暴露的任何方法,并且将
     * 任何对这些方法的调用委托给这个混合类。因为我们的类实现了Auditable,对这个接口的方法的
     * 所有调用都将调用我们的拦截器。任何其他方法将委托给目标对象。
     
*/
    
public Date getLastModifiedDate() {
        
return lastModifiedDate;
    }

    
public void setLastModifiedDate(Date lastModifiedDate) {
        
this.lastModifiedDate = lastModifiedDate;
    }

}

创建一个引入Advisor:
因为引入通知只应用在类层次上,所以引入有他们自己的Advisor:IntroductionAdvisor.Spring也提供了一个适合大多数情况的缺省实现。它的名字叫做DefaultIntroductionAdvisor.
BeanFactory对象是一个负责创建其他JavaBean的JavaBean.我们的ProxyFactoryBean创建代理对象。和其他JavaBean一样,它有控制行为的属性。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    
<!-- 创建一个目标对象 -->
    
<bean id="courseTarget" class="com.springinaction.training.model.Course"></bean>
    
<!-- 创建一个引入 -->
    
<bean id="auditableMixin" class="com.springinaction.training.advice.AuditableMixin"></bean>
    
<!-- 创建一个引入通知 -->
    
<bean id="auditableAdvisor" class="org.springframework.aop.support.DefaultIntroductionAdvisor">
        
<constructor-arg>
            
<ref bean="auditableMixin"/>
        
</constructor-arg>
    
</bean>
    
<!-- 创建一个代理
        
ProxyFactoryBean的属性
         target:代理的目标对象
         proxyinterfaces:代理应该实现的接口列表
         interceptorNames:需要应用到目标对象上的通知Bean的名字,可以是拦截器、Advisor或者其他通知类型的名字。
         singleton:在每次抵用getBean时,工厂是否返回的是同一个代理实例。如果是有状态通知,应该设置为false.
         aopProxyFactory:通常不需要使用这个属性。
         ProxyTargetClass:是否代理目标类,而不是接口类。
      -->
    
<bean id="course" class="org.springframework.aop.framework.ProxyFactoryBean">
        
<property name="proxyTargetClass">
            
<value>true</value>
        
</property>
        
<property name="singleton">
            
<value>false</value>
        
</property>
        
<property name="proxyInterfaces">
            
<value>com.springinaction.training.advice.Auditable</value>
        
</property>
        
<property name="interceptorNames">
            
<ref bean="auditableAdvisor"/>
        
</property>
        
<property name="target">
            
<ref bean="courseTarget"/>
        
</property>
    
</bean>
</beans>

posted @ 2009-11-06 15:35 王永庆 阅读(160) | 评论 (0)编辑 收藏
仅列出标题
共7页: 上一页 1 2 3 4 5 6 7 下一页 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(1)

随笔分类

随笔档案

关注blogs

搜索

  •  

最新评论

阅读排行榜

评论排行榜