发表于: 2018-01-30 22:49:23
1 578
今天完成的事情:(一定要写非常细致的内容,比如说学会了盒子模型,了解了Margin)
尝试了一天的本地客户端连接服务器远程都失败.
首先我在使用spring修改远程服务器连接的时候出现一个问题,因为是作为远程连接,我首先想到就是用服务器的公网IP暴漏出RMI的接口,所以需要修改Host,但是spring 集成的RMI在修改registryHost这条属性的时候整个项目就会报错,后来经过一番查询才了解到这个属性不是你想用就用.
就是这条属性, 我们如果不做修改,默认是使用127.0.0.1创建注册表并开启端口,修改之后就是根据我们的实际IP地址(公网)进行注册.
但是我们看一下源码:
/**
* Locate or create the RMI registry for this exporter.
* @param registryHost the registry host to use (if this is specified,
* no implicit creation of a RMI registry will happen)
* @param registryPort the registry port to use
* @param clientSocketFactory the RMI client socket factory for the registry (if any)
* @param serverSocketFactory the RMI server socket factory for the registry (if any)
* @return the RMI registry
* @throws RemoteException if the registry couldn't be located or created
*/
protected Registry getRegistry(String registryHost, int registryPort,
RMIClientSocketFactory clientSocketFactory, RMIServerSocketFactory serverSocketFactory)
throws RemoteException {
if (registryHost != null) {
// Host explicitly specified: only lookup possible.
if (logger.isInfoEnabled()) {
logger.info("Looking for RMI registry at port '" + registryPort + "' of host [" + registryHost + "]");
}
Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory);
testRegistry(reg);
return reg;
}
else {
return getRegistry(registryPort, clientSocketFactory, serverSocketFactory);
}
}
因为RmiServiceExporter提供了多个重载的getRegistry方法,只要我们设置了registryHost属性就会使用这个方法,可以看到,当我们的registryHost不为空的时候会去调用这个方法来获取一个Registry
public static Registry getRegistry(String host, int port,
RMIClientSocketFactory csf)
throws RemoteException
{
Registry registry = null;
if (port <= 0)
port = Registry.REGISTRY_PORT;
if (host == null || host.length() == 0) {
// If host is blank (as returned by "file:" URL in 1.0.2 used in
// java.rmi.Naming), try to convert to real local host name so
// that the RegistryImpl's checkAccess will not fail.
try {
host = java.net.InetAddress.getLocalHost().getHostAddress();
} catch (Exception e) {
// If that failed, at least try "" (localhost) anyway...
host = "";
}
}
/*
* Create a proxy for the registry with the given host, port, and
* client socket factory. If the supplied client socket factory is
* null, then the ref type is a UnicastRef, otherwise the ref type
* is a UnicastRef2. If the property
* java.rmi.server.ignoreStubClasses is true, then the proxy
* returned is an instance of a dynamic proxy class that implements
* the Registry interface; otherwise the proxy returned is an
* instance of the pregenerated stub class for RegistryImpl.
**/
LiveRef liveRef =
new LiveRef(new ObjID(ObjID.REGISTRY_ID),
new TCPEndpoint(host, port, csf, null),
false);
RemoteRef ref =
(csf == null) ? new UnicastRef(liveRef) : new UnicastRef2(liveRef);
return (Registry) Util.createProxy(RegistryImpl.class, ref, false);
}
这大致的意思的去获取一个已经建立好了的server端口,但是我们这个时候我们并没有建立,所以解决方案就是继承这个RmiServiceExporter类并重写他的getRegistry方法.
这是我重写了的:
package com.rmi;
import org.springframework.remoting.rmi.RmiServiceExporter;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
/**
* @author Arike
* Create_at 2018/1/30 17:55
*/
public class MyRmi extends RmiServiceExporter {
@Override
protected Registry getRegistry(String registryHost, int registryPort, RMIClientSocketFactory clientSocketFactory, RMIServerSocketFactory serverSocketFactory) throws RemoteException {
if (registryHost != null) {
// Host explictly specified: only lookup possible.
if (logger.isInfoEnabled()) {
logger.info("Looking for RMI registry at port '" + registryPort + "' of host [" + registryHost + "]");
}
try {
//把spring源代码中这里try起来,报异常就创建一个以设置好的端口建立的注册表连接
Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory);
testRegistry(reg);
return reg;
} catch (RemoteException ex) {
LocateRegistry.createRegistry(registryPort);
Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory);
testRegistry(reg);
return reg;
}
} else {
return getRegistry(registryPort, clientSocketFactory, serverSocketFactory);
}
}
}
主要思路就把找不到server那个异常try起来,找不到就自己建立一个.
然后把自己的这个类配置到spring里面.
<!--将一个类发布为一个RMI服务 -->
<bean id="myRmi" class="com.rmi.MyRmi">
<property name="serviceName" value="RMI"/>
<property name="service" ref="serviceImpl"/>
<property name="serviceInterface" value="com.service.IService"/>
<property name="registryPort" value="1099"/>
<property name="registryHost" value="192.168.31.213"/>
</bean>
现在再使用registryHost属性就不会出错了.
但是我在使用服务器IP的时候出现了问题,我没法定位到服务器的真实IP,使用公网IP也好,给的私有IP也就是阿里一个交换机内的内网IP,也不行, 只能使用127.0.0.1才能发布服务.(明天再研究一下使用监听器修改全局默认IP的方法).
反正一整天我尝试了很多方案,总感觉方案没多大问题,问题主要就在ip上,等过两天我回家直接插网线看一下能否用公网IP抛出注册表端口.
今天打算先把任务交了,继续任务9,赶紧做完申请进入复盘.(知识学不完,先完成任务了.)
...........
哇,本来打算今天交任务的,结果,发现任务要求我有点懵,就是一台web随机访问两台Server,这个和之前他们做的不一样啊,他们都是一台web对应一台server....
去翻了一下北京的几个师兄的过往日报,发现他们也没有做随机访问, 只是做了挂了一台而去另外一台,我打算好好做做,另外关于服务器远程的方法,还真的用监听器,恩,监听器好好研究一波.
明天计划的事情:(一定要写非常细致的内容)
完成一台web随机访问2台Server
并完成远程访问服务器.
遇到的问题:(遇到什么困难,怎么解决的)
有一个很弱智的问题我要提一提.
就是关于client和server,两边的接口权限定名一定要一样,一样,一样
我在两台电脑局域网连接的时候使用了七八种方式都连接不上....原来就是我的包名不同..顺便贴一下昨天上午做的局域网内跨服操作...
服务端
package rmi.run;
import rmi.imp.RmiTestImpl;
import rmi.in.RmiTest;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
/**
* @author Arike
* Create_at 2018/1/29 16:38
*/
public class Start2 {
public static void main(String[] args) {
RmiTest rmi = null;
Registry registry =null;
try{
rmi = new RmiTestImpl();
registry = LocateRegistry.createRegistry(1099);
Naming.rebind("rmi://localhost:1099/rmi",rmi);
System.out.println("RMI服务已启动");
}catch(Exception e){
e.printStackTrace();
}
}
}
客户端:
package rmi.client;
import rmi.in.RmiTest;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
/**
* @author Arike
* Create_at 2018/1/29 15:35
*/
public class Start {
public static void main(String[] args) {
try {
RmiTest rmi = (RmiTest) Naming.lookup("rmi://192.168.31.213:1099/rmi");
System.out.println(rmi.getNum());
} catch (NotBoundException | MalformedURLException | RemoteException e) {
e.printStackTrace();
}
}
}
收获:(通过今天的学习,学到了什么知识)
spring提供的服务也不是并不可变的.如果有自己的需求可以选择几种方式:
第一种,继承类或者实现接口,然后将自己配置的功能类进行配置.
第二种,修改监听器,恩,监听器很重要.
评论