SpringBoot整合CXF,实现Restful api 与 WebService api dao层使用Mybatis

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34446485/article/details/79669134

1、本demo目的查询学生信息【为了方便没有写批量查询,也就是说以下getAllStudents也是一个一个查询【而且没有测试该方法正确性,之所以写只是为了规范,返回Student的集合Students也是一个独立的实体,非必需,请忽略】

2、主要是网上好多不全,整合的时候各种坑,我就记录一下。

一、老规矩,先搞个数据库

命名demo【可自己修改】
/*
Navicat MySQL Data Transfer

Source Server         : root
Source Server Version : 50540
Source Host           : localhost:3306
Source Database       : demo

Target Server Type    : MYSQL
Target Server Version : 50540
File Encoding         : 65001

Date: 2018-03-23 16:21:20
*/

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(10) NOT NULL,
  `name` varchar(100) DEFAULT NULL,
  `sex` char(6) DEFAULT NULL,
  `address` varchar(255) DEFAULT NULL,
  `age` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '李斯', '男', '江西南昌', '22');
ps【忽略细节,只是为了说明问题】

二、maven依赖【可能不是最少依赖】

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>cn.edu.jxnu</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.10.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!-- 提供JacksonJsonProvider,非必需,学过jersey,所以在这块直接使用了,可以使用其他json转化替换,使用cxf的有很多问题,没法填 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jersey</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
			<version>3.1.11</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.1</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.7</version>
		</dependency>
		<dependency>
			<groupId>org.jsoup</groupId>
			<artifactId>jsoup</artifactId>
			<version>1.9.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>3.1.6</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>3.1.6</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http-jetty</artifactId>
			<version>3.1.6</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

三、实体类

package cn.edu.jxnu.entity;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * 学生实体类
 * 
 * @author: liguobin
 * @Description:
 * @时间: 2018-3-7 下午3:42:04
 * @version: V1.0
 * 
 */
@XmlRootElement(name = "Student")
public class Student implements Serializable {
	private static final long serialVersionUID = 1L;
	private Integer id;
	private String name;
	private char sex;
	private String address;
	private Integer age;

	public Student() {
		super();
	}

	public Student(Integer id, String name, char sex, String address,
			Integer age) {
		super();
		this.id = id;
		this.name = name;
		this.sex = sex;
		this.address = address;
		this.age = age;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public char getSex() {
		return sex;
	}

	public void setSex(char sex) {
		this.sex = sex;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", sex=" + sex
				+ ", address=" + address + ", age=" + age + "]";
	}

}
学生集合实体

package cn.edu.jxnu.entity;

import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * 封装多个学生实体类
 * 
 * @author: liguobin
 * @Description:
 * @时间: 2018-3-7 下午3:42:14
 * @version: V1.0
 * 
 */
@XmlRootElement(name = "Students")
public class Students {

	private List<Student> students;

	public Students(List<Student> students) {
		super();
		this.students = students;
	}

	@XmlElement(name = "Student")
	public List<Student> getStudents() {
		return students;
	}

	public Students() {
		super();
	}

	public void setStudents(List<Student> students) {
		this.students = students;
	}

}

四、开始整合SpringBoot mybatis

整合myabtis的具体不再赘述,网上很多也很简单。
application.properties
#server port set
server.port: 8082
#mysql datasource set
spring.datasource.
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

mybatis.typeAliasesPackage=cn.edu.jxnu.entity
mybatis.mapperLocations=classpath\:mapper/*.xml
mybatis.config-location=classpath\:mybatis-config.xml
spring.jackson.serialization.indent_output =true
logging.level.org.springframework.web=WARN
#logging.file = C\:\\web\\temp\\log\\log.log
logging.level.org.springframework=WARN
logging.level.cn.edu.jxnu.dao=INFO
logging.level.cn.edu.jxnu.resource=WARN

mybatis-config.xml 【没干什么】

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 在这里仅仅为了开启懒加载 -->
	<settings>
		<!-- 打开延迟加载的开关 -->
		<setting name="lazyLoadingEnabled" value="true" />
		<!-- 将积极加载改为消极加载,即延迟加载 -->
		<setting name="aggressiveLazyLoading" value="false" />
		<setting name="cacheEnabled" value="true" />
	</settings>

</configuration>

StudentMapper.xml mapper文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.edu.jxnu.dao.StudentDao">
	<resultMap type="cn.edu.jxnu.entity.Student" id="Student">
		<id property="id" column="id" />
		<result property="name" column="name" />
		<result property="sex" column="sex" />
		<result property="address" column="address" />
		<result property="age" column="age" />
	</resultMap>
	<!-- 定义字段集合 -->
	<sql id="studentInformation">
		id,name,sex,address,age
	</sql>
	<select id="getStudentById" resultMap="Student" flushCache="true"
		parameterType="java.lang.Integer">
		select
		<include refid="studentInformation" />
		from student where id=#{id}
	</select>
	<!-- 刷新间隔 -->
	<cache flushInterval="600000" />
</mapper>

mapper接口

package cn.edu.jxnu.dao;

import org.apache.ibatis.annotations.Param;

import cn.edu.jxnu.entity.Student;

/**
 * dao层数据操作接口
 * 
 * @author: liguobin
 * @Description:
 * @时间: 2018-3-7 下午3:41:43
 * @version: V1.0
 * 
 */
public interface StudentDao {

	Student getStudentById(@Param("id") Integer id);
}

配置SpringBoot扫描dao【这个也是主启动类,学过SpringBoot应该都知道,不再赘述】

package cn.edu.jxnu;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
import org.springframework.stereotype.Controller;

/**
 * 启动类
 * 
 * @author: liguobin
 * @Description:
 * @时间: 2018-3-7 下午3:41:24
 * @version: V1.0
 * 
 */
@Controller
@MapperScan("cn.edu.jxnu.dao")
@SpringBootApplication
// / 没有这个rest失效 只存在soap
@ImportResource(locations = { "classpath:cxf-config.xml" })
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}
cxf-config.xml很重要,等等再说

五、重点  整合cxf webService【注意,不是restful,而是webservice 基于soap的】

cxf配置类【因为是使用SpringBoot,所以使用类和注解配置】

package cn.edu.jxnu;

import javax.xml.ws.Endpoint;

import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;

import cn.edu.jxnu.serviceImpl.StudentServiceImpl;

/**
 * 
 * @author: liguobin @Description: @时间: 2018-3-7 下午4:11:57 @version: V1.0
 * 
 */
@Configuration
public class CxfConfig {

	@Bean
	public ServletRegistrationBean newServlet() {
		return new ServletRegistrationBean(new CXFServlet(), "/cxf/*");
	}

	@Bean(name = Bus.DEFAULT_BUS_ID)
	public SpringBus springBus() {
		return new SpringBus();
	}

	/**
	 * @return
	 */
	@Bean
	@Qualifier("studentServiceImpl") // 注入webService
	public Endpoint endpoint(StudentRestfulServiceImpl studentServiceImpl) {
		EndpointImpl endpoint = new EndpointImpl(springBus(), studentServiceImpl);
		endpoint.publish("/webService");// 暴露webService api,用在资源访问
		return endpoint;
	}

	@Bean("jsonProvider") // 构造一个json转化bean,用于将student转化为json,因为后面需要用这个bean配置json转化,所以给他取个名
	public JacksonJsonProvider getJacksonJsonProvider() {
		return new JacksonJsonProvider();

	}
}
CXFServlet()是返回一个cxf Servlet,用来拦截cxf,这里传入拦截路径/cxf/* 也就是访问路径是: ip:port/cxf/这里填@path的值
此处为了说明我写了一个Spring Controller

package cn.edu.jxnu;

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.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.edu.jxnu.entity.Student;
import cn.edu.jxnu.entity.Students;
import cn.edu.jxnu.service.StudentService;

import com.alibaba.fastjson.JSONObject;

/**
 * Spring 前端控制
 * 
 * 通过这个返回正确,作对比
 * 
 * @author: liguobin
 * @Description:
 * @时间: 2018-3-7 下午3:35:17
 * @version: V1.0
 * 
 */
@Controller
public class SpringController {

	@Autowired
	private StudentService studentService;

	@ResponseBody
	@Produces({ MediaType.APPLICATION_JSON + "charset='utf-8'" })
	@RequestMapping(value = "get/{id}", method = RequestMethod.GET)
	public String getStudent(@PathVariable("id") Integer id) {
		Student student = studentService.getStudent(id);
		Object json = JSONObject.toJSON(student);
		return json.toString();
	}

	/**
	 * @参数:{"ids":{"id":[1,2,3,4]
	 * 
	 * @param ids
	 * @return
	 */
	@ResponseBody
	@Produces({ MediaType.APPLICATION_JSON + "charset='utf-8'" })
	@Consumes({ MediaType.APPLICATION_JSON })
	@RequestMapping(value = "gets/{ids}", method = RequestMethod.GET)
	public String getAll(@PathVariable("ids") String ids) {
		Students students = studentService.getAllStudent(ids);
		Object json = JSONObject.toJSON(students);
		return json.toString();
	}
}

众所周知springmvc的默认由dispatherServlet处理。所以这里使用ip:port/get/1 即可获取【@PathVariable 是Spring的 与PathParam 是JSR-RS的功能类似

此处只是为了说明cxf 的重要性。可以看到,没有使用/cxf/ 就依然是由springmvc来处理的


编写webservice 接口  基本是最简了

package cn.edu.jxnu.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import cn.edu.jxnu.entity.Student;
import cn.edu.jxnu.entity.Students;

/**
 * @description WebService接口定义 soap
 * @author liguobin
 * 
 */
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) // 返回类型
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) // 请求类型
@WebService
public interface StudentService {

	/**
	 * 查找一个学生
	 * 
	 * @param id
	 * @return
	 */
	@WebMethod
	public Student getStudent(@WebParam(name = "id") Integer id);

	/**
	 * 查找多个学生
	 * 
	 * @param ids
	 * @return
	 */
	@WebMethod
	public Students getAllStudent(@WebParam(name = "ids") String ids);

}

实现service

package cn.edu.jxnu.serviceImpl;

import java.util.ArrayList;

import javax.jws.WebService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.edu.jxnu.dao.StudentDao;
import cn.edu.jxnu.entity.Student;
import cn.edu.jxnu.entity.Students;
import cn.edu.jxnu.service.StudentService;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 实现webservice接口,对外暴露 soap
 * 
 * @author: liguobin 
 * @Description: 
 * @时间: 2018-3-7 下午3:43:06 
 * @version: V1.0
 * 
 */
@Component//由Spring管理
@WebService(endpointInterface = "cn.edu.jxnu.service.StudentService") // webservice接口的全类名
public class StudentServiceImpl implements StudentService {

	/**
	 * 注入spring bean
	 */
	@Autowired
	private StudentDao studentDao;

	@Override
	public Student getStudent(Integer id) {
		return studentDao.getStudentById(id);
	}

	/**
	 * 没有测试正确性,不是本文重点
	 */
	@Override
	public Students getAllStudent(String ids) {
		Students students = new Students(new ArrayList<Student>());
		// 得到json对象
		JSONObject json = JSONObject.parseObject(ids);
		// 获取对象的id列表
		JSONArray sid = json.getJSONArray("id");

		for (int i = 0; i < sid.size(); i++) {
			Integer s = sid.getInteger(0);
			if (s != null) {
				students.getStudents().add(studentDao.getStudentById(s));
			} else {
				continue;
			}
		}
		return students;

	}

}

测试webservice

输入http://localhost:8082/cxf    【查看所以soap和restful api】

单独查看某一个soap api【http://localhost:8082/cxf/webService?wsdl】 在前文  endpoint.publish("/webService");// 就是这个webService

浏览器显示:


点击wsdl


命名空间等等都是默认的,没有在webservice配置。也为了简洁

六、整合Restful api【 RESTful services

首先,编写rest一个接口

package cn.edu.jxnu.resource;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import cn.edu.jxnu.entity.Student;
import cn.edu.jxnu.entity.Students;

/**
 * @author: liguobin 
 * @Description: 
 * @时间: 2018-3-7 下午3:59:15 
 * @version: V1.0
 * 
 */
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public interface StudentInterface {

	/**
	 * @param id
	 * @return
	 */
	@GET
	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@Path("/getone/{id:[0-9]{0,10}}") // 限制id只能是0~9的数组 不超过10位
	public Student getStudent(@PathParam("id") Integer id);

	/**
	 * 查找多个学生
	 * 
	 * @param ids
	 * @return
	 */

	@GET
	@Produces({ MediaType.APPLICATION_JSON })
	@Path("/getmany/{ids}")
	public Students getAllStudent(@PathParam("ids") String ids);
}

实现rest接口

package cn.edu.jxnu.resource;

import java.util.ArrayList;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import cn.edu.jxnu.entity.Student;
import cn.edu.jxnu.entity.Students;
import cn.edu.jxnu.service.StudentService;

@Path("/")
public class StudentInterfaceImpl implements StudentInterface {

	@Autowired
	private StudentService studentService;

	// 获取json
	@Override
	@GET
	@Path("/getjson/{id:[0-9]{0,10}}")
	@Produces({ MediaType.APPLICATION_JSON })
	public Student getStudent(@PathParam("id") Integer id) {
		return studentService.getStudent(id);
	}

	// 获取xml
	@GET
	@Path("/getxml/{id}")
	@Produces({ MediaType.APPLICATION_XML })
	public Student getStudent2(@PathParam("id") Integer id) {
		return studentService.getStudent(id);
	}

	/**
	 * 返回students集合,此方法没有测试,参数是一个json对象,该对象包含一个name为id的数组
	 */
	@Override
	@GET
	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@Path("/getmany/{ids}")
	public Students getAllStudent(@PathParam("ids") String ids) {
		Students students = new Students(new ArrayList<Student>());
		// 得到json对象
		JSONObject json = JSONObject.parseObject(ids);
		// 获取对象的id列表
		JSONArray sid = json.getJSONArray("id");

		for (int i = 0; i < sid.size(); i++) {
			Integer s = sid.getInteger(0);
			if (s != null) {
				students.getStudents().add(studentService.getStudent(s));
			} else {
				continue;
			}
		}
		return students;

	}

}
写法不标准甚至有错不要在意,不是本文重点

rest接口和类都写完,剩下就是配置了

前文,在主类曾经导入过一个配置文件,这个文件就是专门用来配置cxf的【@ImportResource(locations = { "classpath:cxf-config.xml" })

cxf-config.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:jaxrs="http://cxf.apache.org/jaxrs"
	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.0.xsd   
       http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd   
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
	<!-- 将Bean托管给Spring -->
	<bean id="studentService" class="cn.edu.jxnu.resource.StudentInterfaceImpl">
	</bean>
	<!-- 配置需要暴露的Rest ful Service -->
	<jaxrs:server id="restContainer" address="/students"> <!-- 暴露restful api 类似于前文提到的webService【暴露soap】 即访问的时候要加上这个address -->
		<jaxrs:serviceBeans>
			<!-- 相当于打包发布服务 -->
			<ref bean="studentService" />
		</jaxrs:serviceBeans>
		<!-- 提供一个json转化,没有这个不能自动返回json jsonProvider就是前面@Bean生成的在CxfConfig -->
		<jaxrs:providers>
			<ref bean="jsonProvider" />
		</jaxrs:providers>
	</jaxrs:server>
</beans>  


查看RestFul api


浏览器输入http://localhost:8082/cxf/ 就可以查看到多了 Available RESTful services:Endpoint address: http://localhost:8082/cxf/students

【因为soap和restful均是cxf处理】

最后测试restful请求

输入http://localhost:8082/cxf/students/getjson/1   获取json数据


输入http://localhost:8082/cxf/students/getxml/1  获取xml数据

github 源码:https://github.com/jxnu-liguobin/SpringBoot-CXF-demo


以上仅供参考



展开阅读全文

没有更多推荐了,返回首页