一.WebService概述
1.1WebService简介
Web Service(WEB服务)能够快捷和方便地综合结合各种系统、商务和任何应用平台。利用最新的Web Service 标准能够使任何软件系统和系统之间的应用互通互联,方便,而且更加廉价。
1.2WebService的应用场景
-
跨越防火墙通信
-
集成应用程序
-
复用软件
1.3其他远程应用调用解决方案
-
使用Socket远程通信
-
使用Apache的HttpClient
-
RMI(Remote Method Invoke)
1.4WebService的三个规范
-
JAXM&SAAJ(废弃)
-
JAX-WS :采用标准SOAP(Simple Object Access Protocol) 协议传输,soap协议传输是xml数据。
-
JAX-RS:Java针对REST(Representation State Transfer)风格制定的一套Web服务规范。
二.Apache的CXF
Apache CXF是一个开源的Web Service 框架,CXF 帮助我们构建和开发 Web Service,它支持多种协议,如:SOAP, XML/HTTP、RESTful或者CORBA。
下载地址:http://cxf.apache.org/download.html
三.基于JAX-WS规范的入门
3.1JAX-WS的三要素
-
SOAP:基于HTTP协议,采用XML格式,用来传递信息的格式。
-
WSDL:用来描述如何访问具体的服务
-
UDDI:用户可按UDDI标准搭建UDDI服务器,用来管理分发,查询WebService。其他用户可以自己注册发布WebService调用。
3.2入门案例
我们在使用WebService时,更多的时候充当的是调用者。因为服务端别人已经写好了。
3.2.1编写服务端
第一步:创建Maven工程导入CXF坐标
<!-- 导入cxf相关坐标 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-features-logging</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.3.0</version> </dependency>
第二步:编写服务接口和实现类
/** * 提供实时公交的服务接口 * @author Mr.song * @date 2019/05/20 9:55 */ @WebService //表明当前接口是一个WebService服务 public interface BusService { /** * 根据公交线路查询公交实时站点 * @param line 公交线路 * @return */ String getBusByLine(String line); } //========================================== /**提供实时公交的服务实现类 * @author Mr.song * @date 2019/05/20 9:57 */ public class BusServiceImpl implements BusService { public String getBusByLine(String line) { if ("916".equals(line)){ return "距您还有3站"; } return "未知"; } }
Tips:注意加入@WebService注解
第三步:编写测试类(main方法启动)
/** * @author Mr.song * @date 2019/05/20 10:17 */ public class WebBusServiceTest { public static void main(String[] args) { //1.创建发布服务的对象 JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean(); //2.设置服务地址 factoryBean.setAddress("http://localhost:8847/bus"); //3.设置服务的对象 factoryBean.setServiceBean(new BusServiceImpl()); //4.发布服务 factoryBean.create(); } }
第四步:浏览器访问测试
地址为:http://localhost:8847/bus/?wsdl
若控制台无错误,则表明服务端编写正确。
3.2.2编写客户端
第一步:创建Maven工程导入CXF坐标(同上)
第二步:使用jdk提供的命令生成本地代码
使用的是jdk bin目录下的wsimport.exe工具
进入到客户端工程java目录下,按住shift右击,在此处打开shell窗口输入命令:wsimport -s . http://localhost:8847/bus/?wsdl 即可完成解析,并生成代码。(此处的链接是服务端浏览器测试时访问的)| -s 指定生成文件目录 . 指当前文件夹下
第三步:编写测试类
/** * @author Mr.song * @date 2019/05/20 16:32 */ public class BusTest { @Test public void testBus(){ //1.创建客户端的代理工厂bean JaxWsProxyFactoryBean proxy = new JaxWsProxyFactoryBean(); //2.设置说明书的地址 proxy.setAddress("http://localhost:8847/bus?wsdl"); //3.设置客户端需要使用的服务接口类字节码 proxy.setServiceClass(BusService.class); //4.使用proxy创建服务接口的代理对象 Object obj = proxy.create(); //5.如果obj是service接口的代理实现类,强转成service接口 BusService busService = (BusService) obj; //6.执行service中的方法 String rtValue = busService.getBusByLine("916"); System.out.println(rtValue); } }
Tips: 运行测试端代码时,保证服务端不要关闭
3.3Spring整合CXF
3.3.1编写服务端
第一步:创建Maven的Web工程并导入CXF坐标(同上)
第二步:编写服务接口和实现类(同上)
第三步:配置 Spring 的配置文件
<?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:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 配置服务端的服务 --> <!-- 主机和端口用tomcat的,http协议 --> <jaxws:server address="/bus"> <!-- 配置具体服务实现类 --> <jaxws:serviceBean> <bean class="cn.dintalk.service.BusServiceImpl"/> </jaxws:serviceBean> </jaxws:server> </beans>
第四步:在 web.xml 中配置Spring容器在应用加载时创建
<?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_2_5.xsd" version="2.5"> <!-- 配置应用加载监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-cxf-server.xml</param-value> </context-param> <!-- CXF框架的核心控制器:CXFServlet --> <servlet> <servlet-name>cxf</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxf</servlet-name> <!-- 配置处理请求url中含有/ws/*的请求 --> <url-pattern>/ws/*</url-pattern> </servlet-mapping> </web-app>
第五步:浏览器访问测试
地址:http://localhost:8080/ws/bus?wsdl
若控制台无错误,则表明服务端编写正确。
3.3.2编写客户端
第一步:创建Maven的Web工程并导入CXF坐标(同上)
第二步:使用 jdk 提供的命令生成客户端代码(同上)
第三步:编写 Spring 配置文件
<?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:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 配置服务端访问地址和应用接口 --> <jaxws:client id="client" address="http://localhost:8080/ws/bus?wsdl" serviceClass="cn.dintalk.service.BusService"></jaxws:client> </beans>
第四步:编写测试类
/** * @author Mr.song * @date 2019/05/20 17:29 */ public class BusTest { @Test public void testBus(){ //1.读取配置文件,创建容器 ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-cxf-client.xml"); //2.根据bean的id获取对象 BusService busService = (BusService) ac.getBean("client"); //3.执行方法 String rtValue = busService.getBusByLine("916"); System.out.println(rtValue); } }
Tips: 运行测试类测试时,主要不要关闭服务端。
四.基于JAX-RS规范的入门
4.1JAX-RS和Restful
JAX-RS 是一个 Java 编程语言接口,被设计用来简化使用 REST 架构的应用程序的开发。JAX-RS API 使用 Java 编程语言的注解来简化 RESTful web service 的开发。开发人员使用 JAX-RS 的注解修饰Java编程语言的类文件来定义资源和能够应用在资源上的行为。JAX-RS的注解是运行时的注解,因此运行时的映射会为资源生成辅助类和其他的辅助文件。包含 JAX-RS 资源类的 Java EE 应用程序中资源是被配置好的,辅助类和辅助文件是生成的,资源通过被发布到 Java EE 服务器上来公开给客户端。
RESTful web service 是创建来能在 web 更好的运行的 web service。REST 是一种架构类型,指定了如统一的接口等应用于 web service 的约束。REST 提供了如性能、可扩展性和可变性等特性,使得 service 能够更好的在web上工作。在 REST 框架中,数据和功能被认为是资源,是通过 URI来访问的,通常是 web链接。资源是通过使用一组简单的、定义良好的操作来生效。REST 的架构方式限定了客户/服务器架构,是设计来使用无状态的通信协议的,通常是 HTTP。在 REST 框架类型中,客户端和服务器使用标准的接口和协议交换资源的representation。
4.2入门案例
4.2.1编写服务端
第一步:创建Maven工程并导入坐标
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-extension-providers</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> <version>1.3.7</version> </dependency>
第二步:编写实体类(业务实体)
@XmlRootElement(name = "User") public class User { private Integer id; private String username; private String city; private List<Car> cars = new ArrayList<Car>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", city=" + city + ", cars=" + cars + "]"; }
@XmlRootElement(name = "Car") public class Car { private Integer id; private String carName; private Double price; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getCarName() { return carName; } public void setCarName(String carName) { this.carName = carName; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } @Override public String toString() { return "Car [id=" + id + ", carName=" + carName + ", price=" + price + "]"; } }
第三步:编写业务接口和实现类
@Path("/userService") @Produces("*/*") public interface UserService { @POST @Path("/user") @Consumes({ "application/xml", "application/json" }) public void saveUser(User user); @PUT @Path("/user") @Consumes({ "application/xml", "application/json" }) public void updateUser(User user); @GET @Path("/user") @Produces({ "application/xml", "application/json" }) public List<User> findAllUsers(); @GET @Path("/user/{id}") @Consumes("application/xml") @Produces({ "application/xml", "application/json" }) public User finUserById(@PathParam("id") Integer id); @DELETE @Path("/user/{id}") @Consumes({"application/xml", "application/json"}) public void deleteUser(@PathParam("id") Integer id); }
/** * @author Mr.song * @date 2019/05/20 19:39 */ public class UserServiceImpl implements UserService { public void saveUser(User user) { System.out.println("save user:" + user); } public void updateUser(User user) { System.out.println("update user:" + user); } public List<User> findAllUsers() { List<User> users = new ArrayList<User>(); User user1 = new User(); user1.setId(1); user1.setUsername("小明"); user1.setCity("北京"); List<Car> carList1 = new ArrayList<Car>(); Car car1 = new Car(); car1.setId(101); car1.setCarName("保时捷"); car1.setPrice(1000000d); carList1.add(car1); Car car2 = new Car(); car2.setId(102); car2.setCarName("宝马"); car2.setPrice(400000d); carList1.add(car2); user1.setCars(carList1); users.add(user1); User user2 = new User(); user2.setId(2); user2.setUsername("小丽"); user2.setCity("上海"); users.add(user2); return users; } public User finUserById(Integer id) { if (id == 1) { User user1 = new User(); user1.setId(1); user1.setUsername("小明"); user1.setCity("北京"); return user1; } return null; } public void deleteUser(Integer id) { System.out.println("delete user id :" + id); } }
第四步:编写服务发布类
/** * jaxrs服务的发布 * @author Mr.song * @date 2019/05/20 19:45 */ public class UserTest { public static void main(String[] args) { //1.创建jaxrs服务工厂bean对象 JAXRSServerFactoryBean factoryBean = new JAXRSServerFactoryBean(); //2.设置服务地址 factoryBean.setAddress("http://localhost:8848"); //3.设置提供服务的类 factoryBean.setServiceBean(new UserServiceImpl()); //4.设置日志输入和输出的两个拦截器 factoryBean.getInInterceptors().add(new LoggingInInterceptor()); factoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); //5.发布服务 factoryBean.create(); } }
4.2.2编写客户端
第一步:创建Maven工程并导入坐标(同时)
第二步:编写业务实体类(同上)
第三步:编写测试类
/** * @author Mr.song * @date 2019/05/20 19:55 */ public class UserClientTest { /** * 注意:它和jaxws规范的区别是,它使用的是restful的url */ @Test public void test(){ User user = new User(); user.setId(1); user.setUsername("test"); //1.使用WebClient创建访问地址 : 在服务端接口中有/userService /user的路径规则 Object rtValue = WebClient.create("http://localhost:8848/userService/user") .type(MediaType.APPLICATION_XML).post(user); System.out.println(rtValue); } @Test public void test2(){ //1.使用WebClient创建访问地址 Object rtValue = WebClient.create("http://localhost:8848/userService/user/123") .type(MediaType.APPLICATION_JSON).delete(); System.out.println(rtValue); } }
Tips: 测试时保证服务端开启。
4.3Spring整合CXF
4.3.1编写服务端
第一步:创建Maven的Web工程并导入坐标(同上)
第二步:编写业务代码(实体类和服务接口及实现类)同上
第三步:编写Web.xml配置文件
<?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_2_5.xsd" version="2.5"> <!-- 配置应用加载监听器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-cxf-rs.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- CXF的核心控制器 --> <servlet> <servlet-name>cxfServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>cxfServlet</servlet-name> <!-- 配置拦截的路径 --> <url-pattern>/rs/*</url-pattern> </servlet-mapping> </web-app>
第四步:编写Spring配置文件
<?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:jaxrs="http://cxf.apache.org/jaxrs" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> <!-- 配置服务:ip、端口用tomcat的 --> <!-- 这里配置了address,接口类就不要配置注解了(@Path("/userService")) --> <jaxrs:server id="userService" address="/userService"> <jaxrs:serviceBeans> <bean class="cn.dintalk.service.UserServiceImpl"/> </jaxrs:serviceBeans> <!-- 配置拦截器 --> <jaxrs:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/> </jaxrs:inInterceptors> <jaxrs:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/> </jaxrs:outInterceptors> </jaxrs:server> </beans>
4.3.2编写客户端
第一步:创建Maven工程并导入坐标(同上)
第二步:创建业务实体类(同上)
第三步:编写测试类
@Test public void test04(){ User user = WebClient.create("http://localhost:8080/rs/userService/user/1") .type(MediaType.APPLICATION_XML).get(User.class); System.out.println(user); } //输出如下: //User [id=1, username=小明, city=北京, cars=[]]
Tips: 测试时要保证服务端开启。