首页技术文章正文

+jax-rs【黑马java培训】

更新时间:2019年07月26日 11时10分57秒 来源:黑马程序员论坛

JAX-RS,全称为Java API for RESTful Web Services.的核心概念是resource,即面向资源。

JAX-RS的JavaDoc可以在这里找到。 
JAX-RS的标准可以在这里找到。

1. Root Resource Classes
满足下列2个条件的POJO类被称为Root Resource Class:

使用@Path注解
至少有一个方法使用@Path或者资源方法注解(如@GET,@DELETE)
下面的HelloworldResource就是这样一样例子:
 

import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("helloworld") // 条件1
public class HelloWorldResource {
    public static final String CLICHED_MESSAGE = "Hello World!";

    @GET // 条件2
    @Produces("text/plain")
    public String getHello() {
        return CLICHED_MESSAGE;
    }
}
1.1. @Path
@Path注解的值是一个相对的URI路径。@Path的有没有/开头是一样的,同理,结尾有没有包含/也是一样的。上面例子中的/helloworld是最简单的一个例子,但是JAX-RS允许我们在路径中嵌入各种变量。

路径模板在路径中嵌入了以{}包含的变量,这个变量在运行时(资源被请求时)替换成实际的值。例如:

@Path("/users/{username}")
参数的实际值在资源方法中使用@PathParam提取:

@Path("/users/{username}")
public class UserResource{
    @GET
    @Produces("text/xml")
    public String getUser(@PathParam("username") String username){
        ...
    }
}
我们还可以对模板参数的格式做约束,例如我们只允许大小写字符以及数字,则可以使用下面的正则表达式来限制模板参数:

@Path("users/{username: [a-zA-z_0-9]*}")
如果请求路径不符合要求,将会返回404.

1.2 @GET, @PUT, @POST, @DELETE, … (HTTP Methods)
@GET, @PUT, @POST, @DELETE, @HEAD这些注解称为resource method designator,与HTTP规范中定义的方法一致。这些方法决定资源的行为。

1.3 @Produce
@Produce注解指定返回给客户端的MIME媒体类型。可以用于注解类或者注解方法。

@Path("/myResource")
@Produces("text/plain")
public class SomeResource {
    @GET
    public String doGetAsPlainText() {
        ...
    }

    @GET
    @Produces("text/html")
    public String doGetAsHtml() {
        ...
    }
}
如果类中的方法没有指定,则默认使用类级别的@Produce值。@Produce注解可以指定多个值,同时可以指定quality factor:

@GET
@Produces({"application/xml; qs=0.9", "application/json"})
public String doGetAsXmlOrJson() {
    ...
}
@Consumes
该注解用于指定可以接受的客户端请求的MIME媒体类型:

@POST
@Consumes("text/plain")
public void postClichedMessage(String message) {
    // Store the message
}

注意上述方法返回void,表示没有内容,此时给客户端返回204(No Content)

2. 参数注解(@*Param)
参数注解用于从请求中提取参数,例如上面的@PathParam用于提取路径中的参数。

2.1 @QueryParam
@QueryParam注解用于提取查询参数:

@Path("smooth")
@GET
public Response smooth(
    @DefaultValue("2") @QueryParam("step") int step,
    @DefaultValue("true") @QueryParam("min-m") boolean hasMin,
    @DefaultValue("true") @QueryParam("max-m") boolean hasMax,
    @DefaultValue("true") @QueryParam("last-m") boolean hasLast,
    @DefaultValue("blue") @QueryParam("min-color") ColorParam minColor,
    @DefaultValue("green") @QueryParam("max-color") ColorParam maxColor,
    @DefaultValue("red") @QueryParam("last-color") ColorParam lastColor) {
    ...
}


如果请求参数无法被正确地转化为相应的类型,返回404. 参数类型可以自定义:

public class ColorParam extends Color {

    public ColorParam(String s) {
        super(getRGB(s));
    }

    private static int getRGB(String s) {
        if (s.charAt(0) == '#') {
            try {
                Color c = Color.decode("0x" + s.substring(1));
                return c.getRGB();
            } catch (NumberFormatException e) {
                throw new WebApplicationException(400);
            }
        } else {
            try {
                Field f = Color.class.getField(s);
                return ((Color)f.get(null)).getRGB();
            } catch (Exception e) {
                throw new WebApplicationException(400);
            }
        }
    }
}


对这个类的约束就是要有一个接收字符串的构造函数。如果没有@DefaultValue注解,并且请求中未包含该参数,则方法的参数为各类型的“空值”。

2.2 @MatrixParam
从url片段中提取参数,即url中冒号后面的参数。

2.3 @HeaderParam
从请求的头部提取Header。

2.4 @CookieParam
提取cookie。

2.5 @FormParam
用于提取请求中媒体类型为”application/x-www-form-urlencoded” 的参数,根据相应的表单类型提取其中的参数。

@POST
@Consumes("application/x-www-form-urlencoded")
public void post(@FormParam("name") String name) {
    // Store the message
}

2.6 @BeanParam
该注解用于从请求的各部分中提取参数,并注入到对应的Bean中,例如我们有如下定义的Bean:

public class MyBeanParam {
    @PathParam("p")
    private String pathParam;

    @MatrixParam("m")
    @Encoded
    @DefaultValue("default")
    private String matrixParam;

    @HeaderParam("header")
    private String headerParam;

    private String queryParam;

    public MyBeanParam(@QueryParam("q") String queryParam) {
        this.queryParam = queryParam;
    }

    public String getPathParam() {
        return pathParam;
    }
    ...
}


这个Bean的各个属性都是使用前面的参数注解注解的,然后我们可以在resource class类的方法中使用这个类:

@POST
public void post(@BeanParam MyBeanParam beanParam, String entity) {
    final String pathParam = beanParam.getPathParam(); // contains injected path parameter "p"
    ...
}

当接到请求时,RS实现将从查询参数、头部、Cookie等各处提取参数,并注入到beanParam的各个属性中。

可以组合使用多种参数注解:

@POST
public void post(@BeanParam MyBeanParam beanParam, @BeanParam AnotherBean anotherBean, @PathParam("p") pathParam,
String entity) {
    // beanParam.getPathParam() == pathParam
    ...
}

3. 子资源(Sub-resources)
sub-resources的概念类似于Spring MVC框架中Controller的二级映射,及类级别上有一个@RequestMapping,方法上也有一个二级的@RequestMapping。 @Path注解可以用在类上,表示根资源(root resource),也可以用在类的方法上,这里的方法就叫sub-resource method,对应的资源叫sub-resource。

@Singleton
@Path("/printers")
public class PrintersResource {

    @GET
    @Produces({"application/json", "application/xml"})
    public WebResourceList getMyResources() { ... }

    @GET @Path("/list")
    @Produces({"application/json", "application/xml"})
    public WebResourceList getListOfPrinters() { ... }

    @GET @Path("/jMakiTable")
    @Produces("application/json")
    public PrinterTableModel getTable() { ... }

    @GET @Path("/jMakiTree")
    @Produces("application/json")
    public TreeModel getTree() { ... }

    @GET @Path("/ids/{printerid}")
    @Produces({"application/json", "application/xml"})
    public Printer getPrinter(@PathParam("printerid") String printerId) { ... }

    @PUT @Path("/ids/{printerid}")
    @Consumes({"application/json", "application/xml"})
    public void putPrinter(@PathParam("printerid") String printerId, Printer printer) { ... }

    @DELETE @Path("/ids/{printerid}")
    public void deletePrinter(@PathParam("printerid") String printerId) { ... }
}

此例中,如果url为printers,则对应到getMyResources方法,其他二级url分别对应各方法。

@Path的另一种使用场景是用来表示资源嵌套,此时@Path不与@GET之类的HTTP方法注解一起使用,例如:

@Path("/item")
public class ItemResource {
    @Context UriInfo uriInfo;

    @Path("content")
    public ItemContentResource getItemContentResource() {
        return new ItemContentResource();
    }

    @GET
    @Produces("application/xml")
        public Item get() { ... }
    }
}

public class ItemContentResource {

    @GET
    public Response get() { ... }

    @PUT
    @Path("{version}")
    public void put(@PathParam("version") int version,
                    @Context HttpHeaders headers,
                    byte[] in) {
        ...
    }
}
这里的@Path(“content”)没有指定方法注解,因此如果URL为/item/content,此时会继续往上递归,找到ItemContentResource这个资源类,然后针对该类使用URL匹配规则,所以/item/content将映射ItemContentResource的get方法,’/item/content/1.0’将映射到相应的put方法。 
这里的getItemContentResource()方法因此也叫子资源定位器(sub-resource locator)

单例资源
正常情况下,资源的scope都是针对每个请求的,也就是说每个请求都会创建不同的资源实例,如果想要每个请求都返回一样的资源,此时需要使用单例注解@Singleton:

@Path("/item")
public class ItemResource {
    @Path("content")
    public Class<ItemContentSingletonResource> getItemContentResource() {
        return ItemContentSingletonResource.class;
    }
}

@Singleton
public class ItemContentSingletonResource {
    // this class is managed in the singleton life cycle
}

4. Root Resource Classes的生命周期
root resource默认的生命周期是请求范围的,也就是器生命周期在一个请求内有效。另外Jersey支持两种不同生命周期:

Scope    注解    类全称    说明
Request    @RequestScoped或者空    org.glassfish.jersey.process.internal.RequestScoped    默认的生命周期
Per-lookup    @PerLookup    org.glassfish.hk2.api.PerLookup    
Singleton    @Singleton    javax.inject.Singleton    一个JAX-RS应用只有一个实例,可以在类上使用@Singleton注解或者使用Application注册
5. 注入规则(Rules of Injection)
正常情况下,可以将请求的各种值注入到参数注解注解的对象,例如属性,方法参数,构造函数等。但是有一些特别的注入规则,会根据注入资源的生命周期有所不同,例如有些参数无法注入单例资源:

@Path("resource")
@Singleton
public static class MySingletonResource {

    @QueryParam("query")
    String param; // WRONG: initialization of application will fail as you cannot
                  // inject request specific parameters into a singleton resource.

    @GET
    public String get() {
        return "query param: " + param;
    }
}

事实上,所以跟某个特定请求相关的参数,都不能被注入到单例资源中,这些规则的验证会在应用启动的时候进行。

一些特殊的对象可以被注入到单例的构造函数或者属性中,此时RS运行时会注入对应的代理类,要使用这些特殊的注入,需要使用@Context注解:

@Path("resource")
@Singleton
public static class MySingletonResource {
    @Context
    Request request; // this is ok: the proxy of Request will be injected into this singleton

    public MySingletonResource(@Context SecurityContext securityContext) {
        // this is ok too: the proxy of SecurityContext will be injected
    }

    @GET
    public String get() {
        return "query param: " + param;
    }
}

总结一下注入类型,有:

Class fields: 注入类的域中
构造函数:注入的值将用于调用构造函数
Resource Method:资源的各方法中注入
sub resource locator:不带方法注解的@Path
setter方法:只能使用@Context注解
下面是一个综合的例子:

@Path("resource")
public static class SummaryOfInjectionsResource {
    @QueryParam("query")
    String param; // injection into a class field


    @GET
    public String get(@QueryParam("query") String methodQueryParam) {
        // injection into a resource method parameter
        return "query param: " + param;
    }

    @Path("sub-resource-locator")
    public Class<SubResource> subResourceLocator(@QueryParam("query") String subResourceQueryParam) {
        // injection into a sub resource locator parameter
        return SubResource.class;
    }

    public SummaryOfInjectionsResource(@QueryParam("query") String constructorQueryParam) {
        // injection into a constructor parameter
    }


    @Context
    public void setRequest(Request request) {
        // injection into a setter method
        System.out.println(request != null);
    }
}

public static class SubResource {
    @GET
    public String get() {
        return "sub resource";
    }
}

推荐了解热门学科

java培训 Python人工智能 Web前端培训 PHP培训
区块链培训 影视制作培训 C++培训 产品经理培训
UI设计培训 新媒体培训 产品经理培训 Linux运维
大数据培训 智能机器人软件开发




传智播客是一家致力于培养高素质软件开发人才的科技公司“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。

传智播客从未停止思考

传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”

中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。

何为中高级程序员课程?

传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。




黑马程序员热门视频教程【点击播放】

Python入门教程完整版(懂中文就能学会) 零起点打开Java世界的大门
C++| 匠心之作 从0到1入门学编程 PHP|零基础入门开发者编程核心技术
Web前端入门教程_Web前端html+css+JavaScript 软件测试入门到精通


在线咨询 我要报名
和我们在线交谈!