`
dragonsoar
  • 浏览: 205688 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

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) 比如说我们有这样的一个需求,我们想批量更新一组数据信息,每组数据信息内容都相同;如下图:

      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 src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->

  </head>

  <body>
  	${widget("/petstore/widgets/header")}
    <div class="container">
    
	<form method="post" action="/item/modify_items.htm">
	<@spring.bind "modifyItemsFormBean.*"/>
     <table id="tb" class="table table-striped">
        <tbody>
		  <tr>
            <td class="span1"><img src="/images/tb_pet_1.jpg"/></td>
            <td class="span2"><a href="/item/1.htm">兔子1</a></td>
			<td class="span10">
				名字:<input type="text" name="pets[0].name" value="${modifyItemsFormBean.pets[0].name}"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
				年龄:<input type="text" name="pets[0].age" value="${modifyItemsFormBean.pets[0].age}"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
				${error(status,"pets[0]")}
			</td>
            <td>说明</td>
			 <tr>
            <td class="span1"><img src="/images/tb_pet_2.jpg"/></td>
            <td class="span2"><a href="/item/1.htm">兔子2</a></td>
			<td class="span10">
				名字:<input type="text" name="pets[1].name" value="${modifyItemsFormBean.pets[1].name}"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
				年龄:<input type="text" name="pets[1].age" value="${modifyItemsFormBean.pets[1].age}"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
				${error(status,"pets[1]")}
			</td>
            <td>说明</td>
			 <tr>
            <td class="span1"><img src="/images/tb_pet_3.jpg"/></td>
            <td class="span2"><a href="/item/1.htm">小狗1</a></td>
			<td class="span10">
				名字:<input type="text" name="pets[2].name" value="${modifyItemsFormBean.pets[2].name}"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
				年龄:<input type="text" name="pets[2].age" value="${modifyItemsFormBean.pets[2].age}"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
				${error(status,"pets[2]")}
			</td>
            <td>说明</td>
          </tr>
        </tbody>
      </table>
      		<div class="actions">
				<input type="submit" value="提交" class="btn">&nbsp;<button class="btn" 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");
	}

	@Override
	protected 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);
	}

	@Override
	protected Map<?, ?> referenceData(HttpServletRequest request) throws Exception {
		return super.referenceData(request);
	}

	@Override
	protected 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!");
			}
		}
	}

	@Override
	protected 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>

 

 

 

 

 

 

 

 

  • 大小: 33.4 KB
分享到:
评论
6 楼 dragonsoar 2013-01-30  
Sunny_kaka 写道

谢谢支持
5 楼 Sunny_kaka 2013-01-30  
4 楼 dragonsoar 2012-11-01  
最近有点忙啊,在弄一个内部项目,打算创业中,项目是都弄完了,不好意思了各位。
3 楼 liliang_xf 2012-10-30  
亲, 都10月份了, 还没看到其他的开源啊
2 楼 dragonsoar 2012-08-17  
m33707 写道
summercool-ddl框架什么时候开源?很想学习一下

不好意思,最近有点忙,尽快在一周以内,请关注
1 楼 m33707 2012-08-17  
summercool-ddl框架什么时候开源?很想学习一下

相关推荐

    summercool-hsf:自动从code.google.compsummercool-hsf导出

    笔者工作的这几年之中,总结并开发了如下几个框架: summercool(Web 框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、 summercool-...

    summercool-ddl:自动从code.google.compsummercool-ddl导出

    summercool-ddl Automatically exported from code.google.com/p/summercool-ddl 学习了解使用!

    summercool-ddl:从 code.google.compsummercool-ddl 自动导出

    《Summercool-DDL:基于MyBatis的分库分表框架详解》 在现代的互联网应用中,随着数据量的快速增长,单表存储的数据量往往容易达到瓶颈,从而影响系统的性能和稳定性。为了解决这一问题,分布式数据库和分库分表...

    summercool-hsf:从 code.google.compsummercool-hsf 自动导出

    summercool-hsf Automatically exported from code.google.com/p/summercool-hsf 1.目前为止性能最高的RPC远程通讯框架 2.也可以做为手机长连接的Server,经测试已经达到了50W以上的性能长连接 (需调整linux内核...

    summercool:从 code.google.compsummercool 自动导出

    笔者工作的这几年之中,总结并开发了如下几个框架: summercool( Web框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、summercool-...

    Ibatis之分表分库解决方案

    在实际项目中,`summercool-ddl`可能是一个包含数据库创建脚本的文件,用于在实施分库分表前准备数据库结构。这些脚本可能包含了创建分片表的DDL语句,以及可能的视图和索引,以优化查询性能。 总之,Ibatis的分库...

Global site tag (gtag.js) - Google Analytics