视频发布在youtube上面了 https://youtu.be/EaT-EpD-1fM 优酷上面的链接 http://v.youku.com/v_show/id_XMjgwODcyNzg5Ng==.html?f=49760672
接着007的项目操作。
数据库的主键改为自增,主键的相关处理这里不是重点。
HTTP POST 请求/users 带着一个user对象JSON格式创建一个新的user
显示添加页面Get请求 Uri: user提交添加信息POST请求 Uri: userbody里面添加addUser对话框
... <!-- create user dialog --> <div id="dlg" class="easyui-dialog" data-options="iconCls:'icon-save',resizable:true,modal:true" style="width: 400px; height: 280px; padding: 10px 20px" closed="true" buttons="#dlg-buttons"> <div class="ftitle">用户信息</div> <form id="fm" method="post"> <div class="fitem"> <label for="name">用户名:</label> <input name="name" class="easyui-validatebox" type="text" data-options="required:true"> </div> <div class="fitem"> <label for="age">年 龄:</label> <input name="age" class="easyui-numberbox" type="text" data-options="required:true,validType:'number'"> </div> <div class="fitem"> <label for="gender">性 别:</label> <input id="state1" name="gender" value="男" type="radio" checked="true" />男 <input id="state2" name="gender" value="女" type="radio" />女 </div> <div class="fitem"> <label for="email">Email:</label> <input name="email" class="easyui-validatebox" type="text" data-options="required:true,validType:'email'"> </div> <div class="fitem"> <label for="teacherId">教 师:</label> <input id="cc" class="easyui-combobox" name="teacherId" data-options="valueField:'id',textField:'name',panelHeight:80,editable:false,method:'get',url:'${pageContext.request.contextPath}/getTeacherComboData'"> </div> </form> </div> <div id="dlg-buttons"> <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-ok'" onclick="save()">Save</a> <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" onclick="javascript:$('#dlg').dialog('close')">Cancel</a> </div> </body>然后添加ITeacherService接口,给Controller使用。
public Teacher getTeacherById(long id); public List<Teacher> getTeachers();修改teacherMapper添加Dao操作
/** * Select all teachers * @return */ List<Teacher> selectTeachers();修改TeacherMapper.xml增加getTeachers映射
<select id="selectTeachers" resultMap="BaseResultMap"> select * from teacher </select>添加实现类ITeacherServiceImpl
@Service("teacherService") @Transactional public class ITeacherServiceImpl implements ITeacherService { @Autowired TeacherMapper teacherMapper; @Override public List<Teacher> getTeachers() { return teacherMapper.selectTeachers(); } @Override public Teacher getTeacherById(long id) { return teacherMapper.selectByPrimaryKey(id); } }添加TeacherController实现easyUI需要的数据接口
@Controller public class TeacherController { private static final Logger logger = LogManager.getLogger(TeacherController.class.getName()); @Autowired ITeacherService teacherService; @ResponseBody @RequestMapping(value = "/getTeacherComboData", method = RequestMethod.GET) public List<Teacher> teachers(HttpServletRequest request, HttpServletResponse response) { List<Teacher> teachers = teacherService.getTeachers(); logger.info("getUsers api jsonObj:" + JSON.toJSONString(teachers)); return teachers; } }/src/main/webapp/commons/js目录下新建commons.js获取项目路径,网上找的代码,注释信息保留了。
/*! * imalex@163.com - v0.1 (2015-08-29 18:00:00 +0800) * Copyright 2015 */ var ctx=getBasePath(); function getBasePath(){ var obj=window.location; var contextPath=obj.pathname.split("/")[1]; var basePath=obj.protocol+"//"+obj.host+"/"+contextPath; return basePath; } // 格式化日期 Date.prototype.Format = function (fmt) { var o = { "y+": this.getFullYear(), "M+": this.getMonth() + 1, // 月份 "d+": this.getDate(), // 日 "h+": this.getHours(), // 小时 "m+": this.getMinutes(), // 分 "s+": this.getSeconds(), // 秒 "q+": Math.floor((this.getMonth() + 3) / 3), // 季度 "S+": this.getMilliseconds() // 毫秒 }; for (var k in o) { if (new RegExp("(" + k + ")").test(fmt)){ if(k == "y+"){ fmt = fmt.replace(RegExp.$1, ("" + o[k]).substr(4 - RegExp.$1.length)); } else if(k=="S+"){ var lens = RegExp.$1.length; lens = lens==1?3:lens; fmt = fmt.replace(RegExp.$1, ("00" + o[k]).substr(("" + o[k]).length - 1,lens)); } else{ fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); } } } return fmt; }新建目录/src/main/webapp/commons/js/user 在user目录下新建userOper.js脚本处理增加,删除,修改操作
/*! * imalex@163.com - v0.1 (2015-08-29 18:00:00 +0800) * Copyright 2015 */ $(function() { }); function insert() { $('#dlg').dialog('open').dialog('setTitle', '新建用户'); $('#fm').form('clear'); url = ctx + '/users'; type = insert; } function edit() { var row = $('#dg').datagrid('getSelected'); if (row) { $('#dlg').dialog('open').dialog('setTitle', '编辑用户信息'); $('#fm').form('load', row); //setCheckedValue(document.forms['fm'].elements['gender'], row['gender']); url = 'users/' + row.id; type = edit; } } function save() { $('#fm').form('submit', { url : url, type:type, onSubmit : function(param) { if (type == edit) { //use put param._method ='PUT'; } param.createTime = new Date().Format("yyyy-MM-dd hh:mm:ss"); param.loginTime = param.createTime; var ret = $(this).form('validate'); return ret; }, success : function(result) { var result = eval('(' + result + ')'); if (result.errorMsg) { $.messager.show({ title : 'Error', msg : result.errorMsg }); } else { $('#dlg').dialog('close'); // close the dialog $('#dg').datagrid('reload'); // reload the user data } } }); } function del() { var row = $('#dg').datagrid('getSelected'); if (row) { $.messager.confirm('确认', '请确认删除已选择用户?', function(r) { if (r) { $.post('users/' + row.id, { _method : 'DELETE' }, function(result) { if (result.status != null) { $('#dg').datagrid('reload'); // reload the user data } else { $.messager.show({ // show error message title : 'Error', msg : result.errorMsg }); } }, 'json'); } }); } }新建目录/src/main/webapp/commons/css,下面新建user.css用于格式化新建用户对话框的各个元素
<style type="text/css"> #fm { margin: 0; padding: 10px 30px; } .ftitle { font-size: 14px; font-weight: bold; color: #666; padding: 5px 0; margin-bottom: 10px; border-bottom: 1px solid #ccc; } .fitem { margin-bottom: 5px; } .fitem label { display: inline-block; width: 80px; } </style>引入自定义的脚本和css样式
... <!-- 自定义的js脚本 --> <script type="text/javascript" src="commons/js/commons.js"></script> <script type="text/javascript" src="commons/js/user/userOper.js"></script> <link rel="stylesheet" href="commons/css/user.css"> </head>IUserService和实现类增加插入用户的接口和实现代码
public int insertUser(User usr); @Override public int insertUser(User usr) { return userMapper.insert(usr); }UserController增加POST响应代码处理增加用户操作,这里使用POJO对象绑定请求参数值,spring会按照参数名和属性名自动匹配填充。
@Autowired ITeacherService teacherService; @RequestMapping(value = "/users", method = RequestMethod.POST) @ResponseBody public Object addUsersProc(User user) { // 处理新id生成 // 处理teacher类对象 user.setTeacher(teacherService.getTeacherById(user.getTeacherId())); int iRet = userService.insertUser(user); long newId = user.getId(); Map<String, Object> map = new HashMap<String, Object>(); if (iRet == 0) { logger.info("addUsersProc: " + JSON.toJSON("新建失败:" + JSON.toJSONStringWithDateFormat(user, "yyyy-MM-dd HH:mm:ss"))); map.put("status", "新建失败"); map.put("retCode", -1); } else { logger.info("addUsersProc: " + JSON.toJSON("新建用户:" + JSON.toJSONStringWithDateFormat(user, "yyyy-MM-dd HH:mm:ss"))); map.put("status", "新建成功"); map.put("retCode", 0); } return map; }UserMapper.xml里面insert要添加一些配置,才会返回自增的ID,使用实体类的xx.GetId()来获取。
<insert id="insert" parameterType="com.study.model.User" useGeneratedKeys="true" keyProperty="id"> ...条件表单是字符串类型,实体类里面的日期是Date类型,涉及到了类型转换的处理。否则会遇到spring mvc form提交数据报400错误。 提交form表单报这个错误,有可能是你的controller接收数据类型与前台传递类型不符。例如前台传递String 后台用Date接受,就会报这个错误。
新建一个包com.study.converters 新建一个类DateTimeConverter实现spring的springframework.core.convert接口
@Component public class DateTimeConverter implements Converter<String, Date> { @Override public Date convert(String source) { DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = null; try { date = df.parse(source); } catch (ParseException e) { e.printStackTrace(); } return date; } }配置springmvc.xml使converter生效
<!-- 配置自动扫描的包 --> <context:component-scan base-package="com.study.controller,com.study.service,com.study.converters"></context:component-scan> ... <!-- 对于mvc没有映射过的请求,交给容器默认handler来处理,例如:js,css等静态资源 --> <mvc:default-servlet-handler /> <mvc:annotation-driven conversion-service="conversionService"> ... </mvc:annotation-driven> <!-- 配置转换服务 <mvc:annotation-driven conversion-service="conversionService"> --> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <!-- 自定义的转换类,首字母小写 --> <ref bean="dateTimeConverter" /> </set> </property> </bean>还有关于前台传数据到后台中文的乱码问题需要处理一下,在web.xml文件中添加配置,filter是有顺序的,这个最好放在最前面
<!-- 解决中文乱码问题,将参数编码为utf-8 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>现在执行添加用户,应该能看到记录数有所增加。
HTTP DELETE 请求/users/1 删除id=1的user
添加UserService接口和实现
public int deleteById(String id); @Override public int deleteById(String id) { return userMapper.deleteByPrimaryKey(Long.parseLong(id)); }UserController里面添加响应代码
@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE) @ResponseBody public Object deleteUserProc(@PathVariable("id") String id) { int iRet = userService.deleteById(id); Map<String, Object> map = new HashMap<String, Object>(); if (iRet == 0) { logger.error("deleteUserProc: 删除失败"); map.put("status", "删除失败"); map.put("retCode", -1); } else { logger.info("deleteUserProc: 删除成功"); map.put("status", "删除成功"); map.put("retCode", 0); } return map; }因为HiddenHttpMethodFilter的参数是 public static final String DEFAULT_METHOD_PARAM = “_method”; 所以说要把post请求转换成其他请求,提交的参数名就必须指定_method 而参数值必须是要转换的请求形式,这里是DELETE
/users/1 PUT 更新资源 id=1
修改service增加更新接口
public int updateById(User user); @Override public int updateById(User user) { return userMapper.updateByPrimaryKey(user); }UserController里面增加响应处理
@RequestMapping(value = "/users/{id}", method = RequestMethod.PUT) @ResponseBody public Object updateUserProc(@PathVariable("id") long id, User user) { int iRet = userService.updateById(user); Map<String, Object> map = new HashMap<String, Object>(); if (iRet == 0) { logger.error("updateUserProc: 更新失败"); map.put("status", "更新失败"); map.put("retCode", -1); } else { logger.info("updateUserProc: 更新成功"); map.put("status", "更新成功"); map.put("retCode", 0); } return map; }现在可以操作了。RESTFul风格的CRUD功能基本上就实现完毕了。