前言
相信通過上一篇介紹就會對WebService有一個大致的理解,今天主要搭建一個可以用在實際項目中的WebService框架。框架主要用到的是spring+mybatis,用MySQL數據庫,數據庫和表以及用到的數據自己建我就不說了,發佈服務用的是jdk自帶的jaxws(沒有用cxf是因爲依賴的包太多了)。
具體步驟
先看一下整個項目的工程目錄
1.第一步新建一個動態web工程,添加依賴的包(包含spring、mybatis等等)。如下圖
2.第二步整合spring。在web.xml中加入spring容器加載。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
spring配置文件applicationContext.xml如下
<?xml version="1.0" encoding="GBK"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:core="http://jax-ws.dev.java.net/spring/core"
xsi:schemaLocation="http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 自動掃描註解的bean -->
<context:component-scan base-package="com.mycompany"></context:component-scan>
<!-- 加載靜態文件 -->
<context:property-placeholder location="classpath:db.properties"/><!-- 加載配置文件 -->
<!-- 配置數據源 c3p0數據連接池-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 指定連接池中保留的最大連接數. Default:15-->
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>
<!-- 指定連接池中保留的最小連接數-->
<property name="minPoolSize" value="${jdbc.minPoolSize}"/>
<!-- 指定連接池的初始化連接數 取值應在minPoolSize 與 maxPoolSize 之間.Default:3-->
<property name="initialPoolSize" value="${jdbc.initialPoolSize}"/>
<!-- 最大空閒時間,60秒內未使用則連接被丟棄。若爲0則永不丟棄。 Default:0-->
<property name="maxIdleTime" value="${jdbc.maxIdleTime}"/>
<!-- 當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數. Default:3-->
<property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>
<!-- JDBC的標準,用以控制數據源內加載的PreparedStatements數量。
但由於預緩存的statements屬於單個connection而不是整個連接池所以設置這個參數需要考慮到多方面的因數.如果maxStatements與maxStatementsPerConnection均爲0,則緩存被關閉。Default:0-->
<property name="maxStatements" value="${jdbc.maxStatements}"/>
<!-- 每60秒檢查所有連接池中的空閒連接.Default:0 -->
<property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"/>
</bean>
<!-- mybaits 配置 begin-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:/mappings/*.xml"/>
<property name="configLocation" value="classpath:sqlMapConfig.xml" />
</bean>
<!-- 掃描basePackage下所有的接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mycompany.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!-- mybaits 配置 end-->
<!-- webservice jax-ws -->
<!-- baseAddress 的value地址以及端口號是自定義的,端口號不要爲已使用過的 -->
<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
<property name="baseAddress" value="http://10.4.125.84:8099/"/>
</bean>
</beans>
配置文件中各個bean的作用都加了註釋,就不在重複了,下邊附上數據庫配置文件db.properties
#mysql database settings
jdbc.type=mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?
jdbc.username=root
jdbc.password=ABcd1234@
#c3p0 setting
jdbc.initialPoolSize=20
jdbc.maxPoolSize=100
jdbc.minPoolSize=10
jdbc.maxIdleTime=600
jdbc.acquireIncrement=5
jdbc.maxStatements=5
jdbc.idleConnectionTestPeriod=60
3.接下來整合mybatis。在上一步中spring配置文件已經將mybatis整合進去了,下面附上mybatis配置文件sqlMapConfig.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>
<!--<properties resource="webService.properties"/>-->
<settings>
<setting name="callSettersOnNulls" value="true"/>
<!-- 使全局的映射器啓用或禁用緩存。 -->
<setting name="cacheEnabled" value="true"/>
<!-- 全局啓用或禁用延遲加載。當禁用時,所有關聯對象都會即時加載。 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 當啓用時,有延遲加載屬性的對象在被調用時將會完全加載任意屬性。否則,每種屬性將會按需要加載。 -->
<setting name="aggressiveLazyLoading" value="true"/>
<!-- 是否允許單條sql 返回多個數據集 (取決於驅動的兼容性) default:true -->
<setting name="multipleResultSetsEnabled" value="true"/>
<!-- 是否可以使用列的別名 (取決於驅動的兼容性) default:true -->
<setting name="useColumnLabel" value="true"/>
<!-- 允許JDBC 生成主鍵。需要驅動器支持。如果設爲了true,這個設置將強制使用被生成的主鍵,有一些驅動器不兼容不過仍然可以執行。 default:false -->
<setting name="useGeneratedKeys" value="false"/>
<!-- 指定 MyBatis 如何自動映射 數據基表的列 NONE:不隱射 PARTIAL:部分 FULL:全部 -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!-- 這是默認的執行類型 (SIMPLE: 簡單; REUSE: 執行器可能重複使用prepared statements語句;BATCH: 執行器可以重複執行語句和批量更新) -->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 使用駝峯命名法轉換字段。 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 設置本地緩存範圍 session:就會有數據的共享 statement:語句範圍 (這樣就不會有數據的共享 ) defalut:session -->
<setting name="localCacheScope" value="SESSION"/>
<!-- 設置但JDBC類型爲空時,某些驅動程序 要指定值,default:OTHER,插入空值時不需要指定類型 -->
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
<typeAliases>
<typeAlias alias="HashMaps" type="java.util.HashMap" />
</typeAliases>
</configuration>
4.一般開發都需要記錄日誌,加入log4j日記文件log4j.properties,如下
log4j.rootLogger=INFO,stdout,R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy.MM.dd HH:mm:ss} %p [%c] -%m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=../logs/webservice.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy.MM.dd HH:mm:ss} %p [%c] -%m%n
log4j.logger.com.ibatis=info
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=info
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=info
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=info
log4j.logger.java.sql.Statement=info
log4j.logger.java.sql.PreparedStatement=info,stdout
5.完成以上步驟,基本上框架就搭建好了,下面寫個測試類,實現的功能是通過員工id查詢員工姓名。
HelloWorldService.java代碼如下
package com.mycompany.service;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(targetNamespace="http://service.mycompany.com/")
@SOAPBinding(style=Style.RPC)
public interface HelloWorldService {
@WebResult(name="String")
@WebMethod
public String sayHello(@WebParam(name = "id") int id);
}
HelloWorldServiceImpl.java代碼如下
package com.mycompany.service;
import javax.annotation.Resource;
import javax.jws.WebService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mycompany.dao.HelloWorldDao;
@Service
@WebService(serviceName="HelloWorldService",targetNamespace="http://service.mycompany.com/",endpointInterface="com.mycompany.service.HelloWorldService")
public class HelloWorldServiceImpl implements HelloWorldService {
@Resource
private HelloWorldDao helloWorldDao;
private static Logger logger = Logger.getLogger(HelloWorldServiceImpl.class);
@Override
public String sayHello(int id) {
logger.info("----接口查詢開始----");
String name = helloWorldDao.getName(id);
logger.info("----接口查詢結束----");
return "Hello," + name;
}
}
HelloWorldDao .java代碼如下
package com.mycompany.dao;
public interface HelloWorldDao {
public String getName(int id);
}
hello-mapper.xml代碼如下
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mycompany.dao.HelloWorldDao">
<select id="getName" parameterType="int" resultType="string">
select name from user where id = #{id}
</select>
</mapper>
6.以上全部做完,一個簡單的WebService就算是完成了,我們在test包下建一個測試類TestService.java ,代碼如下
package com.mycompany.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mycompany.service.HelloWorldServiceImpl;
public class TestService {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
HelloWorldServiceImpl helloWorldService = app.getBean(HelloWorldServiceImpl.class);
String name = helloWorldService.sayHello(56040);
System.out.println(name);
}
}
通過運行Main方法可以知道自己寫的接口是否正確。
7.以上都沒有問題就將項目用tomcat啓動,注意在spring配置文件中配置了啓動文本項目的自己電腦的ip和端口,如下
<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
<property name="baseAddress" value="http://10.4.125.84:8099/"/>
</bean>
注意一定是自己電腦的ip,而不是localhost,端口也是沒有被佔用的端口。
8.如果項目順利啓動沒有報錯,就可以在瀏覽器裏輸入地址
http://10.4.125.84:8099/HelloWorldService?wsdl
如果看到如下圖所示
那麼一個WebService項目就完成了
9.關於如何生成客戶端代碼,情況上一篇博客中推薦的第一篇博客。