概述
SpringMVC @initBinder注解实现类型转换
- 背景&问题
- 解决方案
- 代码
- 总结
- 参考文章
背景&问题
在【电销推广录入】和【财务资金指标录入】项目中,前端页面中要提交的表单存在时间字符串(使用了WdatePicker插件,如下图),而JavaBean中的对应字段为Java的Date类型,在这里如果不做转换处理,后台Controller将无法得到被正确封装的JavaBean,自然Controller对应的接口也不会被触发,并且前后端控制台都不会报错。
解决方案
方式一:使用SpringMVC框架提供的 @InitBinder 注解,并配合Controller层的如下代码,可借助SpringMVC完成自动类型转换。
// 将页面传过来的Data字符串转换为Date,并封装进JavaBean
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
方式二:在Controller层手动接收页面表单的时间字符串数据(将需要传入后台的input标签值写在Controller层相应接口的参数列表中),再在代码中作格式转换,然后手动封装到JavaBean中。
下面将以两个不同项目,展示两种方式的区别:
代码
方式一:
jsp页面的表单:
<form id="finFundIdxForm" name="finFundIdxForm" action="">
<ul class="all_list">
<li>
<span class="all_title">查询日期:</span>
<span>
<input type="text" id="queryTime" value="" class="Wdate"
onFocus="WdatePicker({dateFmt:'yyyy-MM-dd'})"
style="width: 120px; margin-top: 5px"/>
</span>
</li>
<li>
<span class="all_title">指标名称: </span>
<select id="idxId" name="idxId" style="width: 120px; margin-top: 5px">
<option value="-1">--请选择--</option>
<c:forEach var="IdxInfo" items="${IdxInfo_list}">
<option value="${IdxInfo.idxId}">${IdxInfo.idxName}</option>
</c:forEach>
</select>
</li>
<li class="m-t10">
<span class="all_title"></span>
<span>
<input id="queryBtn" class="btn_blue m-r15 submitBtn" type="button" value="查 询" name="button" />
<input id="resetBtn" class="btn_gray m-r15" type="reset" value="重 置" name="button" />
</span>
</li>
</ul>
</form>
完整的Controller:
package com.sfpay.console.web.finfundidx;
......
import java.text.SimpleDateFormat;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
......
/**
* 类说明:
* 财务资金指标录入模块Controller层
* @author 80003614
* CreateDate: 2019-2-11
*/
@Controller
@RequestMapping("/financefundindex")
public class FinFundIdxController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private FinFundIdxService finFundIdxService;
// 将页面传过来的Data字符串转换为Date,并封装进JavaBean
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
// 财务资金指标录入模块入口;执行完跳转到jsp页面
@RequestMapping("/toFinFundIdx")
public ModelAndView toFinFundIdx() {
ModelAndView mav = new ModelAndView("finfundidx/finFundIdx");
selectAllIdxInfo(mav);
return mav;
}
// 查询全部指标ID、指标名称
private void selectAllIdxInfo(ModelAndView mav) {
try {
List<FinanceFundIndex> list = finFundIdxService.selectAllIdxInfo();
mav.addObject("IdxInfo_list", list);
} catch (Exception e) {
logger.error("查询全部指标ID、指标名称,后台出错:" + e.getMessage());
}
}
/**
* 查询
*/
@RequestMapping("/select")
@ResponseBody
public PageInfo<FinanceFundIndex> select(FinanceFundIndex finFundIdx, int rows, int page) {
logger.debug("----------------查询----------------");
logger.debug("封装页面查询条件的JavaBean预览:" + finFundIdx.toString());
PageInfo<FinanceFundIndex> pageInfo = null;
try {
int pageNo = page <= 0 ? 1 : page;
int pageSize = rows <= 0 ? 20 : rows;
pageInfo = finFundIdxService.select(pageNo, pageSize, finFundIdx);
logger.debug("----------------查询结束----------------");
} catch (Exception e) {
logger.error("查询出错:" + e.getMessage());
}
return pageInfo;
}
/**
* 根据IdxId查询,弹出"修改"窗口
*/
@RequestMapping(value = "/selectByIdxId", method = RequestMethod.POST)
public ModelAndView selectByIdxId(long idxId) {
ModelAndView mav = new ModelAndView("finfundidx/editFinFundIdx");
logger.debug("----------------根据IdxId查询----------------");
try {
FinanceFundIndex finFundIdx = finFundIdxService.selectByIdxId(idxId);
mav.addObject("finFundIdx_edit", finFundIdx);
logger.debug("----------------离开根据IdxId查询----------------");
} catch (Exception e) {
logger.error("根据IdxId查询,后台出错:" + e.getMessage());
}
return mav;
}
/**
* 更新
*/
@RequestMapping("/editFinFundIdxOk")
@ResponseBody
public JsonMessage editFinFundIdxOk(FinanceFundIndex FinFundIdx) {
logger.debug("---------------进入update----------------");
JsonMessage jsonMessage = new JsonMessage();
try {
finFundIdxService.updateFinFundIdx(FinFundIdx);
jsonMessage.setCode("Y");
jsonMessage.setSuccess("success");
jsonMessage.setMessage("修改成功");
logger.debug("---------------离开update----------------");
} catch (Exception e) {
logger.error("修改财务资金指标出错:" + e.getMessage());
jsonMessage.setCode("N");
jsonMessage.setSuccess("error");
jsonMessage.setMessage("修改财务资金指标出现异常:" + e.getMessage());
}
return jsonMessage;
}
}
方式二:
jsp页面的表单:
<form id="recordForm" name="recordForm" action="">
<ul class="all_list">
<li>
<!-- 开始时间必须小于等于今天且小于等于结束时间 -->
<span class="all_title">开始时间:</span>
<span>
<input type="text" id="start" value="" class="Wdate"
onFocus="WdatePicker({dateFmt:'yyyy-MM-dd',maxDate:'#F{$dp.$D('end')||'%y-%M-%d'}'})"
style="width: 100px; margin-top: 5px"/>
</span>
<!-- 结束时间必须小于等于今天且大于等于开始时间 -->
<span class="all_title">结束时间:</span>
<span>
<input type="text" id="end" value="" class="Wdate"
onFocus="WdatePicker({dateFmt:'yyyy-MM-dd',minDate:'#F{$dp.$D('start')}',maxDate:'%y-%M-%d'})"
style="width: 100px; margin-top: 5px"/>
</span>
</li>
<li>
<span class="all_title">月结号:</span>
<span><input value="" name="vipNo" id="vipNo" autofocus="autofocus"></span>
</li>
<li>
<span class="all_title">产品类型:</span>
<span id="prodType_span" width ='200'>
<input type="radio" name="prodType" value="" checked="checked">全部
<c:forEach var="prodDim" items="${prodDim_list}">
<input type="radio" name="prodType" style="margin-left:15px" value="${prodDim.itmCd}">${prodDim.itmName}
</c:forEach>
</span>
</li>
<li>
<span class="all_title">接通情况:</span>
<span id="connectStatus_span" width ='200'>
<input type="radio" name="connectStatus" value="" checked="checked">全部
<c:forEach var="bizDict" items="${connectStatus_list}">
<input type="radio" name="connectStatus" style="margin-left:15px" value="${bizDict.itmCd}">${bizDict.itmName}
</c:forEach>
</span>
</li>
<li>
<span class="all_title">是否有意向:</span>
<span id="resultCode_span" width ='200'>
<input type="radio" name="resultCode" value="" checked="checked">全部
<input type="radio" name="resultCode" style="margin-left:15px" value="1">是
<input type="radio" name="resultCode" style="margin-left:15px" value="0">否
<input type="radio" name="resultCode" style="margin-left:15px" value="2">意向不明
</span>
</li>
<li class="m-t10">
<span class="all_title"></span>
<span>
<input id="queryBtn" class="btn_blue m-r15 submitBtn" type="button" value="查 询" name="button">
<input id="resetBtn" class="btn_gray m-r15" type="reset" value="重 置" name="button" >
<input id="addBtn" class="btn_blue m-r15" type="button" value="新 增" name="button">
</span>
</li>
</ul>
</form>
完整的Controller:
package com.sfpay.console.web.call;
import java.io.IOException;
......
/**
* 类说明:
* 电销推广录入模块Controller层
* @author 80003614
* CreateDate: 2018-10-22
*/
@Controller
@RequestMapping("/callrecord")
public class CallRecordController {
private static Logger logger = LoggerFactory.getLogger(CallRecordController.class);
@Resource
private CallRecordService callRecordService;
// 电销推广录入系统入口;执行完跳转到操作台jsp页面
@RequestMapping("/toCallRecord")
public ModelAndView toCallRecord() {
ModelAndView mav = new ModelAndView("callrecord/callRecordEntering");
selectAllProdType(mav);
selectAllConnectStatus(mav);
return mav;
}
// 查询产品类型
private void selectAllProdType(ModelAndView mav) {
try {
List<DdItm> list = callRecordService.selectProdType();
mav.addObject("prodDim_list", list);
} catch (Exception e) {
logger.error("查询产品类型,后台出错:" + e.getMessage());
}
}
// 查询接通情况类型
private void selectAllConnectStatus(ModelAndView mav) {
try {
List<DdItm> list = callRecordService.selectConnectStatus();
mav.addObject("connectStatus_list", list);
} catch (Exception e) {
logger.error("查询接通情况类型,后台出错:" + e.getMessage());
}
}
// 获取当前登录的员工工号
private String getLoginUser() {
User user = (User) SecurityManager.getSessionAttribute("SESSION_USER");
if (user == null) {
try {
throw new Exception("获取员工session异常");
} catch (Exception e) {
e.printStackTrace();
}
}
return user.getUserName();
}
/**
* 查询
*/
@RequestMapping("/select")
@ResponseBody
public PageInfo<CallRecordLog> select(CallRecordLog record, String start, String end, int rows, int page) {
logger.debug("----------------查询----------------");
PageInfo<CallRecordLog> pageInfo = null;
try {
int pageNo = page <= 0 ? 1 : page;
int pageSize = rows <= 0 ? 20 : rows;
record.setCreateId(this.getLoginUser());
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
if ("" == start || start.equals("")) {
// do nothing
} else {
record.setStartTime(sf.parse(start));
}
if ("" == end || end.equals("")) {
// do nothing
} else {
record.setEndTime(sf.parse(end));
}
pageInfo = callRecordService.select(pageNo, pageSize, record);
logger.debug("----------------查询结束----------------");
} catch (Exception e) {
logger.error("查询出错:" + e.getMessage());
}
return pageInfo;
}
// 弹出"新增"窗口,查询产品类型表
@RequestMapping(value = "/addRecord", method = RequestMethod.GET)
public ModelAndView addRecord() {
ModelAndView mav = new ModelAndView("callrecord/addRecord");
selectAllProdType(mav);
selectAllConnectStatus(mav);
return mav;
}
/**
* 新增
*/
@RequestMapping("/addRecOk")
@ResponseBody
public JsonMessage addRecOk(CallRecordLog record, String enteringTime_add) {
logger.debug("---------------进入add----------------");
JsonMessage jsonMessage = new JsonMessage();
try {
if ("" == enteringTime_add || enteringTime_add.equals("")) {
// do nothing
} else {
Timestamp ts = new Timestamp(System.currentTimeMillis());
ts = Timestamp.valueOf(enteringTime_add);
record.setEnteringTime(ts);
}
record.setCreateId(this.getLoginUser());
callRecordService.insertRecord(record);
jsonMessage.setCode("Y");
jsonMessage.setSuccess("success");
jsonMessage.setMessage("新增成功");
logger.debug("---------------离开add----------------");
} catch (Exception e) {
logger.error("新增电销记录出错:" + e.getMessage());
jsonMessage.setCode("N");
jsonMessage.setSuccess("error");
jsonMessage.setMessage("新增电销记录出现异常");
}
return jsonMessage;
}
/**
* 根据ID查询,弹出"修改"窗口
*/
@RequestMapping(value = "/selectById", method = RequestMethod.POST)
public ModelAndView selectById(long recordId) {
ModelAndView mav = new ModelAndView("callrecord/editRecord");
selectAllProdType(mav);
selectAllConnectStatus(mav);
logger.debug("----------------根据ID查询----------------");
try {
CallRecordLog record = callRecordService.selectById(recordId);
mav.addObject("record_edit", record);
if (record.getEnteringTime() == null) {
logger.error("外呼时间为空");
} else {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String enteringTime = sf.format(record.getEnteringTime());
mav.addObject("enteringTime_edit", enteringTime);
}
logger.debug("----------------离开根据ID查询----------------");
} catch (Exception e) {
logger.error("根据ID查询,后台出错:" + e.getMessage());
}
return mav;
}
/**
* 更新
*/
@RequestMapping("/editRecOk")
@ResponseBody
public JsonMessage updateRecOk(CallRecordLog record, String enteringTime_edit) {
logger.debug("---------------进入update----------------");
JsonMessage jsonMessage = new JsonMessage();
try {
if ("" == enteringTime_edit || enteringTime_edit.equals("")) {
// do nothing
} else {
Timestamp ts = new Timestamp(System.currentTimeMillis());
ts = Timestamp.valueOf(enteringTime_edit);
record.setEnteringTime(ts);
}
callRecordService.updateRecord(record);
jsonMessage.setCode("Y");
jsonMessage.setSuccess("success");
jsonMessage.setMessage("修改成功");
logger.debug("---------------离开update----------------");
} catch (Exception e) {
logger.error("修改电销记录出错:" + e.getMessage());
jsonMessage.setCode("N");
jsonMessage.setSuccess("error");
jsonMessage.setMessage("修改电销记录出现异常");
}
return jsonMessage;
}
/**
* 删除
*/
@RequestMapping(value = "/doDel", method = RequestMethod.POST)
@ResponseBody
public JsonMessage doDel(long recordId) throws IOException {
logger.debug("---------------进入delete----------------");
JsonMessage jsonMessage = new JsonMessage();
try {
callRecordService.deleteByPrimaryKey(recordId);
jsonMessage.setCode("Y");
jsonMessage.setSuccess("success");
jsonMessage.setMessage("删除电销记录成功");
logger.debug("---------------离开delete----------------");
} catch (Exception e) {
jsonMessage.setCode("N");
jsonMessage.setSuccess("error");
jsonMessage.setMessage("删除记录出现异常");
}
return jsonMessage;
}
/**
* 统计
*/
@RequestMapping(value = "/selectCount", method = RequestMethod.POST)
@ResponseBody
public CallRecordLog selectCount(CallRecordLog record, String start, String end) {
logger.debug("----------------统计----------------");
try {
record.setCreateId(this.getLoginUser());
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
if ("" == start || start.equals("")) {
// do nothing
} else {
record.setStartTime(sf.parse(start));
}
if ("" == end || end.equals("")) {
// do nothing
} else {
record.setEndTime(sf.parse(end));
}
record = callRecordService.selectCount(record);
logger.debug("----------------离开统计----------------");
} catch (Exception e) {
logger.error("统计出错:" + e.getMessage());
}
return record;
}
}
总结
通过上述两种实现方式的对比可以发现,方式一(使用 @InitBinder 注解)的代码更加简洁、轻便和易读。
方式二(手动封装)虽然可以达到同样的效果,但实现过程较为繁琐、代码冗长还没有技术含量。因此在涉及前后端数据格式转换问题时,建议使用SpringMVC提供的方式。
参考文章
链接:
@initBinder
SpringMVC注解@initbinder解决类型转换问题
springMVC使用@InitBinder注解把字符串转化为Date类型
SpringMVC中利用@InitBinder来对页面数据进行解析绑定
最后
以上就是动听翅膀为你收集整理的SpringMVC @initBinder注解实现类型转换的全部内容,希望文章能够帮你解决SpringMVC @initBinder注解实现类型转换所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复