所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的标识符。
一个完整的资源访问路径(URI)由以下部分构成
<协议>://<主机地址>:<端口>/应用域/<资源路径>/<子资源路径>
如系统应用中获取用户详细信息的URI可表示为
http://192.169.1.10:8080/system/user/1000001
协议:常用的协议有http、https、ws
主机地址:IP地址或域名
端口:服务端口
应用域:应用中根据业务属性划定的访问范围,如/system代表系统业务域,/product代表产品业务域
资源路径:包含所有子资源的路径
子资源路径:具体的资源访问地址
Jersey中应用域在服务器的启动类中,通过ServletContextHandler提供的setContextPath
方法指定。
ServletContextHandler apiContext = new ServletContextHandler(
ServletContextHandler.SESSIONS);
apiContext.addServlet(sh, "/*");
//指定应用域
apiContext.setContextPath("/system");
@Path注解的源码如下,可以看到该注解可以标记在类上,也可以标记在方法上,接收一个value参数,标识资源的地址。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Path {
String value();
}
@Path使用举例
@Path("")
@WebService
public class WelcomeRes {
@Path("")
@GET
public String sayHello(@Context HttpServletRequest request) {
return "hello, jetty!";
}
}
在JAX-RS标准中,根资源类是带有@PATH 注解的类,且包含至少一个@Path 注解的方法或者方法带有 @GET、@PUT、@POST、 @DELETE 资源方法指示器的 POJO。
资源方法是带有资源方法指示器(resource method designator)注解的方法,在Jersey中,资源方法指示器即@GET、@HEAD、@PUT、@POST、 @DELETE。
@Path("")相当于@Path("/"),即使注解的value中不显示指定"/",框架会自动加上。
如以下示例中路径注解加"/"和不加,最后的访问地址都为/user
//相当于@Path("user")
@Path("/user")
public class UserRes {
//创建用户
@PUT
//相当于@Path("/")
@Path("")
public String add(String params) {
return "";
}
}
一个类被Jersey框架注册为资源的前提条件是,类必须具有@Path注解。如果没有被@Path注解修饰,访问时会产生Not Found错误。
如以下示例中,虽然方法被@Path注解修饰,但类没有被@Path修饰,不能被框架正确注册。
public class UserRes {
//创建用户
@PUT
@Path("")
public String add(String params) {
return "";
}
}
@Path默认值为空,如果是类,紧跟
应用域路径
,如果是方法,紧接着类代表的资源路径
。
如以下示例,访问时地址的地址应为http://
@Path("/user")
public class UserRes {
@GET
@Path("/100001")
public String add(String params) {
return "";
}
}
所有资源中,只能有一个类被标记为@Path("")或@Path("/"),否则在发起请求时会产生错误。
举例
@Path("/")
public class UserRes {
@GET
@Path("/100001")
public String add(String params) {
return "";
}
}
@Path("")
public class ProductRes {
@GET
@Path("/100002")
public String add(String params) {
return "";
}
}
如果有两个类同时被标记为@Path(""),则在发起HTTP访问时会产生以下错误。
org.glassfish.jersey.server.model.ModelValidationException:
Validation of the application resource model has failed during application initialization.
These two methods produces and consumes exactly the same mime-types and therefore their invocation as a resource methods will always fail.; source='org.glassfish.jersey.server.model.RuntimeResource@75ee966d']
在同一个类中,HTTP请求方法注解和资源地址注解相结合唯一确定一个资源的定位。
(1)资源地址相同,但是HTTP请求方法不同的两个方法是完全两个不同的REST接口。
(2)一个类中,@Path注解和HTTP请求方法注解的组合不能重复,否则会发生路径匹配错误,跟Java方法本省的名称无关。
以下类中,虽然方法的名称不同,但因为@Path和@Get组合冲突,故也会出错。
//错误示范
@Path("/product")
public class ProductRes {
@Path("")
@GET
public String get() {
return "";
}
@Path("")
@GET
public String getAll() {
return "";
}
}
错误如下:
org.glassfish.jersey.server.model.ModelValidationException:
Validation of the application resource model has failed during application initialization.
These two methods produces and consumes exactly the same mime-types and therefore their invocation as a resource methods will always fail.; source='org.glassfish.jersey.server.model.RuntimeResource@75ee966d']
该注解定义路径的参数信息,用于指定的URI路径参数,@PathParam 用在接收请求的方法的参数上。
@GET
@Path("/user/{username}")
public String getUser(@PathParam("username") String userName) {
return "hello," + userName;
}
@PathParam注解提供更精确的匹配方式,如要求变量只能由字母和数字构成,则可以使用表达式覆盖默认的表达式[^/]+?
如@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]*}")