DWR框架,古老而显得有些被人遗忘。不过近期维护了一个小旧项目,碰到了DWR框架。期初接手很是不爽。一开始看不懂,更不想理会,但是搞了一段时间还是接受了。现在简单的介绍一下吧。
首先截图以下使用的jar包吧
其次,项目结构以及xml设置(非maven项目)
其次,再写一下application.xml以及web.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:aop="http://www.springframework.org/schema/aop"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jms="http://www.springframework.org/schema/jms" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:oxm="http://www.springframework.org/schema/oxm"
xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.1.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"
default-autowire="byName" default-lazy-init="false">
<!-- 定义受环境影响易变的变量 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<!-- 标准配置 -->
<value>/WEB-INF/config/application.properties</value>
<value>/WEB-INF/config/quartz.properties</value>
<value>/WEB-INF/config/log4j.properties</value>
</list>
</property>
</bean>
<!-- DWR配置 -->
<dwr:configuration />
<dwr:annotation-scan base-package="com.onest.bcms"
scanDataTransferObject="true" scanRemoteProxy="true" />
<dwr:annotation-config id="annotationConfig" />
<!-- 使用annotation 自动注册bean,并保证@Required,@Autowired的属性被注入 -->
<context:annotation-config />
<context:component-scan base-package="com.onest.bcms">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- Connection Pooling Info -->
<property name="maxIdle" value="${dbcp.maxIdle}" />
<property name="maxActive" value="${dbcp.maxActive}" />
<property name="defaultAutoCommit" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="3600000" />
<property name="minEvictableIdleTimeMillis" value="3600000" />
</bean>
<!-- JDBC Template配置 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<aop:aspectj-autoproxy />
<!--事务 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- excel -->
<!-- <bean id="billListExcelView" class="com.onest.bcms.util.BillListExcelView"></bean> -->
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>bankcardmanagementsystem</display-name>
<welcome-file-list>
<welcome-file>jsp/index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/applicationContext.xml
/WEB-INF/config/application-quartz.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dwr</servlet-name>
<servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
<!-- 开发环境中可以打开debug,生产环境中一般要关闭 -->
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<!-- 指定最大上传为10M -->
<init-param>
<param-name>fileUploadMaxBytes</param-name>
<param-value>104857600</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<!-- 验证码 -->
<servlet>
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
<init-param>
<param-name>kaptcha.image.width</param-name>
<param-value>80</param-value>
</init-param>
<init-param>
<param-name> kaptcha.textproducer.font.names </param-name>
<param-value>楷体</param-value>
</init-param>
<init-param>
<param-name>kaptcha.image.height</param-name>
<param-value>40</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.char.string</param-name>
<param-value>acdefghjkmnprstuvwxy34578</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.char.length</param-name>
<param-value>4</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.font.size</param-name>
<param-value>25</param-value>
</init-param>
<init-param>
<param-name>kaptcha.obscurificator.impl</param-name>
<param-value>com.google.code.kaptcha.impl.ShadowGimpy</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.font.names</param-name>
<param-value>Arial</param-value>
</init-param>
<init-param>
<param-name>kaptcha.noise.impl</param-name>
<param-value>com.google.code.kaptcha.impl.NoNoise </param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
</web-app>
最后啊简单的写一下里面的流程代码如下:
一、实体类要打注解@DataTransferObject
@DataTransferObject
public class Fee implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 唯一标识符
* */
private Long fmId;
二、DAO层最好写个基础DAO,其他的没什么
/**
* 费用管理模板四
* @author SHUN
*/
public interface Fee4Dao extends IBaseDao<Fee>{
/**
* 根据公司的Id查询该公司的单笔收费标准
* @param Integer
* @return Fee
*/
Fee4 queryByorganId(Long organId, String dateTime);
/**
* Description: 基础Dao接口 <br />
* Project: bcms <br />
* ClassName: IBaseDao <br />
* Copyright: Copyright (c) 2013 onest<br />
* @author bushy
* @version 1.0 2013-2-28下午3:46:55
*/
public interface IBaseDao<T> {
/**
* 根据查询条件查询列表
* @author bushy
* @createDate 2013-2-28
* @param t
* @return
*/
public List<T> queryListByCondition(T t);
/**
* 根据主键查询一条记录
* @author bushy
* @createDate 2013-2-28
* @param id
* @return
*/
public T queryOneByPK(long id);
/**
* 根据主键删除一条记录
* @author bushy
* @createDate 2013-2-28
* @param id
* @return
*/
public int deleteOneByPK(long id);
}
三、DAO的实现类所用为Jdbctemplate的,在这里简单的写一下增删改的语句
首先建立一个BaseDao让后期使用Jdbctemplate更方面
@Repository
public abstract class BaseDao {
@Autowired
protected JdbcTemplate jdbcTemplate;
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
public boolean insert(Fee fee) {
//增加
String sql = "insert into t_feemanage (feeStandard,startTime,generateDate,modifyDate,organId) values(?,?,?,?,?)";
int result = getJdbcTemplate().update(sql, fee.getFeeStandard(),fee.getStartTime(),new Date(System.currentTimeMillis()),new Date(System.currentTimeMillis()),fee.getOrganId());
if(result > 0){
return true;
}else{
return false;
}
}
@Override
public List<Fee> queryAll() {
// 查询
String sql = "select f.*,o.organid, o.organname from t_feemanage f left outer join T_ORGANIZE o on f.organid=o.organid order by f.fmid";
List<Fee4> list = getJdbcTemplate().query(sql, new FeeMapper());
return list;
}
这里是feeMapper绑定,
protected class FeeMapper implements RowMapper<Fee> {
public Fee mapRow(ResultSet rs, int rowNum) throws SQLException {
Fee fee = new Fee();
fee.setFmId(rs.getLong("fmid"));
fee.setFeeStandard(rs.getDouble("feestandard"));
fee.setGenerateDate(rs.getDate("generatedate"));
fee.setModifyDate(rs.getDate("modifydate"));
fee.setOrganId(rs.getLong("organid"));
fee.setOrganName(rs.getString("organName"));
fee.setStartTime(rs.getString("starttime"));
return fee;
}
}
再写一个批量插入的写法
@Repository
public class BankBillDao extends BaseDao implements IBankBillDao {
/**
* 批量插入银行对帐单
* @author bushy
* @createDate 2013-3-20
* @param bbList
* @return
*/
public int[] batchAddBankBill(final List<BankBill> bbList){
StringBuilder sb = new StringBuilder();
sb.append("insert into t_banktest(merchantNo,merchant) values(?,?)");
return jdbcTemplate.batchUpdate(sb.toString(), new BatchPreparedStatementSetter(){
public int getBatchSize() {
return bbList.size();
}
public void setValues(PreparedStatement psmt, int i)
throws SQLException {
BankBill bankBill = bbList.get(i);
psmt.setString(1, bankBill.getMerchantNo());
psmt.setString(2, bankBill.getMerchant());
}
});
}
四、重点来了,写接口的实现类时一定要有返回的值,也就是不要写void返回如下,还有两个Remote注解一定要写上哦
/**
* @author SHUN
* @since 2018/2/6
*/
@Service
@RemoteProxy(name = "FeeService", creator = SpringCreator.class)
public class Fee4ServiceImpl implements Fee4Service {
@Resource
private FeeDao feeDao;
@Override
@RemoteMethod
@Transactional
public boolean removeFee(Integer[] fmIds) {
// TODO Auto-generated method stub
int result = 0;
for (int i = 0; i < fmIds.length; i++) {
result = fee4Dao.deleteOneByPK(fmIds[i]);
}
if (result > 0)
return true;
else
return false;
}
五、再写一下,与前台交互的js文件,那如果说为啥不用controller,那么DWR里面用不着这个服务实现直接js前端。后台已经异步封装好了,js代码直接调用java代码
$(document)
.ready(
function() {
var ctx = $('#ctx').attr("value");
var cardfiles = dwr.util.getValue("cardfile");//这是dwr包提供的util.js文件里面的方法
var mobilefiles = dwr.util.getValue("mobilefile");//这是dwr包提供的util.js文件里面的方法
$('#returnButton').click(function() {
self.location = ctx + '/jsp/financial/bankfinancialmanage.jsp';
});
$('#card').click(
function() {
Fee5Service
.parseCard(cardfiles,
{
callback : function(
data) {
if (data) {
confirmParseDialogSuccess(
'文件解析成功,将跳入银联对账汇总页面',
"成功提示",
300,
50);
self.location = ctx + '/jsp/financial/bankfinancialmanage.jsp';
} else {
confirmParseDialogfail(
'文件已经解析过,或存在其他问题,请验证再上传',
"失败提示",
300,
50);
$("#cardfile").val("");
}
},
timeout : 5000,
errorHandler : function(
message) {
alert("Oops: "
+ message);
}
});
});
});
六、接下来呢就是前端的的加载以及弹出交互框,值得说的是,最好将加载之后的余下方法写入到另外的js。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>费用模版4管理</title>
<%@include file="/jsp/common/taglib.jsp"%>
<%@include file="/jsp/common/jslib.jsp"%>
<link href="${ctx}/css/frame.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="${ctx}/dwr/interface/Fee5Service.js"></script>
<script type="text/javascript" src="${ctx }/js/parsecard.js"></script>
<script type="text/javascript" src="${ctx }/js/parseDialog.js"></script>
</head>
<body class="frame">
<input type="hidden" id="ctx" name="ctx" value="${ctx}" />
<div class="bt">
<div class="title">
<img src="${ctx}/images/pic.gif" align="absmiddle"> 文件上传 -
月收单报表上传
</div>
<%-- <c:if test="${!viewFlag}">
<input type="button" class="addbut" id="addFileData" />
</c:if> --%>
<div class="tj">
*注意事项:1、不要将同一文件重复提交多次
:2、上传不同文件最好刷新一遍网页再上传
</div>
</div>
<table width="100%" border="0" cellspacing="0" cellpadding="0"
class="form">
<tr>
<td width="12%" height="40" align="center">
银行卡收单:<input type="file" name="cardfile" id="cardfile"/>
<input type="button" class="but" value="提 交" id="card">
<input name="input" type="button" id="returnButton" class="but" value="返 回">
</td>
</tr>
</table>
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="form">
<tr>
<td width="" height="40" align="center">
移动支付收单:<input type="file" name="mobilefile" id="mobilefile"/>
<input type="button" class="but" value="提 交" id="mobile">
<input name="input" type="button" id="returnButton" class="but" value="返 回">
</td>
</tr>
</table>
<div class="tj">
</div>
<div class="tablebottom"></div>
</body>
</html>
function confirmParseDialogfail(msg, width, height) {
var w = width || 300;
var h = height || 200;
var confirmdiv = $("<div title='解析提醒'></div>").appendTo($("BODY"));
confirmdiv.text(msg);
confirmdiv.dialog({
autoOpen : true,
height : h,
width : w,
modal : true,
resizable : false,
bgiframe : true,
close : function(evt, ui) {
confirmdiv.dialog("destroy");
confirmdiv.html("").remove();
},
buttons : {
"确定" : function() {
confirmdiv.dialog("close");
}
}
});
}
七、最后再写一下上传下载的java代码,相对的javajar包按照提示下载即可
/**
*
* @author SHUN
* @since 2018/2/6
*/
@Service
@RemoteProxy(name = "Fee5Service", creator = SpringCreator.class)
public class Fee5ServiceImpl implements Fee5Service {
@Resource
private IBankBillDao bankBillDao;
List<BankBill> bbList = new ArrayList<BankBill>();
ParseMFile parse = new ParseMFile();
List<String> repeatedDataTime = null;
// @Transactional
@Override
@RemoteMethod
public Boolean parseCard(InputStream fileStream) {
try {
bbList = parse.analysizeBankExcel(fileStream);
repeatedDataTime = new ArrayList<String>();
for (BankBill bankBill : bbList) {
boolean existence = bankBillDao.queryExist(bankBill);
if (existence) {
// System.out.println("交易时间:"+bankBill.getTranDateTime()+"条记录已被重复插入,请验证该记录");
repeatedDataTime.add(bankBill.getTranDateTime());
}
}
if (repeatedDataTime.size()>0) {
return false;
} else {
int[] i = bankBillDao.batchAddBankBill(bbList);
System.out.println("成功添加:"+i.length+"条记录");
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
@RemoteMethod
public FileTransfer excelView(String start, String end, Long organId) {
String[] headers = new String[] { "回单编号", "一级公司名称", "二级公司名称", "三级公司名称",
"交易日期", "生成时间", "终端号", "卡号", "发卡行", "交易金额", "清算金额 手续费", "参考号",
"跟踪号", "交易类型", "交易渠道" };
String[] fileds = new String[] { "lsNo", "oneOrganName",
"twoOrganName", "threeOrganName", "cleardate", "createDate",
"terminalNo", "cardNo", "cardBank", "tranAmount", "fee",
"refNo", "serialNo", "tradeType", "tradeChannel" };
if (organId == null) {
return BillCreateExcelView.downloadExcel(headers, fileds,
"集团名称:XXXXXXX有限公司 起止日期:"
+ start + "~" + end,
searchAllDetail(start, end, null, null), start + "到" + end
+ "对账单");
} else {
return BillCreateExcelView.downloadExcel(headers, fileds,
"集团名称:XXXXXXX有限公司 起止日期:"
+ start + "~" + end,
searchDetailByOrganId(start, end, organId, null, null),
start + "到" + end + "对账单");
}
}
至此,也就差不多。综合来讲呢,用到最后呢感觉只要注意其中一点细节,用起来还是很顺畅的。万变不离其宗,依托参考文档以及汲取前辈经验来写,应该会很顺利。也预祝自己和你们在编程路上快乐出发,幸福到达。