一 什么是webservice
web服务:部署在网络上的一个可访问的应用程序,主要对外提供一些业务接口。
日常例子:天气预告、查询手机的归属地。
二 webservice组成
说明:
注册方:服务提供者首先要在注册服务器上注册服务的接口、方法信息、访问地址等等。
服务提供者:服务的实现方
服务消费者:调用服务的一方,称为服务的客户端,指的是一切调用服务的消费者,例如,app、网站、组件 、controller等等。
三 传统的webservice的技术标准(了解)
1. xml文档 数据格式以xml数据交互,优点:平台无关性和语言无关性。是以远程方法调用(RPC).
2. 通讯协议 SOAP协议 simple object access protocal 简单对象访问协议,相对http性能更好,可以传输对象。
3. wsdl web服务描述语言(xml),主要的作用描述web服务(说明书)
技术场景: Dubbo微服务(阿里开源)
四 restfult服务(重点)
1. json数据交互 不是远程方法调用
2. http协议
3. 无wsdl文件
技术场景: Springboot+Springcloud分布式应用开发
五 使用CXF开发Webservice
Apache CXF = Celtix + Xfire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF。Apache CXF 是一个开源的 web Services 框架,CXF 帮助您构建和开发 web Services ,它支持多种协议,比如:SOAP1.1,1,2XML/HTTP、RESTful 或者CORBA。
开发步骤:
(1)开发web应用
(2)导入cxf3类库
(3)配置web.xml,cxf的中央控制器。cxf是基于MVC结构
<!-- CXF 中央控制器 -->
<servlet>
<servlet-name>cxfServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxfServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
(4)实现业务功能
业务接口
@WebService //表示当前是一个可发布的接口
public interface ProductService {
public List<Product> findAllProducts();
}
业务实现类
public class ProductServiceImpl implements ProductService {
@Override
public List<Product> findAllProducts() {
List<Product> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(new Product(i,"TCL电视"+i,5000D,"广州"));
}
return list;
}
}
(5)以spring方式发布webservice
<!-- 以spring方式发布应用程序接口 -->
<jaxws:endpoint id="productServiceImpl"
implementor="com.gec.ws.service.ProductServiceImpl"
address="/productService"></jaxws:endpoint>
(6)访问Websevice的wsdl文件
地址:http://localhost:8080/services/productService?wsdl
(7) 客户端访问
spring方式(代理方式)
/**
* 远程方法调用,spring方式
* 远程方法调用,边界条件:以jvm来区分
*/
public class WebServiceSpringTest {
public static void main(String[] args) {
//要获取spring创建的webservice客户端
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取的是代理接口实例
ProductService productService = (ProductService) context.getBean("productService");
List<Product> list = productService.findAllProducts(); //方法的远程调用
for (Product product : list) {
System.out.println(product.getNanme());
}
}
}
代理方式
/**
* 不依赖于spring
* 使用代理方式创建远程访问的客户端
*/
public class ProxyTest {
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(ProductService.class); //设置代理接口类型
factory.setAddress("http://localhost:8080/services/productService");
ProductService productService = (ProductService) factory.create();
List<Product> list = productService.findAllProducts(); //方法的远程调用
for (Product product : list) {
System.out.println(product.getNanme());
}
}
}
六 Restful服务
Restful服务指的是将网络上的资源分配一个唯一标识(URI),只需要获取了该资源的唯一标识就可以对这个资源进行操作(增删改查)。基本都是以json进行交互。在SSM项目中,一般会使用springmvc的controller对外发布业务数据。
restfule服务常用的操作类别:
GET(查询) POST(创建) PUT(编辑) DELETE(删除)
(1) 完整定义restful服务接口
@Api(tags = "ItemController",description = "商品后台管理服务")
@RestController
public class ItemController {
@Autowired
public ItemService itemService;
@ApiOperation("查询所有商品信息")
@GetMapping("/findAll")
public List<Items> findAll() {
return itemService.findAll();
}
@ApiOperation("根据唯一标识查询唯一商品信息")
@GetMapping("/findOne/{id}")
public Items findOne(@PathVariable int id) {
return itemService.findOne(id);
}
@ApiOperation("添加商品信息")
@PostMapping("/addItems")
public RespBean addItems(@ApiParam("商品对象") @RequestBody Items items) {
System.out.println(items.getId());
System.out.println(items.getName());
try{
itemService.addItem(items);
return RespBean.ok("添加成功",items);
} catch (Exception ex){
ex.printStackTrace();
return RespBean.error("添加失败");
}
}
@ApiOperation("编辑商品信息")
@PutMapping("/updateItems")
public RespBean updateItems(@ApiParam("商品对象") @RequestBody Items items) {
System.out.println(items.getId());
System.out.println(items.getName());
try{
itemService.updateItem(items);
return RespBean.ok("编辑成功",items);
} catch (Exception ex){
ex.printStackTrace();
return RespBean.error("编辑失败");
}
}
@ApiOperation("根据商品唯一标识删除商品信息")
@DeleteMapping("/deleteItems/{id}")
public RespBean deleteItems(@PathVariable int id) {
try{
itemService.deleteItem(id);
return RespBean.ok("删除成功");
} catch (Exception ex){
ex.printStackTrace();
return RespBean.error("删除失败");
}
}
}
(2) 响应消息类
/**
* 消息响应类
*/
public class RespBean {
private Integer code; //自定义响应码: 200正常 500错误
private String message;
private Object data; //返回的数据
public static RespBean ok(String message) {
return new RespBean(200,message);
}
public static RespBean ok(String message,Object data) {
return new RespBean(500,message,data);
}
public static RespBean error(String message) {
return new RespBean(200,message);
}
public static RespBean error(String message,Object data) {
return new RespBean(500,message,data);
}
private RespBean(Integer code, String message, Object data) {
this.code = code;
this.message = message;
this.data = data;
}
private RespBean(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
七 服务的测试
(1)Postman工具
添加测试:
修改测试
(2)Swagger2在线文档
实现步骤:
添加swagger依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
swagger配置
/**
* Swagger2API文档的配置
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//为当前包下controller生成API文档
.apis(RequestHandlerSelectors.basePackage("com.gec.ssm.controller"))
//为有@Api注解的Controller生成API文档
// .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
//为有@ApiOperation注解的方法生成API文档
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("SwaggerUI演示")
.description("商品查询服务")
.contact("陈志凌")
.version("1.0")
.build();
}
}
swagger2的常用注解
主要有三个常用注解:使用于类、方法、参数列表的注解
@Api(tags = "ItemController",description = "商品后台管理服务")
@RestController
public class ItemController {
@Autowired
public ItemService itemService;
@ApiOperation("查询所有商品信息")
@GetMapping("/findAll")
public List<Items> findAll() {
return itemService.findAll();
}
@ApiOperation("根据唯一标识查询唯一商品信息")
@GetMapping("/findOne/{id}")
public Items findOne(@PathVariable int id) {
return itemService.findOne(id);
}
@ApiOperation("添加商品信息")
@PostMapping("/addItems")
public RespBean addItems(@ApiParam("商品对象") @RequestBody Items items) {
System.out.println(items.getId());
System.out.println(items.getName());
try{
itemService.addItem(items);
return RespBean.ok("添加成功",items);
} catch (Exception ex){
ex.printStackTrace();
return RespBean.error("添加失败");
}
}
@ApiOperation("编辑商品信息")
@PutMapping("/updateItems")
public RespBean updateItems(@ApiParam("商品对象") @RequestBody Items items) {
System.out.println(items.getId());
System.out.println(items.getName());
try{
itemService.updateItem(items);
return RespBean.ok("编辑成功",items);
} catch (Exception ex){
ex.printStackTrace();
return RespBean.error("编辑失败");
}
}
@ApiOperation("根据商品唯一标识删除商品信息")
@DeleteMapping("/deleteItems/{id}")
public RespBean deleteItems(@PathVariable int id) {
try{
itemService.deleteItem(id);
return RespBean.ok("删除成功");
} catch (Exception ex){
ex.printStackTrace();
return RespBean.error("删除失败");
}
}
}
效果:
八 总结两种服务区别
说明:
RPC remote process call 远程方法调用
以XML文档进行方法调用的交互
比较复杂,实现较繁琐
采用SOAP协议
客户端要引用服务端的代理接口类型,作为方法的远程调用
应用场景:适用于同构应用比较多
访问性能较好
微服务的发展方向:Dubbo
说明:
数据交互采用json格式
使用http协议
访问性能较差
同构和异构应用都可以使用,应用范围广泛
仅仅是客户端对远程资源的定位操作(增删改查),并不是远程方法的调用
微服务的发展方向:springboot+springcloud
九 RestTemplate访问Restful服务
JavaWeb应用的controller调用:
@Controller
public class ItemWebController {
@Autowired
private RestTemplate restTemplate;
public String baseURL = "http://localhost:8088/";
@GetMapping("/queryItems")
public ModelAndView queryItems() {
//泛型:LinkedHashMap
List list = restTemplate.getForObject(baseURL+"findAll", List.class);
System.out.println(list);
ModelAndView mv = new ModelAndView();
mv.addObject("itemList",list);
mv.setViewName("itemlist");
return mv;
}
@GetMapping("/findItemById")
public ModelAndView findItemById(int id) {
ItemEntity itemEntity = restTemplate.getForObject(baseURL+"findOne/"+id, ItemEntity.class);
ModelAndView mv = new ModelAndView();
mv.addObject("item",itemEntity);
mv.setViewName("editItem");
return mv;
}
@PostMapping("/updateItemsSubmit")
public String updateItemsSubmit(ItemEntity itemEntity) {
restTemplate.put(baseURL+"updateItems",itemEntity);
return "redirect:/queryItems";
}
@PostMapping("/addItemsSubmit")
public String addItemsSubmit(ItemEntity itemEntity) {
RespBean respBean = restTemplate.postForObject(baseURL+"addItems",itemEntity, RespBean.class);
if (respBean.getCode()==200){
return "redirect:/queryItems";
} else {
return "addItem";
}
}
@GetMapping("/deleteItem")
public String deleteItem(int id) {
restTemplate.delete(baseURL+"deleteItems/"+id);
return "redirect:/queryItems";
}
}