dubbo源码解析(三⼗)远程调⽤——rest协议
远程调⽤——rest协议
⽬标:介绍rest协议的设计和实现,介绍dubbo-rpc-rest的源码。
前⾔
REST的英⽂名是RepresentationalState Transfer,它是⼀种开发风格,关于REST不清楚的朋友可以了解⼀下。在dubbo中利⽤的是红帽⼦RedHat公司的Resteasy来使dubbo⽀持REST风格的开发使⽤。在本⽂中主要讲解的是基于Resteasy来实现rest协议的实现。
源码分析
(⼀)RestServer
该接⼝是rest协议的服务器接⼝。定义了服务器相关的⽅法。
public interface RestServer {
/**
* 服务器启动
* @param url
*/
void start(URL url);
/**
* 部署服务器
* @param resourceDef it could be either resource interface or resource impl
*/
void deploy(Class resourceDef, Object resourceInstance, String contextPath);
/**
* 取消服务器部署
* @param resourceDef
*/
void undeploy(Class resourceDef);
/**
* 停⽌服务器
*/
void stop();
}
(⼆)BaseRestServer
该类实现了RestServer接⼝,是rest服务的抽象类,把getDeployment和doStart⽅法进⾏抽象,让⼦类专注于中这两个⽅法的实现。1.start
@Override
public void start(URL url) {
// ⽀持两种 Content-Type
getDeployment().getMediaTypeMappings().put("json", "application/json");
getDeployment().getMediaTypeMappings().put("xml", "text/xml");
// Deployment().getMediaTypeMappings().put("xml", "application/xml");
// 添加
getDeployment().getProviderClasses().add(Name());
// TODO users can override this mapper, but we just rely on the current priority strategy of resteasy
// 异常类映射
getDeployment().getProviderClasses().add(Name());
// 添加需要加载的类
Parameter(Constants.EXTENSION_KEY, ""));
// 开启服务器
doStart(url);
}
2.deploy
@Override
public void deploy(Class resourceDef, Object resourceInstance, String contextPath) {
// 如果
if (StringUtils.isEmpty(contextPath)) {
// 添加⾃定义资源实现端点,部署服务器
getDeployment().getRegistry().addResourceFactory(new DubboResourceFactory(resourceInstance, resourceDef));
} else {
// 添加⾃定义资源实现端点。指定contextPath
getDeployment().getRegistry().addResourceFactory(new DubboResourceFactory(resourceInstance, resourceDef), contextPath);
}
}
3.undeploy
@Override
public void undeploy(Class resourceDef) {
// 取消服务器部署
getDeployment().getRegistry().removeRegistrations(resourceDef);
}
4.loadProviders
protected void loadProviders(String value) {
for (String clazz : Constants.COMMA_SPLIT_PATTERN.split(value)) {
if (!StringUtils.isEmpty(clazz)) {
getDeployment().getProviderClasses().im());
}
}
}
该⽅法是把类都加⼊到ResteasyDeployment的providerClasses中,加⼊各类组件。
(三)DubboHttpServer
该类继承了BaseRestServer,实现了doStart和getDeployment⽅法,当配置选择servlet、jetty或者tomcat作为远程通信的实现时,实现的服务器类
1.属性
/**
* HttpServletDispatcher实例
*/
private final HttpServletDispatcher dispatcher = new HttpServletDispatcher();
/**
* Resteasy的服务部署器
*/
private final ResteasyDeployment deployment = new ResteasyDeployment();
/**
* http绑定者
*/
private HttpBinder httpBinder;
/**
* http服务器
*/
private HttpServer httpServer;
2.doStart
@Override
protected void doStart(URL url) {
// TODO jetty will by default enable keepAlive so the xml config has no effect now
// 创建http服务器
httpServer = httpBinder.bind(url, new RestHandler());
// 获得ServletContext
ServletContext servletContext = Instance().Port());
// 如果为空,则获得默认端⼝对应的ServletContext对象
if (servletContext == null) {
servletContext = Instance().getServletContext(ServletManager.EXTERNAL_SERVER_PORT); }
// 如果还是为空,则抛出异常
if (servletContext == null) {
throw new RpcException("No servlet context found. If you are using server='servlet', " +
"make sure that you've configured " + Name() + " l");
}
// 设置属性部署器
servletContext.setAttribute(Name(), deployment);
try {
// 初始化
dispatcher.init(new SimpleServletConfig(servletContext));
} catch (ServletException e) {
throw new RpcException(e);
}
}
3.RestHandler
private class RestHandler implements HttpHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 设置远程地址
// 请求相关的服务
dispatcher.service(request, response);
}
}
该内部类是服务请求的处理器
4.SimpleServletConfig
private static class SimpleServletConfig implements ServletConfig {
// ServletContext对象
private final ServletContext servletContext;
public SimpleServletConfig(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Override
public String getServletName() {
return "DispatcherServlet";
}
@Override
public ServletContext getServletContext() {
return servletContext;
}
@Overridewebserver接口开发
public String getInitParameter(String s) {
return null;
}
@Override
public Enumeration getInitParameterNames() {
return new Enumeration() {
@Override
public boolean hasMoreElements() {
return false;
}
@Override
public Object nextElement() {
return null;
}
};
}
}
该内部类是配置类。
(四)NettyServer
该类继承了BaseRestServer,当配置了netty作为远程通信的实现时,实现的服务器。
public class NettyServer extends BaseRestServer {
/**
* NettyJaxrsServer对象
*/
private final NettyJaxrsServer server = new NettyJaxrsServer();
@Override
protected void doStart(URL url) {
// 获得ip
String bindIp = Parameter(Constants.BIND_IP_KEY, Host());
if (!url.isAnyHost() && NetUtils.isValidLocalHost(bindIp)) {
// 设置服务的ip
server.setHostname(bindIp);
}
// 设置端⼝
server.Parameter(Constants.BIND_PORT_KEY, Port()));
// 通道选项集合
Map<ChannelOption, Object> channelOption = new HashMap<ChannelOption, Object>();
// 保持连接检测对⽅主机是否崩溃
channelOption.put(ChannelOption.SO_KEEPALIVE, Parameter(Constants.KEEP_ALIVE_KEY, Constants.DEFAULT_KEEP_ALIVE)); // 设置配置
server.setChildChannelOptions(channelOption);
// 设置线程数,默认为200
server.Parameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS));
// 设置核⼼线程数
server.Parameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));
// 设置最⼤的请求数
server.Parameter(Constants.PAYLOAD_KEY, Constants.DEFAULT_PAYLOAD));
// 启动服务
server.start();
}
@Override
public void stop() {
server.stop();
}
@Override
protected ResteasyDeployment getDeployment() {
Deployment();
}
}
(五)DubboResourceFactory
该类实现了ResourceFactory接⼝,是资源⼯程实现类,封装了以下两个属性,实现⽐较简单。
/**
* 资源类
*/
private Object resourceInstance;
/**
* 扫描的类型
*/
private Class scannableClass;
(六)RestConstraintViolation
该类是当约束违反的实体类,封装了以下三个属性,具体使⽤可以看下⾯的介绍。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论