Restlet实战(三)使用Component让不同的Application对应不同的资源

Restlet实战(二)我给出的例子中,把Order和Customer两个资源attach到Order Application上,看如下代码:

 

public class OrderApplication extends Application {   
   
    @Override  
    public synchronized Restlet createRoot() {   
        Router router = new Router(getContext());   
  
        router.attach("/order/{orderId}/{subOrderId}", OrderResource.class);   
        router.attach("/customer/{custId}", CustomerResource.class);   
        return router;   
    }   
  
}  

 

 

这显而易见不是一个好的应用,从关注点来看,Order Resource应该attach到Order Application,那么对应Customer Resource应该有一个Customer Application与之对应。

 

ok,基于这样的思路,我们从OrderApplication删除如下代码:

router.attach("/customer/{custId}", CustomerResource.class);   

 

另外我们创建一个CustomerApplication,并包含上述代码:

public class CustomerApplication extends Application{
	@Override
	public synchronized Restlet createRoot() {
		Router router = new Router(getContext());
		
		router.attach("/customers/{custId}", CustomerResource.class);
		return router;
	}
}

 

 有了CustomerApplication,那么如何设置才能生效呢?根据之前的配制,很容易想到的是在web.xml中把CustomerApplication配制进去,事实上是不行的,看看ServerServlet类里面这段代码:

private static final String APPLICATION_KEY = "org.restlet.application";   

 protected Application createApplication(Context parentContext) {
        Application application = null;

        final String applicationClassName = getInitParameter(APPLICATION_KEY,
                null);

 

这段代码是根据参数名org.restlet.application来获得配制在web.xml中application,而之前我们已经配制了OrderApplication,所以,我们不能再把CustomerApplication配制的参数名设置为org.restlet.application。那么在ServerServlet加载application的时候,就加载不到。

 

那么怎么作能让这两个Application生效呢?答案是Component,实际上,从上一篇文章中的图可以看出,一个Component可以设置多个Virtual Host,而一个Virtual Host能attach多个Application。

 

至于使用Component的做法有两种,一种是在web.xml中配制一个名字为“org.restlet.component”的context参数,例如:

<context-param>
                 <param-name>org.restlet.component</param-name>
                 <param-value>com.mycompany.MyComponent</param-value>
         </context-param>

 

另外一种是,WEB-INF/下存在restlet.xml,可以在这个xml文件里定义包含application和connector的Commponent。

 

下面就第二种方式来解决上面出现的问题,首先在WEB-INF/下建立一个名为restlet.xml,这个名字不能改变成别的名字,为啥呢?仍然看一下ServerServlet里面的一段代码:

    protected Component createComponent() {
        Component component = null;

        // Look for the Component XML configuration file.
        Client client = createWarClient(new Context(), getServletConfig());
        Response response = client.get("war:///WEB-INF/restlet.xml");

 

既然不让改,不改好了,在restlet.xml里面放入配制Component的代码:

<?xml version="1.0"?>
 <component xmlns="http://www.restlet.org/schemas/1.1/Component"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.restlet.org/schemas/1.1/Component">
    <!-- 
    <client protocol="CLAP" />
    <client protocol="FILE" />
    <client protocols="HTTP HTTPS" />
    <server protocols="HTTP HTTPS" port="8080"/>
     -->
     
    <defaultHost>
       <attach uriPattern="/customers/{custId}" 
                  targetClass="com.mycompany.restlet.application.CustomerApplication" />
       <attach uriPattern="/orders/{orderId}/{subOrderId}" 
                  targetClass="com.mycompany.restlet.application.OrderApplication" />           
       <!-- <attach uriPattern="/efgh/{xyz}" targetDescriptor="clap://class/org/restlet/test/MyApplication.wadl" /> -->
    </defaultHost>
 </component>

 

看上面的配制文件,很清楚的我们能知道,如果在浏览器输入http://localhost:8080/restlet/customers/1,那么CustomerApplication这个类应该被访问到。

 

咦,好象有点不对,好像CustomerApplication里面在attach资源的时候,也指定了同样的URL(/customers/{custId}),那么是当前这两个URL定义的URL重复了?还是有别的含义?

 

我们可以这样理解,在restlet.xml中定义的URL附加到Context上,而在application里面定义的URL会附加到restlet.xml中定义的URL上。

 

例如,如果想通过http://localhost:8080/restlet/customers/1 来使用CustomerResource,则需要在CustomerApplication中有如下代码:

router.attach("", CustomerResource.class);

 而如果想通过http://localhost:8080/restlet/customers/1/orders/2 来使用CustomerResource,则需要在CustomerApplication中定义如下代码:

 

router.attach("/orders/{orderId}", CustomerResource.class);

 

Ok,让我们测试一下,首先修改

CustomerApplication.java

 

public class CustomerApplication extends Application{
	@Override
	public synchronized Restlet createRoot() {
		Router router = new Router(getContext());
		
		//router.attach("", CustomerResource.class);
		router.attach("/orders/{orderId}", CustomerResource.class);
		return router;
	}
}

 

CustomerResource.java

 

public class CustomerResource extends Resource {
	String customerId;
	String orderId;

	public CustomerResource(Context context, Request request, Response response) {
		super(context, request, response);
		customerId = (String) request.getAttributes().get("custId");
		orderId = (String) request.getAttributes().get("orderId");
		// This representation has only one type of representation.
		getVariants().add(new Variant(MediaType.TEXT_PLAIN));
	}

	@Override
	public Representation getRepresentation(Variant variant) {
		Representation representation = new StringRepresentation(
				"The customer which id is " + customerId
						+ " has the order which id  : " + orderId,
				MediaType.TEXT_PLAIN);
		return representation;
	}
}

 

 输入http://localhost:8080/restlet/customers/1/orders/2,结果如下:

 

The customer which id is 1 has the order which id  : 2

 

请注意,上面CustomerApplicaiton被注释的一行代码

router.attach("", CustomerResource.class);

如果反注释这行代码,则所有基于http://localhost:8080/restlet/customers/1/****(除了/customers/{custId}/orders/{orderId} )的访问都会路由到同一个资源(CustomerResource),换句话说,如果我访问一个我没有定义的URL,如/customers/{customerId}/orders,则也会被路由到CustomerResource,这是不对的。。所以,应慎用之。

 

总结,现在我们可以分别用不同的Application来管理不同的资源了,并采用restlet.xml这种方式来定义包含applicaiton和connector的component.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值