Spring5.x+Jersey+Tomcat搭建REST服务

       Jersey作为最开始的REST的参考,有很多项目偏好使用Jersey构建RestFul服务。CXF同样也能够构建REST服务,但是CXF最开始是作为实现SOAP的框架,比较完善,同时也相对重载,在REST构建上可能性能不如Jersey。

       我最开始构建时是在原使用CXF的WebService工程中,想到这样需要引入的jar包相对较少(在使用CXF构建REST引入了一些CXF之外的包,如javax.ws.rs-api-2.1.jar,包含了@GET、@QueryParam等暴露服务时需要使用的注解)

1.使用Jersey1.x构建REST服务引入的Jersey包,如图:

        在启动时没有报错,但是访问报错了:java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/

        经百度发现是UriBuilder类在javax.ws.rs-api-2.1.jar和jersey-bundle-{version}.jar中都有,而且路径都是javax.ws.rs.core,因此导致类加载冲突。解决方案,去掉javax.ws.rs-api-2.1.jar,重新启动项目,访问正常

Jersey1.x版本和2.x版本的变化较大,1.x版本的类路径基本是com.sun开头,而2.x版本以glassfish开头org.glassfish开头

注册服务

Jersey的服务注册主要有2种方式:

(1)按包去注册,使用默认的资源加载器加载,在定义Jersey的Servlet时param-name指定为jersey.config.server.provider.packages,而param-value为资源包的路径

(2)注册资源类,使用自定义的资源加载器加载,param-name为javax.ws.rs.Application,param-value为资源类路径

疑问:2种注册服务的方式各有什么优劣势和使用场景呢?实际项目中更推荐使用哪种方式?

2.使用Jersey2构建REST服务(不使用Spring)

手动引入jar包,经实测,这些包都不能少

web.xml配置

<servlet>
     <servlet-name>JerseyServlet</servlet-name>
     <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
     <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <!-- javax.ws.rs.core.Application -->
        <param-value>
            com.weijie.resource
        </param-value>
        <!-- com.weijie.resource.Resource -->
     </init-param>
  </servlet>
  <servlet-mapping>
     <servlet-name>JerseyServlet</servlet-name>
     <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

资源类

package com.weijie.resource;
import com.weijie.service.impl.ExportExcel;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.core.MediaType;

import com.weijie.pojo.Test;

@Path("/resource")
public class Resource {
    
    @GET
    @Path("hello")
    @Produces(MediaType.TEXT_PLAIN)
    public String sayHello(@QueryParam("str")String str)
    {
        return new ExportExcel().hello(str);
    }
    
    @GET
    @Path("test")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String test(@QueryParam("name")String name,@QueryParam("value")String value)
    {
        String str ="This is " + name +",value is " + value;
        return str;
    }
    
    @POST
    @Path("form")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)//APPLICATION_FORM_URLENCODED
    @Produces(MediaType.APPLICATION_JSON)
    public Test writeSomething(@FormParam("value1")String value1,@FormParam("value2")String value2)
    {
        Test test =new Test();
        test.setName(value1);
        test.setValue(value2);
        
        test.setNum((int)(Math.random()*100));
        
        System.out.println(test.getNum());
        return test;
    }
    
    @POST
    @Path("form1")
    @Consumes(MediaType.APPLICATION_JSON)//APPLICATION_FORM_URLENCODED
    @Produces(MediaType.APPLICATION_JSON)
    public Test writeSomething1(Test test)//使用@FormParam会报错,因为Jersey默认接受application/x-www-form-urlencoded参数
    {
        Test result =new Test();
        result.setName(test.getName()+"1");
        result.setValue(test.getValue()+"1");
        
        result.setNum(test.getNum()+(int)(Math.random()*100));
        
        return result;
    }

}
POJO类

package com.weijie.pojo;
import java.io.Serializable;

public class Test implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 3486448853755783061L;
    
    private String name;
    
    private String value;
    
    private int num;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    } 

}

测试WADL,结构http://IP:port/项目名/Jersey的Servlet拦截的uri/application.wadl,最后面的application.wadl是不变的

Spring5.x+Jersey构建REST服务

web.xml

<context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring.xml</param-value>
  </context-param>
  <listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
     <servlet-name>JerseyServlet</servlet-name>
     <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
     
     <init-param>
        <!--<param-name>javax.ws.rs.Application</param-name> 
        <param-value>com.weijie.resource.Service</param-value>-->
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.weijie.resource</param-value>
     </init-param>
  </servlet>
  
  <servlet-mapping>
     <servlet-name>JerseyServlet</servlet-name>
     <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

bean的配置(spring.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    
    <!-- 开启注解扫描 
    (1)到包里面扫描类,方法,属性上面是否有注解
    
    <context:component-scan base-package = "com.weijie.resource"></context:component-scan>
    -->
    <!-- 只会扫描属性上的注解 
    <context:annotation-config></context:annotation-config>
    -->
    <bean id="export" class ="com.weijie.service.impl.ExportExcel"/>
</beans>

POJO类

package com.weijie.pojo.export;
import java.io.Serializable;

public class ExportVO implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = -2793236307669513041L;
    private String appid;
    private String report;
    private String owner;
    private Params[] params;
    
    public String getAppid() {
        return appid;
    }
    public void setAppid(String appid) {
        this.appid = appid;
    }
    public String getReport() {
        return report;
    }
    public void setReport(String report) {
        this.report = report;
    }
    public String getOwner() {
        return owner;
    }
    public void setOwner(String owner) {
        this.owner = owner;
    }
    public Params[] getParams()
    {
        return params;
    }
    public void setParams(Params[] params)
    {
        this.params =params;
    }
    public static class Params implements Serializable
    {    
        /**
         * 
         */
        private static final long serialVersionUID = -3276814523885247312L;
        private String key;
        private Object value;
        public String getKey() {
            return key;
        }
        public void setKey(String key) {
            this.key = key;
        }
        public Object getValue() {
            return value;
        }
        public void setValue(Object value) {
            this.value = value;
        }
    }
}

这里使用了一个静态内部类,用于相对复杂一点的对象,可用于接受数组参数,针对一些场景需要识别自适应参数,方便扩展。对于参数较多的场景,也可以使用这种方式。
资源类:

package com.weijie.resource;
import com.weijie.service.api.IExportExcel;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
import javax.ws.rs.QueryParam;
import com.weijie.pojo.export.ExportVO;

import javax.ws.rs.FormParam;


//@Component
@Path("/resource")
public class ExportResource {
    @Autowired
    private IExportExcel export;
    
    @Path("/hello")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String hello(@QueryParam("str")String str)
    {
        return export.hello(str);
    }
    
    @Path("/export")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)//.APPLICATION_JSON
    @Produces(MediaType.APPLICATION_JSON)
    public String export(ExportVO expVO)
    {
        return export.export(expVO);
    }
    
    @Path("/export1")
    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)//.APPLICATION_JSON
    @Produces(MediaType.APPLICATION_JSON)
    public String export1(@FormParam("appid")String appid,@FormParam("report")String report, @FormParam("owner")String owner)
    {
        ExportVO expVO =new ExportVO();
        expVO.setAppid(appid);
        expVO.setReport(report);
        expVO.setOwner(owner);
        return export.export(expVO);
    }

}
接口:

package com.weijie.service.api;
import com.weijie.pojo.export.ExportVO;

public interface IExportExcel {
    public String hello(String str);
    public String export(ExportVO expVO);

}
实现类:

package com.weijie.service.impl;
import com.weijie.service.api.IExportExcel;
import com.weijie.pojo.export.ExportVO;

public class ExportExcel implements IExportExcel{
    public String hello(String str)
    {
        return "hello "+str;
    }
    
    public String export(ExportVO expVO)
    {
        StringBuilder sb =new StringBuilder();
        sb.append("appid:"+ expVO.getAppid()).append(",export:"+expVO.getReport()).append(",owner:"+expVO.getOwner());
        return sb.toString()+Math.random()*100;
    }

}
总结:Jersey是REST的参考实现,Jersey2相对于Jersey1在项目结构上有较大的变化。Jersey默认生成WADL

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值