Spring整合jdbc+事务+rmi

一、Spring整合jdbc

1、坐标添加



  junit
  junit
  4.12
  test



  org.springframework
  spring-context
  4.3.2.RELEASE




  org.aspectj
  aspectjweaver
  1.8.9




  mysql
  mysql-connector-java
  5.1.39



  c3p0
  c3p0
  0.9.1.2




  org.springframework
  spring-jdbc
  4.3.2.RELEASE




  org.springframework
  spring-tx
  4.3.2.RELEASE


  

2、配置文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/senior?useUnicode=true&characterEncoding=utf8
jdbc.user=root
jdbc.password=breeze

3、spring.xml配置修改



4、配置数据源

可选:C3P0,dbcp
C3P0数据源配置



    
    
    
    

5、模板类配置

Spring 把 JDBC 中重复的操作建立成了一个模板类: org.springframework.jdbc.core.JdbcTemplate ,配置文件中加入





6、创建数据库

并创建测试表 account

7、测试整合结果

通过 junit 测试 jdbcTemplate bean 是否获取到
public class SpringJdbcTest {

    private JdbcTemplate template;
    private AccountService accountService;

    @Before
    public void init(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        template = (JdbcTemplate) context.getBean("jdbcTemplate");
    }

    @Test
    public void test01(){
        String sql = "select count(*) from account";
        Integer total = template.queryForObject(sql, Integer.class);
        System.out.println("total: "+total);
    }
}

二、转账操作模拟

1、Dao层方法定义

package com.shsxt.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * Created by xlf on 2019/7/6.
 */
@Repository
public class AccountDao {

    @Autowired
    private JdbcTemplate template;

    /**
     * 出账
     * @param id
     * @param money
     */
    public void outMoney(Integer id, Double money){
        String sql = "update account set money=money-? where id=?";
        template.update(sql,money,id);
    }

    /**
     * 入账
     * @param id
     * @param money
     */
    public void inMoney(Integer id, Double money){
        String sql = "update account set money=money+? where id=?";
        template.update(sql,money,id);
    }
}

2、service层转账方法定义

package com.shsxt.service;

import com.shsxt.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by xlf on 2019/7/6.
 */
@Service
public class AccountService {

    @Autowired
    private AccountDao accountDao;

    /**
     * 转账
     * @param outId
     * @param inId
     * @param money
     */
    public void zhuanzhang(Integer outId, Integer inId, Double money){
            accountDao.outMoney(outId, money);
            accountDao.inMoney(inId, money);
    }
}

3、转账业务实现

public class SpringJdbcTest {

    private JdbcTemplate template;
    private AccountService accountService;

    @Before
    public void init(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        template = (JdbcTemplate) context.getBean("jdbcTemplate");
        accountService = (AccountService) context.getBean("accountService");
    }

    @Test
    public void zhuanzhang(){
        accountService.zhuanzhang(8,9,100.00);
    }

}

三、Spring事务

1、Spring事务核心接口

  • JDBC事务
  • Hibernate事务
  • JPA事务
  • JTA事务

2、Spring jdbc事务管理配置

方式一:XML配置

1、修改xml命名空间

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

2、Aop代理


3、配置事务管理器



    

4、配置事务相关通知




    
        
        
        
        
        
        
        
        
    

5、配置Aop



    
    

方式二:Spring事务管理注解方式

1、配置事务管理器



    

2、配置注解支持


3、Service 方法上在需要添加事务的方法上加入事物注解

@Transactional(propagation = Propagation.REQUIRED)
    public void zhuanzhang(Integer outId, Integer inId, Double money){
        try {
            accountDao.outMoney(outId, money);
            int i = 1/0;
            accountDao.inMoney(inId, money);
        } catch (Exception e) {
            e.printStackTrace();
            // 如果需要try ... catch,则必须自己手动抛出一个异常
            // 抛出的异常必须是RuntimeException
            throw new RuntimeException();
        }
    }

注:
默认 spring 事务只在发生未被捕获的 runtimeexcetpion 时才回滚。
spring aop 异常捕获原理:
被拦截的方法需显式抛出异常,并不能经任何处理, 这样 aop 代理才能捕获到方法的异常,才能进行回滚,默认情况下 aop 只捕获 runtimeexception 的异常,但可以通过配置来捕获特定的异常并回滚 换句话说 在 service 的方法中不使用 try catch 或者在 catch 中最后加上 throw new RunTimeexcetpion(),这样程序异常时才能被 aop 捕获进而回滚

四、远程方法调用RMI

Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让
在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。JVM 可以位于相
同或不同计算机上,在多个 JVM 中,一个 JVM 可以调用存储在其它 JVM 的对象的方法

RMI 是 Java 编程语言里,一种用于实现远程过程调用的应用程序编程接口,它是客户机上运行的程序可以调用远程服务器上的对象,远程方法调用特性使 Java 编程人员能够在网络环境中分布操作。RMI 全部的宗旨就是尽可能简化远程接口对象的使用。

Java RMI 极大地依赖于接口,在需要创建一个远程对象的时候,程序员通过传递一个
接口来隐藏底层的实现细节,客户端得到的远程对象句柄正好与本地的根代码连接,由后者负责透过网络通信。这样一来,程序员只需关心如何通过自己的接口句柄发送消息。

Spring 的优势除了 IOC 和 AOP 外,还提供了简易的服务抽象。如远程 rmi 调用。 远
程方法调用,即 Java RMI(java Remote Method Invocation)。 RMI 底层封装了Socket反射机制。java 语言当中 分布式的基础!!!实现java之间的互相访问。RMI 本质就是使用代理类来封装Socket的通信细节!!RMI 的 API 帮组我们创建一个代理类及其内容!!使用这个代理类实例就可以远程通信。

RMI实现常用API

1).Remote 接口:每一个要暴露出去的 java 类,都需要实现 Remote 接口,并且所有
的方法必须抛出 RemoteException
2).UnicastRemoteObject 类:服务端程序的实现方案之一就是继承这个类,无参构造器
也要抛出 RemoteException
3).LocateRegistry 类创建能在特定接口接受调用远程对象注册服务程序。

public static Registry createRegistry(int port) throws RemoteException

4).Naming 类提供了存储和获得远程对象注册服务程序中的远程对象进行引用的方法

public static Remote lookup(String name) throws
NotBoundException,MalformedURException,ReoteException
public static void bind(String name,Remote obj) throws
AlreadyBoundException,MalforedURException,RemoteException

JAVA RMI实例

1)服务器端

1、接口定义

package com.shsxt.service;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 1.接口继承 Remote
* 2.对外服务方法声明 RemoteException 异常
*
*/
public interface IHelloService extends Remote{
public String sayHello(String msg) throws RemoteException;
}

2、接口具体服务实现类

package com.shsxt.service.impl;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import com.shsxt.service.IHelloService;
/**
* 1、继承 UnicastRemoteObject
* 2、提供 无参构造 对外声明 RemoteException
*
*/
public class HelloServiceImpl extends UnicastRemoteObject implements
IHelloService {
private static final long serialVersionUID = -5672932066566630040L;
public HelloServiceImpl() throws RemoteException {
}
@Override
public String sayHello(String msg) throws RemoteException{
System.out.println("服务器端接收到消息:"+msg);
return "hello:"+msg;
}
}

3、发布服务,对外提供相应服务

package com.shsxt.test;
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import com.shsxt.service.impl.HelloServiceImpl;
public class Publish {
public static void main(String[] args) throws RemoteException,
MalformedURLException, AlreadyBoundException {
//注册端口
LocateRegistry.createRegistry(8888);
//对外发布 rmi 服务
Naming.bind("rmi://127.0.0.1:8888/hello", new
HelloServiceImpl());
}
}

2)客户端

1、客户端与服务端声明相同接口

package com.shsxt.service;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IHelloService extends Remote{
public String sayHello(String msg) throws RemoteException;
}

2、客户端查找并调用远程服务

package com.shsxt.test;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import com.shsxt.service.IHelloService;
public class Test {
public static void main(String[] args) throws
MalformedURLException, RemoteException, NotBoundException {
IHelloService helloService=(IHelloService)
Naming.lookup("rmi://127.0.0.1:8888/hello");
System.out.println(helloService.sayHello("im win10"));
}
}

Spring 实现远程方法调用

使用 spring 的RMI,提供的服务简单方便,不用继承接口和指定的类,不用抛出异常。

服务端接口声明

package com.shsxt.service;
public interface IHelloService {
public String sayHello(String msg);
}

1、接口实现

package com.shsxt.service.impl;
import org.springframework.stereotype.Service;
import com.shsxt.service.IHelloService;
@Service
public class HelloServiceImpl implements IHelloService {
@Override
public String sayHello(String msg) {
System.out.println("服务器端收到信息:"+msg);
return "hello:"+msg;
}
}

2、spring.xml配置



    
    

    
    
        
        
        
        
    

3、发布服务

package com.shsxt;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Publish {

    public static void main(String[] args) {
        /**
         * 启动spring ioc容器 ,并发布对应服务
         */
        ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
    }
}

客户端调用

1、接口声明

package com.shsxt.service;
public interface IHelloService {
public String sayHello(String msg);
}

2、xml配置




    
    

    
        
        
    

3、客户端使用远程接口方法服务

package com.shsxt.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.shsxt.service.IHelloService;

import java.rmi.RemoteException;

@Service
public class UserServiceImpl {
    @Resource
    private IHelloService helloService;

    public void test() throws RemoteException {
        System.out.println(helloService.sayHello("im win10"));
    }
}

4、客户端测试

package com.shsxt;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.shsxt.service.IHelloService;
import com.shsxt.service.impl.UserServiceImpl;

import java.rmi.RemoteException;


public class Test {

    public static void main(String[] args) throws RemoteException {
        ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
        UserServiceImpl userServiceImpl=  (UserServiceImpl) ac.getBean("userServiceImpl");
        userServiceImpl.test();

    }

}

你可能感兴趣的:(java,框架)