Android端需要的Jar
ksoap2的下载地址,现在下载积分很贵啊,反正我是没有积分。
https://github.com/simpligility/ksoap2-android/releases
为了方便这里先自行准备个接口用来练习。
这里我使用的IntelliJ IDEA创建的后台项目。用的JDK1.8,转Kotlin项目直接用的IDE提示的方式进行转换的。需要在pom.xml添加上以下两个依赖:
<dependency>
<groupId>org.jetbrains.kotlingroupId>
<artifactId>kotlin-reflectartifactId>
<version>${kotlin.version}version>
dependency>
<dependency>
<groupId>org.apache.cxfgroupId>
<artifactId>cxf-spring-boot-starter-jaxwsartifactId>
<version>3.2.5version>
dependency>
这里准备一个实体类,用来当返回数据用,后台程序入口代码就不贴出来了。
/**
* 测试数据
* msg : 内容
* date : 日期
*/
data class Message(val msg : String , val date : String)
接下来定义一下接口的功能,这里准备返回JSON字符串,所以返回类型设成了String(这种先写接口,再写实现的方式。让我想起了C++创建类的时候的先写.h声明,再写.cpp文件实现。顿时有种感觉很有道理,又说不清楚的感觉- -!)。代码如下:
import javax.jws.WebMethod
import javax.jws.WebService
/**
* 定义接口
*/
@WebService
interface TestService {
@WebMethod(action = "http://service.test.lyan.com/getMsg")
fun getMsg(): String
}
实现接口的具体功能,返回一条Json格式的数据。具体实现如下:
import com.fasterxml.jackson.databind.ObjectMapper
import com.lyan.test.bean.Message
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import javax.jws.WebService
/**
* 调用的接口
*/
@Component
@WebService(endpointInterface = "com.lyan.test.service.TestService",
serviceName = "TestService", targetNamespace = "http://service.test.lyan.com/")
class TestImpl : TestService {
@Autowired
private lateinit var objectMapper: ObjectMapper
/**
* 客户端调用的方法
*/
override fun getMsg(): String =
objectMapper.writeValueAsString(
Message("测试内容", LocalDate.now().format(
DateTimeFormatter.ofPattern("yyyy-MM-dd"))))
}
import com.lyan.test.service.TestService
import org.apache.cxf.Bus
import org.apache.cxf.jaxws.EndpointImpl
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import javax.xml.ws.Endpoint
/**
* 用来发布接口的配置
*/
@Configuration
open class CxfConfig {
@Autowired
private lateinit var testService: TestService
@Autowired
private lateinit var bus : Bus
/**
* 发布测试接口
*/
@Bean open fun testEndpoint(): Endpoint = EndpointImpl(bus,testService).apply { publish("/TestService") }
}
接下来运行SpringBoot项目,请求这个本地地址http://localhost:8080/services。不出意外肯定会出现下面这个页面(圈中的部分就是发布的接口):
点击这个链接,就会跳到下面这个页面,圈中的部分就是我们请求的url地址,也就是我们通常请求的url就是这么来的:
到这里准备工作已经完成,接下来就是在android端中调用这个接口,获取数据了。
在Android工程里别忘了添加ksoap2的Jar包和请求网络的权限。这里为了装逼就没用线程去做异步请求用的协程,既然是练习还是用线程的话感觉实在是太low了。用到的依赖如下(具体版本去Anko的Github里找就行):
implementation "org.jetbrains.anko:anko-commons:$anko_version"
implementation "org.jetbrains.anko:anko-coroutines:$anko_version"
下面这个配置最好也加上,加上后跟协程有关的代码会看的舒服一些
kotlin { experimental { coroutines ‘enable’ } }
接下来就实现网络请求的功能就可以了,主要功能就是将请求到的数据展示在弹窗中。
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import org.jetbrains.anko.AnkoLogger
import org.jetbrains.anko.alert
import org.jetbrains.anko.coroutines.experimental.bg
import org.jetbrains.anko.info
import org.ksoap2.SoapEnvelope
import org.ksoap2.serialization.SoapObject
import org.ksoap2.serialization.SoapSerializationEnvelope
import org.ksoap2.transport.HttpTransportSE
/**
* 网络请求测试界面
*/
class MainActivity : AppCompatActivity() ,AnkoLogger{
private val NAMESPACE = "http://service.test.lyan.com/"
private val METHOD_NAME = "getMsg"
private val SOAP_ACTION = "$NAMESPACE$METHOD_NAME"
private val URL = "http://192.168.3.224:8080/services/TestService?wsdl"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/**
* 点击按钮后进行网络数据的请求
* getData 按钮控件的id
*/
getData.setOnClickListener {
launch(UI) {
val result = bg { downLoad() }.await()
info{"返回内容 -> $result"}
alert { message = result }.show()
}
}
}
/**
* 请求WebService接口
*/
private fun downLoad(): String {
val request = SoapObject(NAMESPACE, METHOD_NAME)
val envelope = SoapSerializationEnvelope(SoapEnvelope.VER11)
envelope.setOutputSoapObject(request)
val transportSE = HttpTransportSE(URL)
transportSE.call(SOAP_ACTION, envelope)
return envelope.response.toString()
}
}
之前只是普通的请求,那如果有上传参数怎么办呢。接下来对代码改造一下。
在后台部分对接口的定义和实现改造一下,让getMsg()这个方法能接收参数,改造后如下:
/**
* 接口
*/
@WebService
interface TestService {
@WebMethod(action = "http://service.test.lyan.com/getMsg")
fun getMsg(@WebParam(name = "msg") message : String): String
}
在实现中就是将上传的参数,添加到返回的数据中,然后再返还给客户端。具体代码如下:
/**
* 实现
*/
@Component
@WebService(endpointInterface = "com.lyan.test.service.TestService",
serviceName = "TestService", targetNamespace = "http://service.test.lyan.com/")
class TestImpl : TestService {
@Autowired
private lateinit var objectMapper: ObjectMapper
/**
* 客户端调用的方法
*/
override fun getMsg(message : String): String =
objectMapper.writeValueAsString(
Message(message, LocalDate.now().format(
DateTimeFormatter.ofPattern("yyyy-MM-dd"))))
}
Android这部分很好改,就是在请求的时候通过SoapObject的addProperty()方法添加参数就行了。
/**
* 请求WebService接口
*/
private fun downLoad(): String {
val request = SoapObject(NAMESPACE, METHOD_NAME)
request.addProperty("msg" , "来自客户端的数据")//添加的上传参数
val envelope = SoapSerializationEnvelope(SoapEnvelope.VER11)
envelope.setOutputSoapObject(request)
val transportSE = HttpTransportSE(URL)
transportSE.call(SOAP_ACTION, envelope)
return envelope.response.toString()
}