Spring HttpInvoker入门 (1)

Spring HTTP Invoker简介

Hessian和Burlap都是基于HTTP的,他们都解决了RMI所头疼的防火墙渗透问题。但当传递过来的RPC消息中包含序列化对象时,RMI就完胜Hessian和Burlap了。 因为Hessian和Burlap都是采用了私有的序列化机制,而RMI使用的是Java本身的序列化机制。如果数据模型非常复杂,那么Hessian/Burlap的序列化模型可能就无法胜任了。 Spring开发团队意识到RMI服务和基于HTTP的服务之前的空白,Spring的HttpInvoker应运而生。 Spring的HttpInvoker,它基于HTTP之上提供RPC,同时又使用了Java的对象序列化机制。

使用HTTP 协议进行remoting.由于传统的RMI方式存在协议可能被拦截等问题,spring增加了http方式的remoting,也就是说使用HTTP协议取代了JRMP协议。这种方式有优点为只要防火墙允许HTTP协议即可运行。其他方面依旧使用Java平台默认的序列化方法序处理对象。由于使用了HTTP协议,服务器端需要运行在web服务器中,同时核心类HttpInvokerServiceExporterHttpInvokerProxyFactoryBean也被放在spring-web这个jar中.

Spring HTTP invoker 是 spring 框架中的一个远程调用模型,执行基于 HTTP 的远程调用(意味着可以通过防火墙),并使用 java 的序列化机制在网络间传递对象。这需要在远端和本地都使用Spring才行。客户端可以很轻松的像调用本地对象一样调用远程服务器上的对象,这有点类似于 ‍webservice ‍,但又不同于 ‍webservice ‍,区别如下:‍

WebServiceHttp Invoker
跨平台,跨语言只支持 java 语言
支持 SOAP ,提供 wsdl不支持
结构庞大,依赖特定的 webservice 实现,如 xfire等结构简单,只依赖于 spring 框架本身

配置服务器端

创建实现Serializable接口的bean

package com.iframe.springmvc.bean;

import java.io.Serializable;
import java.util.Date;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

@Component
public class User implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int Cd;
	private String username;
	private String password;
	private Date birthday;
	private String address;
	public User(){
		
	}
	public User(int cd, String username, String password, Date birthday, String address) {
		super();
		Cd = cd;
		this.username = username;
		this.password = password;
		this.birthday = birthday;
		this.address = address;
	}
	
	public int getCd() {
		return Cd;
	}
	public void setCd(int cd) {
		Cd = cd;
	}
	
	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 Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
	@Override
	public String toString() {
		return "User [Cd=" + Cd + ", username=" + username + ", password=" + password + ", birthday=" + birthday
				+ ", address=" + address + "]";
	}
	
	
}
创建接口及其实现类

UserService
package com.iframe.springmvc.service;

import java.util.Map;
import com.iframe.springmvc.bean.User;

public interface UserService {
	//通过id查询用户信息
	public User searchUserById(int id) throws Exception;
	
	//检查用户是否存在
	public int checkUser(User user) throws Exception;
	
	//检查用户是否存在
	public int checkUser2(int id,String password) throws Exception;
	
	public int updateUser(Map<String,Object> map);
}
UserServiceImpl


package com.iframe.springmvc.service.impl;

import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import com.iframe.springmvc.bean.User;
import com.iframe.springmvc.mapper.UserMapper;
import com.iframe.springmvc.service.UserService;
@Service("userService")
public class UserServiceImpl implements UserService {
	
	private UserMapper userMapper;
	public User searchUserById(int id) throws Exception {
		return userMapper.findUserById(id);
		
	}
	public int checkUser(User user) throws Exception {
		return userMapper.checkUser(user);
	}
	
	public int checkUser2(int id, String password) throws Exception {
		return userMapper.checkUser2(id,password);
	}
	
	public int updateUser(Map<String, Object> map) {	
		return userMapper.updateUser(map);
	}
	
	public UserMapper getUserMapper() {
		return userMapper;
	}
	
	@Resource(name="userMapper")
	//@Resource(type=UserMapper.class)
	public void setUserMapper(UserMapper userMapper) {
		this.userMapper = userMapper;
	}
	
	
	

}

UserMapper 

使用mybatis 


package com.iframe.springmvc.mapper;


import java.util.Map;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.iframe.springmvc.bean.User;




@Mapper
public interface UserMapper {
	
	//通过id 查询用户信息
	public User findUserById(int id) throws Exception;
	
	//检查用户是否存在 方式一
	public int checkUser(User user) throws Exception;
	
	//检查用户是否存在 方式二  @Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值
	public int checkUser2(@Param("ids") int id,@Param("password") String password) throws Exception;
	
	
	//向用户表中插入信息 ()
	public int updateUser(Map<String,Object> map);
	
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace接口全名 -->
<mapper namespace="com.iframe.springmvc.mapper.UserMapper">
<!-- 
<cache
        eviction="FIFO"
        flushInterval="60000"
        size="512"
        readOnly="true" />
 -->
<select id="findUserById" parameterType="int" resultType="com.iframe.springmvc.bean.User">
	SELECT  
	id as Cd,
	username as username,
	password as passwrod,
	birthday as birthday,
	address as address 
	FROM USER where id = #{cd}
</select>

<select id="checkUser" parameterType="com.iframe.springmvc.bean.User" resultType="int">
	SELECT COUNT(*) FROM USER where id= #{cd} AND password=#{password}
</select>

<select id="checkUser2" parameterType="map" resultType="int">
	SELECT COUNT(*) FROM USER where id= #{ids} AND password=#{password}
</select>
<update id="updateUser" parameterType="map">
	update user set 
	username=#{username,jdbcType=VARCHAR}
	where id=#{id,jdbcType=INTEGER}
</update>
</mapper>
公开服务 使用springmvc配置

dispatcher-server.xml

  <!--httpInvoker 服务器端设置  使用springmvc URL映射配置  -->
		<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	        <property name="mappings">
	            <props>
	                <prop key="/userService">userHttpInvokerService</prop>
	            </props>
	        </property>
   		</bean>
		<!-- Announce that this interface is a HTTP invoker service. 宣布该接口是一个http invoker 服务-->
		<bean name="userHttpInvokerService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
			 <property name="service" ref="userService"/>
        	 <property name="serviceInterface" value="com.iframe.springmvc.service.UserService"/>
		</bean>


org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean

org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter 原属于 spring-remoting 现整合到spring-web


配置客户端


访问服务配置 server-invoker.xml

   

<bean id="userServiceProxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">  
	     	<property name="serviceUrl">  
	           <value>http://localhost:8080/HttpInvoke/userService</value>  
	        </property>
	        <!-- Server端与Client端的DTO的包名不同导致反序列化失败。 接口名字和bean名字保持一致 -->
	        <!-- 如果包名或者字段名不同,则会被认为是不同的对象,会反序列化失败,调用也就出错了 -->  
	        <property name="serviceInterface">  
	            <value>com.iframe.springmvc.service.UserService</value>  
	        </property>
   		</bean>
注意

1.客户端配置bean 接口 及其实现类并保证和服务器端同名同包。不然会因为客户端反序列化失败(报ClassCastException异常)。Bean对象需要实现Serializable接口。

2.如果serialVersionUID是指定生成,需要保持客户端和服务端的UID保持一致

原因 :

Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException

参考博文:

关于serialVersionUID的说明
























  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值