读书人

Summercool-Web框架简介 (8)

发布时间: 2012-07-04 19:33:55 作者: rapoo

Summercool-Web框架简介 (八)

?

简介:轻量封装Spring MVC

? ? ? ? ?因为本人在国内最大的电子商务公司工作期间,深感一个好的Web框架可以大大提高工作效率,而一个不好的Web框架,又可以大大的降低开发效率。所以,在根据笔者在从事电子商务开发的这几年中,对各个应用场景而开发的一个轻量封装Spring MVC的一个Web框架。

? ? ? ? ?笔者工作的这几年之中,总结并开发了如下几个框架: summercool(Web框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、summercool-ddl(基于Mybaits的分表分库框架,已经应用国内某移动互联网公司);相继缓存方案、和消息系统解决方案也会慢慢开源。Summercool框架做为笔者的第一个开源框架

?

框架地址:http://summercool.googlecode.com/svn/trunk/summercool-web?

应用地址:http://summercool.googlecode.com/svn/trunk/summercool-petstore?

工具地址:http://summercool.googlecode.com/svn/trunk/summercool-tools

说明:此框架要用到spring-tools文件夹中的security文件夹中的文件,使用此框架的人员请将security文件夹的内容替换到JDK中的security文件夹中

?

一、Spring MVC中批量提交的处理

? ? ? ?1) 比如说我们有这样的一个需求,我们想批量更新一组数据信息,每组数据信息内容都相同;如下图:

Summercool-Web框架简介 (8)

? ? ? 2) 比如说,上面这三行数据全部都是从DB中获取,然后批更更新后再提交到DB并返回到当前页面;但是,在Spring MVC框架中要是想实现这样的功能还是比较容易的,如下:

?

? ? /item/modifyItems.ftl

<!DOCTYPE html><html lang="zh">  <head>    <meta charset="utf-8">    <title>Summercool, Petstore</title>    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta name="description" content="">    <meta name="author" content="">    <!-- Le styles -->    <link href="/css/bootstrap.css" rel="stylesheet">    <style type="text/css">      body {        padding-top: 60px;        padding-bottom: 40px;      }  #tb td ,#tb th{border-top: 0px;  }    </style>    <link href="/css/bootstrap-responsive.css" rel="stylesheet">    <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->    <!--[if lt IE 9]>      <script style="max-width: 100%;height: auto;width: auto\9;" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>    <![endif]-->  </head>  <body>  ${widget("/petstore/widgets/header")}    <div action="/item/modify_items.htm"><@spring.bind "modifyItemsFormBean.*"/>     <table id="tb" name="pets[0].name" value="${modifyItemsFormBean.pets[0].name}"/>     年龄:<input type="text" name="pets[0].age" value="${modifyItemsFormBean.pets[0].age}"/>     ${error(status,"pets[0]")}</td>            <td>说明</td> <tr>            <td name="pets[1].name" value="${modifyItemsFormBean.pets[1].name}"/>     年龄:<input type="text" name="pets[1].age" value="${modifyItemsFormBean.pets[1].age}"/>     ${error(status,"pets[1]")}</td>            <td>说明</td> <tr>            <td name="pets[2].name" value="${modifyItemsFormBean.pets[2].name}"/>     年龄:<input type="text" name="pets[2].age" value="${modifyItemsFormBean.pets[2].age}"/>     ${error(status,"pets[2]")}</td>            <td>说明</td>          </tr>        </tbody>      </table>      <div value="提交" type="reset">取消</button></div>      </form>      <hr>      ${widget("/petstore/widgets/footer")}    </div>  </body></html>

?

? ? /item/ModifyItemsController.java

package org.summercool.platform.web.module.petstore.controllers.item;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.validation.BindException;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.SimpleFormController;import org.summercool.platform.web.module.petstore.formbean.ModifyItemsFormBean;import org.summercool.platform.web.module.petstore.pojo.Pet;@SuppressWarnings("deprecation")public class ModifyItemsController extends SimpleFormController {public ModifyItemsController() {setBindOnNewForm(true);setCommandName("modifyItemsFormBean");setCommandClass(ModifyItemsFormBean.class);setFormView("/petstore/views/item/modifyItems");}@Overrideprotected void onBindOnNewForm(HttpServletRequest request, Object command) throws Exception {ModifyItemsFormBean formBean = (ModifyItemsFormBean) command;//Pet pet1 = new Pet();pet1.setName("王");pet1.setAge("25");Pet pet2 = new Pet();pet2.setName("少");pet2.setAge("26");Pet pet3 = new Pet();pet3.setName("川");pet3.setAge("27");//formBean.getPets().add(pet1);formBean.getPets().add(pet2);formBean.getPets().add(pet3);}@Overrideprotected Map<?, ?> referenceData(HttpServletRequest request) throws Exception {return super.referenceData(request);}@Overrideprotected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors) throws Exception {ModifyItemsFormBean formBean = (ModifyItemsFormBean) command;for (int i = 0; i < formBean.getPets().size(); i++) {Pet pet = formBean.getPets().get(i);if (!"25".equals(pet.getAge())) {errors.reject("pets[" + i + "]", "年龄必须为25!");}}}@Overrideprotected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {return showForm(request, response, errors);}}

? ? ? ?说明:在上面的批量更新代码中,在CommandObject的FromBean中有pets属性,该属性是List类型的,那么在页面中就可以通过循环列表显示,如果想通过批量提交就可以通过pets[0]这样的型式提交(0:代表List中的index)。

?

二、自定义freemarker内置函数的支持

? ? ? ?1) 虽然通过上面的表单批量提交,但是我们还需检验每一行的数据信息,如下:

?

ModifyItemsFormBean formBean = (ModifyItemsFormBean) command;for (int i = 0; i < formBean.getPets().size(); i++) {Pet pet = formBean.getPets().get(i);if (!"25".equals(pet.getAge())) {errors.reject("pets[" + i + "]", "年龄必须为25!");}}

?

? ? ? ? ? ?说明:表单提交后就可以通过formBean中的pets属性来提取表单信息,进一步完成表单信息的校验。

? ? ? ? ? ? ? ? ? ? ?error.reject()函数就可以添加每个pets[i]错误检验信息。

? ? ? ?2) 在页面上,我们需要在每一行显示数据的检验之后的错误信息,如下:

?

${error(status,"pets[0]")}

?

? ? ? ? ? ?说明:error()函数就是freemarker自定义的函数,可以跟据每个“pets[i]”显示具体的错误信息

? ? ? ?3) error()的内置函数,信息如下:

?

package org.summercool.platform.web.module.petstore.config.freemarker;import java.util.ArrayList;import java.util.List;import org.springframework.validation.ObjectError;import org.springframework.web.servlet.support.BindStatus;import freemarker.template.TemplateMethodModelEx;import freemarker.template.TemplateModel;import freemarker.template.TemplateModelException;import freemarker.template.utility.DeepUnwrap;public class FreeMarkerErrorFunction implements TemplateMethodModelEx {public Object exec(@SuppressWarnings("rawtypes") List arguments) throws TemplateModelException {// 解包FreeMarker函数的参数List<Object> args = new ArrayList<Object>();for (Object object : arguments) {args.add((object instanceof TemplateModel) ? DeepUnwrap.unwrap((TemplateModel) object) : object);}// BindStatus bindStatus;String errorCode;//if (args.size() != 2) {throw new TemplateModelException("error()函数只支持参数:(BindStatus status, String errorCode)");}if (!(args.get(0) instanceof BindStatus) || !((args.get(1) instanceof String))) {throw new TemplateModelException("error()函数只支持参数:(BindStatus status, String errorCode)");}//bindStatus = (BindStatus) args.get(0);errorCode = (String) args.get(1);//for (ObjectError error : bindStatus.getErrors().getAllErrors()) {String[] codes = error.getCodes();if (codes == null) { continue; }for (String code : codes) {if (code.equals(errorCode)) {return error.getDefaultMessage();}}}//return null;}}

?

? ? ? ? 说明:上面的freemarker内置函数生效,需要注册到freemarker全局工具类中,如(applicationContext.xml):

?

<!-- Spring MVC页面层FreeMarker的处理类 --><util:map id="uriModuleConstants"><entry><key><value>error</value></key><bean class="org.summercool.platform.web.module.petstore.config.freemarker.FreeMarkerErrorFunction"/></entry></util:map>
?

?

?

?

?

?

?

?

读书人网 >Web前端

热点推荐