前言:
1、Web Service笔记(五):利用CXF结合Spring开发web service
2、XML学习笔记(三):Jaxb负责xml与javaBean映射
3、jax-rs详解
4、可以使用浏览器的工具调试:如 Firefox 的RESTClient 和chrome的REST Console。
一、配置Spring的配置文件
1、需要引入新的 jar 包。
2、配置 applicationContext-server.xml 文件。使用 jaxrs:server ,记得引入jaxrs 的schema 约束。
1)address:为地址,如 http://localhost:8080/Java_WS_Server/rest/
2)serviceBeans:暴露的ws服务类。也可以使用“#beanId”,引入。
-
- <jaxrs:server id="restfulServer" address="/rest">
- <jaxrs:inInterceptors>
- </jaxrs:inInterceptors>
- <jaxrs:serviceBeans>
- <bean class="cn.rest.rest.SurpolicyEntrence"></bean>
- </jaxrs:serviceBeans>
- <jaxrs:extensionMappings>
- <entry key="json" value="application/json" />
- <entry key="xml" value="application/xml" />
- </jaxrs:extensionMappings>
- <jaxrs:languageMappings>
- <entry key="en" value="en-gb"/>
- </jaxrs:languageMappings>
- </jaxrs:server>
二、Restful 服务类需要实现jax_rs规范。就像ws的服务类需要实现jax_ws规范一样。1、在 javax.ws.rs.* 中定义,都是一些注解,是 JAX-RS (JSR 311) 规范的一部分。
2、具体的注解如下:
1)@Path:定义资源基 URI。由上下文根和主机名组成,如:
- http://localhost:8080/Java_WS_Server/rest/surpolicy
2)@GET/@POST:这意味着以下方法可以响应 HTTP GET 或是 HTTP POST方法。 3)@Produces:响应内容 MIME 类型。如
- @Produces(MediaType.TEXT_PLAIN)
- @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
4)@Context: 使用该注释注入上下文对象,比如 Request、Response、UriInfo、ServletContext 等。
- @Context HttpServletRequest servletRequest
- @Context HttpServletResponse servletResponse
- @Context
- private UriInfo uriInfo;
5)@PathParam("contact"):该注释将参数注入方法参数的路径。其他可用的注释有 @FormParam、@QueryParam 等。
3、一般来说,服务类与方法上应该分别标注注解 @Path,用于区分访问路径。
- @Path(value = "/surpolicy")
- public class SurpolicyEntrence {}
- @Path("/sendXml")
- public String sendXml(String requestXML) {}
三、简单的 RESTful 服务
1、服务类代码:
-
-
-
-
-
-
- @GET
- @Path("/sendString/{input}")
-
- @Produces(MediaType.TEXT_PLAIN)
- public String sendStringParam(@PathParam("input") String input) {
- System.out.println("接收的参数: \r\n" + input);
- String tReturn = "成功返回";
- return tReturn;
-
- }
启动服务后,访问 http://localhost:8080/Java_WS_Server,有Available RESTful services的内容,说明发布成功。
2、分析:
1)前提:服务类的path定义为如下,故所有的方法的访问地址都为
http://localhost:8080/Java_WS_Server/rest/surpolicy/ + "方法自己的地址"。/rest 为在配置文件中配置的address地址
- @Path(value = "/surpolicy")
- public class SurpolicyEntrence {}
2)@Path("/sendString/{input}") :用浏览器的rest 工具访问的时候,必须把参数放在url地址后面。如:
3)访问的结果如下:
后台显示:表示成功。返回的信息可以在 RestClient 中查看。
3、客户端代码:本文中的客户端统一使用 org.apache.cxf.jaxrs.client.WebClient 实现。
其他实现方式见:
HTTP访问的两种方式(HttpClient和HttpURLConnection)
利用HttpURLConnection和WebClient发布REST风格的WebService客户端(解决超时问题)
1)WebClient 可以使用spring注入,也可以手工创建:
-
-
-
-
-
- ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-client.xml");
- client = ctx.getBean("webClient", WebClient.class);
使用spring,需要配置 applicationContext-client.xml 代码:- <bean id="webClient" class="org.apache.cxf.jaxrs.client.WebClient" factory-method="create">
- <constructor-arg type="java.lang.String" value="http://localhost:8080/Java_WS_Server/rest/" />
- </bean>
2)先初始化 webClient对象- public void init() {
-
-
-
-
-
- ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-client.xml");
- client = ctx.getBean("webClient", WebClient.class);
-
- }
3)简单服务的访问方法:
-
-
-
- public void sendString(){
- String tResponseMsg = client.path("surpolicy/ping/{input}","我来ping一下。。").accept(MediaType.TEXT_PLAIN).get(String.class);
- System.out.println(tResponseMsg);
- }
4)显示:
- 服务端:
- 接收的参数:
- 我来ping一下。。
-
- 客户端:
- 成功返回
四、以XML为交互内容的 RESTful 服务
(一)需要使用 jaxb 来映射Xml与javaBean。
1、接收的javaBean 代码。
- package cn.rest.bean;
-
- import java.util.List;
-
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlElementWrapper;
- import javax.xml.bind.annotation.XmlRootElement;
-
-
-
-
-
-
-
-
-
-
-
- @XmlRootElement(name = "USER")
- public class UserBean {
- private String name;
- private String age;
- private UserAddress userAddress;
- private List<UserPhone> phoneList ;
-
- @XmlElement(name="NAME")
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @XmlElement(name = "AGE")
- public String getAge() {
- return age;
- }
-
- public void setAge(String age) {
- this.age = age;
- }
-
- @XmlElement(name = "UserAddress")
- public UserAddress getUserAddress() {
- return userAddress;
- }
-
- public void setUserAddress(UserAddress userAddress) {
- this.userAddress = userAddress;
- }
-
- @XmlElementWrapper(name = "PhoneList")
- @XmlElement(name = "UserPhone")
- public List<UserPhone> getPhoneList() {
- return phoneList;
- }
-
- public void setPhoneList(List<UserPhone> phoneList) {
- this.phoneList = phoneList;
- }
-
- }
- package cn.rest.bean;
-
- public class UserPhone {
-
- private String type;
- private String num;
-
- public String getType() {
- return type;
- }
- public void setType(String type) {
- this.type = type;
- }
- public String getNum() {
- return num;
- }
- public void setNum(String num) {
- this.num = num;
- }
-
- }
- package cn.rest.bean;
-
- import javax.xml.bind.annotation.XmlElement;
-
- public class UserAddress {
-
- private String homeAddress;
- private String workAddress;
-
- @XmlElement(name = "HomeAddress")
- public String getHomeAddress() {
- return homeAddress;
- }
- public void setHomeAddress(String homeAddress) {
- this.homeAddress = homeAddress;
- }
-
- @XmlElement(name = "WorkAddress")
- public String getWorkAddress() {
- return workAddress;
- }
- public void setWorkAddress(String workAddress) {
- this.workAddress = workAddress;
- }
-
- }
2、返回的javaBean 代码。
- package cn.rest.bean.response;
-
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlRootElement;
-
-
-
-
-
- @XmlRootElement(name = "RETURN")
- public class ReturnDTO {
-
- protected String code;
- protected String msg;
-
- @XmlElement(name="Code")
- public String getCode() {
- return code;
- }
- public void setCode(String code) {
- this.code = code;
- }
- @XmlElement(name="MSG")
- public String getMsg() {
- return msg;
- }
- public void setMsg(String msg) {
- this.msg = msg;
- }
-
- }
3、转换工具类。
- package cn.rest.util;
- import java.io.StringReader;
- import javax.xml.bind.JAXBContext;
- import javax.xml.bind.JAXBException;
- import javax.xml.bind.Marshaller;
- import javax.xml.bind.Unmarshaller;
- import org.xml.sax.InputSource;
- import cn.rest.bean.UserBean;
-
-
-
-
-
-
-
-
-
-
- public class ObjectAndXmlHandle {
-
- public static UserBean parseXml2OUserBean(String xml) {
- try {
- JAXBContext context = JAXBContext.newInstance(UserBean.class);
- InputSource is = new InputSource();
- StringReader xmlStr = new StringReader(xml);
- is.setCharacterStream(xmlStr);
- Unmarshaller unmarshaller = context.createUnmarshaller();
- UserBean user = (UserBean) unmarshaller.unmarshal(is);
- return user;
- } catch (JAXBException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- public static void Object2Xml(Object object) {
-
- try {
- JAXBContext context = JAXBContext.newInstance(object.getClass());
- Marshaller marshal = context.createMarshaller();
- marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
- marshal.setProperty("jaxb.encoding", "utf-8");
- marshal.marshal(object, System.out);
-
-
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
(二)、服务端方法代码1、把 xml 以 String 的方法传输。
-
-
-
-
-
-
- @POST
- @Path("/sendXml")
- @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
- public String sendXml(String requestXML) {
- System.out.println("接收的参数:\r\n " + requestXML);
-
- UserBean tUserBean = ObjectAndXmlHandle.parseXml2OUserBean(requestXML);
-
- String tReturn = tUserBean.getName()+ " 你好,你的请求成功返回";
- return tReturn;
- }
2、RESTClient 工具访问,xml放在 Body 中,可以不设置 Content-Type
3、客户端访问代码:
-
-
-
- private void sendRequestXml() {
- String tRequestXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><USER><AGE>27</AGE><NAME>SAM-SHO</NAME><PhoneList><UserPhone><num>13612345678</num><type>移动</type></UserPhone><UserPhone><num>13798765432</num><type>联通</type></UserPhone></PhoneList><UserAddress><homeAddress>苏州高新区</homeAddress><workAddress>苏州园区</workAddress></UserAddress></USER>";
- String tResponseMsg = client.path("surpolicy/sendXml").accept(MediaType.APPLICATION_XML).post(tRequestXml, String.class);
- System.out.println("返回的信息: \r\n" + tResponseMsg);
- }
五、以JavaBean为交互内容的 RESTful 服务1、服务端方法代码
-
-
-
-
-
-
-
-
-
- @POST
- @Path("/sendBean")
- @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
- public ReturnDTO sendBean(UserBean user) {
-
-
- ObjectAndXmlHandle.Object2Xml(user);
- System.out.println(user.getUserAddress().getHomeAddress());
-
- ReturnDTO tReturnDTO = new ReturnDTO();
- tReturnDTO.setCode("1");
- tReturnDTO.setMsg(user.getName()+ " ,请求成功,已返回");
-
- return tReturnDTO;
- }
2、RESTClient访问
1)一定要设置 headers信息,设置 Content-Type: application/xml ,不然访问不了。
2)需要设置 Content-Type。
3)正确访问:
5)成功返回:
3、客户端访问:
-
-
-
- private void sendRequestBean() {
- UserBean tUserBean = new UserBean();
- tUserBean.setName("SAM-SHO");
- tUserBean.setAge("27");
-
- UserAddress tUserAddress = new UserAddress();
- tUserAddress.setWorkAddress("苏州园区");
- tUserAddress.setHomeAddress("苏州高新区");
- tUserBean.setUserAddress(tUserAddress);
-
- List<UserPhone> phoneList = new ArrayList<UserPhone>();
- UserPhone tUserPhone = new UserPhone();
- tUserPhone.setType("移动");
- tUserPhone.setNum("13612345678");
- phoneList.add(tUserPhone);
-
- tUserPhone = new UserPhone();
- tUserPhone.setType("联通");
- tUserPhone.setNum("13798765432");
- phoneList.add(tUserPhone);
- tUserBean.setPhoneList(phoneList);
-
- ClientConfiguration config = WebClient.getConfig(client);
- config.getHttpConduit().getClient().setReceiveTimeout(90000);
- ReturnDTO tReturnDTO = client.path("surpolicy/sendBean").accept(MediaType.APPLICATION_XML).acceptEncoding("utf-8").post(tUserBean,ReturnDTO.class );
-
- System.out.println("返回的数据:" + tReturnDTO.getMsg());
-
- }
六、服务端与客户端完整代码如下:
1、服务端
- package cn.rest.rest;
-
- import javax.ws.rs.GET;
- import javax.ws.rs.POST;
- import javax.ws.rs.Path;
- import javax.ws.rs.PathParam;
- import javax.ws.rs.Produces;
- import javax.ws.rs.core.MediaType;
-
- import cn.rest.bean.UserBean;
- import cn.rest.bean.response.ReturnDTO;
- import cn.rest.util.ObjectAndXmlHandle;
-
-
-
-
-
-
-
-
-
-
- @Path(value = "/surpolicy")
- public class SurpolicyEntrence {
-
-
-
-
-
-
-
- @GET
- @Path("/sendString/{input}")
-
- @Produces(MediaType.TEXT_PLAIN)
- public String sendStringParam(@PathParam("input") String input) {
- System.out.println("接收的参数: \r\n" + input);
- String tReturn = "成功返回";
- return tReturn;
-
- }
-
-
-
-
-
-
-
- @POST
- @Path("/sendXml")
- @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
- public String sendXml(String requestXML) {
- System.out.println("接收的参数:\r\n " + requestXML);
-
- UserBean tUserBean = ObjectAndXmlHandle.parseXml2OUserBean(requestXML);
-
- String tReturn = tUserBean.getName()+ " 你好,你的请求成功返回";
- return tReturn;
- }
-
-
-
-
-
-
-
-
-
-
- @POST
- @Path("/sendBean")
- @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
- public ReturnDTO sendBean(UserBean user) {
-
-
- ObjectAndXmlHandle.Object2Xml(user);
- System.out.println(user.getUserAddress().getHomeAddress());
-
- ReturnDTO tReturnDTO = new ReturnDTO();
- tReturnDTO.setCode("1");
- tReturnDTO.setMsg(user.getName()+ " ,请求成功,已返回");
-
- return tReturnDTO;
- }
- }
2、客户端