欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Jersey 实践:构建RESTful服务及解决跨域问题

程序员文章站 2022-07-10 10:23:34
...

最近在准备为我的小程序做个后台,刚好之前在网上了解了RESTful这种设计风格,觉得很简单轻量,便准备采用这种设计方式。有很多框架都能支持RESTful的设计,在一番权衡之后,决定选择jersey框架,因为我的小程序的并发量并不大,而且自己对于spring也还不太熟悉,而jersey框架写起来很简单,开发比较快。接下来便来讲解如何用jersey完整的构建RESTful服务。

开发所使用IDE:Eclipse

开发环境:Maven、Jersey

因为jersey是基于maven的,所以大家要先装好maven环境,具体方法请自行百度。

一、新建maven项目

Jersey 实践:构建RESTful服务及解决跨域问题

具体就不赘述了。

二、导入jersey的jar包

没有的话到官网下载:https://jersey.github.io/download.html。除了把jar包导入到java build path外,也要放到lib文件夹里。

Jersey 实践:构建RESTful服务及解决跨域问题

三、编写代码

在src/main/java里新建包,再新建两个类:MyApplication和common

Jersey 实践:构建RESTful服务及解决跨域问题

因为jersey是通过注解来识别不同的请求的,所以编写起来十分方便

import javax.ws.rs.*;
import javax.ws.rs.core.*;

@Path("/common") //表示请求该类下的url时前面要加上/common,@Path里的值不一定要与类名相同
public class common {
	   @GET
	   @Path("/hello") //访问时是 /common/hello
	    public String hello() {
	        return "hello";
	    }
	   }

@GET表示通过get请求,@Path表示请求时对应的url,当通过get请求/common/hello时会调用hello(),请求后服务器将返回hello字符串。怎么样?是不是很简单?短短几行代码就能实现spring大量代码等同的功能。

接下来我们就要在MyApplication里注册我们的类了,也就是配置资源,因为REST认为每个url都是资源,只有注册后访问url才有效。

import org.glassfish.jersey.server.ResourceConfig;

public class MyApplication extends ResourceConfig {

    public MyApplication() {
        register(common.class);
    }
}

注册也很简单,通过继承ResourceConfig,然后再在构造器里通过register方法注册我们的类,就行了。

四、配置xml

最后一步就是配置xml了,这个也不难。我们需要配置两个web.xml文件。第一个是WebContent里的

Jersey 实践:构建RESTful服务及解决跨域问题

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>auto_make_page</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>com.main.MyApplication</servlet-name>
  </servlet>
  <servlet-mapping>
    <servlet-name>com.main.MyApplication</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

然后是下图这个

Jersey 实践:构建RESTful服务及解决跨域问题

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>com.main_servlet.MyApplication</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.main.MyApplication</param-value>
            
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>com.main_servlet.MyApplication</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

注意这个的servlet-name是com.main_servlet.MyApplication,在所在包名后加上_servlet。

最后就可以把项目部署进tomcat运行了~~访问的url是  /项目名/common/hello

Jersey 实践:构建RESTful服务及解决跨域问题

jersey还有很多注解,能够实现非常丰富的功能,大家可以到官网查看。

 

【跨域问题解决】

我们在本地调试远程服务器的api的时候,会遇到跨域问题。浏览器为了安全而不允许设置Access-Control-Allow-Origin的header,而服务器为了安全也只允许当origin与域名相同时才能访问。浏览器我们无法修改,但在服务端我们可以。代码如下:

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.container.*;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.ContainerResponse;

public class CorsFilter implements ContainerResponseFilter {
  
    public ContainerResponse filter(ContainerRequest creq, ContainerResponse cres) {
        cres.getHeaders().add("Access-Control-Allow-Origin", "*");
        /**
         * 允许的Header值,不支持通配符
         */
        cres.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
        cres.getHeaders().add("Access-Control-Allow-Credentials", "true");

        /**
         * 即使只用其中几种,header和options是不能删除的,因为浏览器通过options请求来获取服务的跨域策略
         */
        cres.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");

        /**
         * CORS策略的缓存时间
         */
        cres.getHeaders().add("Access-Control-Max-Age", "1209600");

       //可以通过 throw new WebApplicationException(Status.UNAUTHORIZED); 来中断请求

        return cres;
    }

	public void filter(ContainerRequestContext request, ContainerResponseContext cres) throws IOException {
		 if("OPTIONS".equalsIgnoreCase(request.getMethod())) {//浏览器会先通过options请求来确认服务器是否可以正常访问,此时应放行
 		    cres.setStatus(HttpServletResponse.SC_OK);
 		}
		 	cres.getHeaders().add("Access-Control-Allow-Origin", "*");

	        cres.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
	        cres.getHeaders().add("Access-Control-Allow-Credentials", "true");

	        cres.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");

	        /**
	         * CORS策略的缓存时间
	         */
	        cres.getHeaders().add("Access-Control-Max-Age", "1209600");

	}

}

最后把这个类也注册进MyApplication就行了。