发表于: 2021-10-24 20:17:57

1 906


一,今天完成的事情

任务八。保证controller能和远端出来的service协作。能运行。其实就是整个项目正常运行


1,分解后web.xml修改。

我昨天给出了我client.xml的配置。里面有两行是我能把controller以及以上拆开的原因之一。

<context:annotation-config/>
<context:component-scan base-package="com.nicole" />


这样就能在我的client\src\main\webapp\WEB-INF\web.xml修改成如下。

  <!-- @Autowired 自动注入注解的spring容器加载文件路径 -->
 <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:client.xml</param-value>
 </context-param>

 <!--IOC container should read xml files-->
<!--  <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:spring-mybatis.xml</param-value>
 </context-param>-->


黄色的部分是新的,被注解的部分是原来的。关键就是理解

<context-param>

这个必要的部分是需要写什么。我已经把service以下拆出去了,如果用网络传过来就不能再用classpath:spring-mybatis.xml文件了。

格式定义:

<context-param> 

<param-name>contextConfigLocation</param-name> 

<param-value>contextConfigLocationValue></param-value> 

</context-param>

作用:该元素用来声明应用范围(整个WEB项目)内的上下文初始化参数。

param-name 设定上下文的参数名称。必须是唯一名称

param-value 设定的参数名称的值

base-package="com.nicole"是我的上下文,在这个项目肯定没错。


2,controller能和远端传递来的一个service协作。

我有一个类。写成一个工具。

@Component
public class RMIServiceUtil {
private Logger logger = LoggerFactory.getLogger(this.getClass());
   private UserService userService;

   public UserService getUserServiceRandom(){
return getUserService("UserServiceOne");
   }

private UserService getUserService( String serviceName){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(
"client.xml");
       return (UserService) applicationContext.getBean(serviceName);
   }

}


负责给controller提供service。我现在只保证给出一个正确的serviceone,但是先写好骨架。一个方法是按照bean的名称得到service。另外就是带Random的,完成任务八要求随机得到一个service。现在我先写死,看看controller是否有问题。


@Autowired
RMIServiceUtil rmiServiceUtil;

private UserService userService;

每次使用service的时候都是从方法里random,这样应该平均。


我先运行

public class StartServer

注意把除了client的包,我都给成jar包。我的有3个模块都是jar包。

<groupId>org.example</groupId>
<artifactId>serviceone</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>


而client模块我是war包。

<groupId>org.example</groupId>
<artifactId>client</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

本地edit configuration 这个war到tomcat

先启动

public class StartServer {
public static final Logger logger = LoggerFactory.getLogger(StartServer.class);

   public static void main(String[] args)


再启动部署好client的war的tomcat。这样目前同时运行2个。

首先测试邮件注册,成功。


测试登录新注册的用户成功。


3,写servicetwo。在client.xml加入servicetwo代码。在client测试servicetwo能成功拿到。

复制serverone的代码到servertwo

稍微修改

server.xml

<!-- 使用RmiServiceExporterRMIServiceImpl的对象导出为RMI服务对象 -->
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
  <!--服务的接口类型-->
  <property name="serviceInterface" value="com.nicole.service.UserService"/>
  <!--对外的名称,即客户端访问时用这个名字找到这个服务-->
  <property name="serviceName" value="servicetwo"/>
  <!--服务占用的端口-->
  <property name="registryPort" value="7020"/>
  <!--<property name="servicePort" value="7010"/>-->
  <!--要发布成服务的类-->
  <property name="service" ref="UserServiceImpl"/>
</bean>


client的client.xml加入

<bean name="UserServiceTwo" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"
     lazy-init="true">
   <!-- 根据服务端的serviceName(服务名)和registryPort(端口)组成的访问地址 -->
   <property name="serviceUrl" value="rmi://127.0.0.1:7020/servicetwo"></property>
   <property name="serviceInterface" value="com.nicole.service.UserService"></property>
   <!-- 预查找远程对象 默认为true -->
   <property name="lookupStubOnStartup" value="false"/>
   <!-- 是否刷新远程调用缓存的stub -->
   <property name="refreshStubOnConnectFailure" value="true"></property>
</bean>


ApplicationContext context2 = new ClassPathXmlApplicationContext("client.xml");
UserService userService2 = (UserService) context2.getBean("UserServiceTwo");
System.out.println( userService2.selectUserName( "nicole2") );

测试刚才controller调用serverone注册的一个信息成功


4,先分别启动两个server或者说service,部分先后,然后启动client。都测试查数据。

    public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("client.xml");
       UserService userService = (UserService) context.getBean("UserServiceOne");
       System.out.println( userService.selectUserName( "nicole") );
       UserService userService2 = (UserService) context.getBean("UserServiceTwo");
       System.out.println( userService2.selectUserName( "nicole2") );
   }

启动两个服务器

两个服务器都能正常运行

Redis也涉及序列化和反序列化,至少测试2次能正常访问数据,目前我的逻辑是数据在数据库中。


5,完善方法。

public UserService getUserServiceRandom()

随机,应该是同等概率拿到serviceone servicetwo其中一个,Logger记录好。

Logger记录使用哪个service等情况。

我被问过获得同样概率的随机算法。下面的被证明是比较好的部分处理方式。

private static long seedUniquifier() {
// L'Ecuyer, "Tables of Linear Congruential Generators of
   // Different Sizes and Good Lattice Structure", 1999
   for (;;) {
long current = seedUniquifier.get();
       long next = current * 181783497276652981L;
       if (seedUniquifier.compareAndSet(current, next))
return next;
   }
}


平均可能性选service one和service two,返回相应的service。


6,controller测试包含随机同样概率两个service正常使用。

如果有超过一个service的代码,如果controller或者以上要调用service的地方,都要处理好使用哪一个。不能

@Autowired

运行,多试几次登录。


注册,email注册,手机号注册。再登录。

上传,全部在任务七中需要完成的任务都正常。


本地测试全部完成


二,今天问题

我今天仔细一看我的项目名,居然有typo,居然能打错register这个单词。赶紧refractor,也改了文件夹名,把文件夹放到了平时我应该放这个项目的地方。


三,今天的收获

RPC有用过。RMI设计得好,用起来很简单,和本地调用差别小。


四,明天的计划

任务八。整理代码。部署到云Linux上,用命令行启动服务器,所以启动的是main方法。任务八深度思考。任务八小结。



返回列表 返回列表
评论

    分享到