最近在一个的三级数据库考试系统采用了分布式架构,需要使用web service来实现客户端的C#与服务器端的java的交互,我依然选择了最近最火的cxf框架
首先是Cxf与spring的集成,在我的前一篇博客中已经说明:
现在我就拿一个其中简单例子来实现下(这里只实现java服务器端的)
首次是Service层:ExamStartService:
package xidian.sl.service.webService;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
@WebService
@SOAPBinding(style = Style.RPC)
//@SOAPBinding(style = Style.RPC)这个必须要加否则在客户端加载服务时会出现参数的错误
public interface ExamStartService {
/*
* 客户端传过来的应该是学生的学号和考试的名字
* **/
public String startExam(@WebParam(name = "stuNum")String stuNum,
@WebParam(name = "examName")String examName, @WebParam(name = "sign")String sign, @WebParam(name = "ipaddr")String ipaddr)throws Exception;
}
service的实现层:ExamStartServiceImpl:
package xidian.sl.service.impl.webService;
import java.util.List;
import java.util.Random;
import javax.jws.WebService;
import xidian.sl.dao.webService.ExamStartDAO;
import xidian.sl.entity.Exam;
import xidian.sl.entity.Examinee;
import xidian.sl.entity.Paper;
import xidian.sl.service.webService.ExamStartService;
import xidian.sl.util.FormatDate;
@WebService(endpointInterface = "xidian.sl.service.webService.ExamStartService")
public class ExamStartServiceImpl implements ExamStartService {
private ExamStartDAO examStartDAO;
public ExamStartDAO getExamStartDAO() {
return examStartDAO;
}
public void setExamStartDAO(ExamStartDAO examStartDAO) {
this.examStartDAO = examStartDAO;
}
/**
* @author shenliang 2011-11-29
* 客户端点击开始考试后的处理(客户端传过来的是考生的学号,和本场考试的考试名)
* 1.###先根据客户端传过来的参数sign{"false","true"},false表示在客户端还没有压缩包的存在,true表示已经有压缩包的存在
* 若为false,则先判断该考生是刚开始考生还是再次的请求(查询该考生表中是否已经存在开始考试的时间),若无,则为第一次考试,
* 将开始考试的时间更新进去,并返回success,若已经有考试开始时间,则表示该考生已更换电脑,
* 则需要将该考生原先的试卷包和考试的剩余时间发送过去,
* 若为true,表示该考试已开始考生并且是有压缩包的,此时服务器端只需要将该考试的剩余时间进行返回即可
* @throws Exception
*
* */
public String startExam(String stuNum, String examName, String sign, String ipaddr) throws Exception {
System.out.println("成功了! "+"学号="+stuNum+" 考试="+examName+" 标记="+sign+" ip="+ipaddr);
//查找该场考试
List<Exam> examList = examStartDAO.getExamList(examName);
//考试的名字必须是唯一的
Exam exam = examList.get(0);
//判断该场考试是否有ip范围的限制
String ipAddr = exam.getExamIpaddr();
if(!"未设定".equals(ipAddr)){
String[] ips = ipAddr.split("-"); //将ip地址切分为开始和结束ip
Boolean boo = isBetween(ipaddr, ips[0], ips[1]);
if(boo == false){
//考试机所属ip不在指定的范围
System.out.println("不合法的ip地址");
return "wrongfulIP";
}else{
System.out.println("合法的ip地址");
}
}
//查找该考生
List<Examinee> examineeList = examStartDAO.getExamineeByNumAndExamName(stuNum, examName);
//该集合中只可能有一条记录
Examinee examinee = examineeList.get(0);
//此处还要判断该考生是否已经完成考试了 防止第二次重复考试
if(!"???".equals(examinee.getExamEndtime())){
return "finished";
}
if("false".equals(sign)){ //false表示客户端还没有压缩包
System.out.println("进入false");
//查询该考生的开始考试时间是否存在
if( !"???".equals(examinee.getExamStartime()) ){ //该考生已经开始考试,但中途更换了电脑
System.out.println("已经开始考试了,但是换机子了");
//更新考生表,将机子的变换加1
examStartDAO.updateChangeComNum(examinee);
//将ip更新进去
examinee.setExamineeIpaddr(ipaddr);
examStartDAO.updateExaminee(examinee);
String examLong = exam.getExamLong(); //获得考试的时长
//则将剩余的时间返回,先计算使用了的时间,返回的是一个字符串,分#秒
String examUserdTime = FormatDate.examRemainTime(examinee.getExamStartime(), FormatDate.getFormateDateAll()); //param:1.考试开始时间,2.现在的时间
String[] splitTime = examUserdTime.split("#");
//这里先忽略秒
String examRemainTime = String.valueOf(Integer.valueOf(examLong) - Integer.valueOf(splitTime[0]));
/**
* 将下载的操作交给客户端处理了,这边只需要传递试卷名参数给客户端即可
* */
//将该考生原先的压缩包再次发送,更加该考生得到该试卷包
//String paperPath = examinee.getPaper().getZipPath()+examinee.getPaper().getZipName();
//调用FileDownload类中的downloadFile()方法
//FileDownload.downloadFile(paperPath);
//返回的 剩余时间#试卷名
StringBuilder str = new StringBuilder(examRemainTime);
str.append("#");
str.append(examinee.getPaper().getZipName());
return str.toString(); //返回考试的剩余时间
}else{
System.out.println("未开始过考试");
//更新ip
examinee.setExamineeIpaddr(ipaddr);
examStartDAO.updateExaminee(examinee);
//得到本场考试的所有试卷编号
List<Integer> paperIdList = examStartDAO.getPaperId(examName);
//产生一个随机编号
Random random = new Random();
int rand = random.nextInt(paperIdList.size()); //利用nextInt(产生0到指定值之间的) 产生随机数
int paperId = paperIdList.get(rand); //list.get()返回列表中指定位置的元素,题目的编号
System.out.println("随机编号:"+ paperId);
//将相应的试卷包的id更新到考生表中
examStartDAO.UpdateExamZipAndStartTime(stuNum, examName, paperId, FormatDate.getFormateDateAll());
//得到试卷,
Paper paper = examStartDAO.getPaperById(paperId);
/**
* 将下载的操作交给客户端处理了,这边只需要传递试卷名参数给客户端即可
* */
//String paperPath = paper.getZipPath()+paper.getZipName(); //获得试卷的地址
//调用FileDownload类中的downloadFile()方法
//FileDownload.downloadFile(paperPath);
//返回的 success#试卷名
StringBuilder str = new StringBuilder("success");
str.append("#");
str.append(paper.getZipName());
return str.toString();
}
}else{
System.out.println("已经开始过考试了,现在重新开始了");
//这里就不需要更新ip
String examLong = exam.getExamLong(); //获得考试的时长
//则将剩余的时间返回,先计算使用了的时间,返回的是一个字符串,分#秒
String examUserdTime = FormatDate.examRemainTime(examinee.getExamStartime(), FormatDate.getFormateDateAll()); //param:1.考试开始时间,2.现在的时间
String[] splitTime = examUserdTime.split("#");
//这里先忽略秒
String examRemainTime = String.valueOf(Integer.valueOf(examLong) - Integer.valueOf(splitTime[0]));
return examRemainTime; //只需返回考试的剩余时间即可
}
}
//判断ip的范围
public static boolean isBetween(String ip, String start, String end){
//注意一下用点切割时要注意转义
String[] ipArray = ip.split("\\.");
String[] startArray = start.split("\\.");
String[] endArray = end.split("\\.");
//以上是将三个ip都以点进行切分
System.out.println(ipArray.length);
if(ipArray.length != 4){
return false;
}
long ipLong=((long)((((Integer.parseInt(ipArray[0])<< 8)+Integer.parseInt(ipArray[1]))<< 8)+
Integer.parseInt(ipArray[2]))<< 8)+Integer.parseInt(ipArray[3]);
long startLong=((long)((((Integer.parseInt(startArray[0])<< 8)+Integer.parseInt(startArray[1]))<< 8)+
Integer.parseInt(startArray[2]))<< 8)+Integer.parseInt(startArray[3]);
long endLong=((long)((((Integer.parseInt(endArray[0])<< 8)+Integer.parseInt(endArray[1]))<< 8)+
Integer.parseInt(endArray[2]))<< 8)+Integer.parseInt(endArray[3]);
return ipLong>= startLong&& ipLong<= endLong;
}
}
这样就初步实现了客户端,然后根据配置文件中配置的方法,客户端就能进行接口的调用了