发表于: 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
<!-- 使用RmiServiceExporter将RMIServiceImpl的对象导出为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方法。任务八深度思考。任务八小结。
评论