简介:轻量封装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}"/> 年龄:<input type="text" name="pets[0].age" value="${modifyItemsFormBean.pets[0].age}"/> ${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}"/> 年龄:<input type="text" name="pets[1].age" value="${modifyItemsFormBean.pets[1].age}"/> ${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}"/> 年龄:<input type="text" name="pets[2].age" value="${modifyItemsFormBean.pets[2].age}"/> ${error(status,"pets[2]")} </td> <td>说明</td> </tr> </tbody> </table> <div class="actions"> <input type="submit" value="提交" class="btn"> <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>
相关推荐
笔者工作的这几年之中,总结并开发了如下几个框架: summercool(Web 框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、 summercool-...
summercool-hsf Automatically exported from code.google.com/p/summercool-hsf 1.目前为止性能最高的RPC远程通讯框架 2....笔者还开发了web层的框架,也在国内最大的电子商务公司使用,平稳运行两年时间: 地址:
笔者工作的这几年之中,总结并开发了如下几个框架: summercool( Web框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、summercool-...
dawe_01_1108
主要功能: wordpress插件主题系列支持自动采集并发布。 主要采集: 福缘,中创,冒泡 自动采集各大项目网进行整合发布到自己个人网站 插件话更新,减少网络请求,提升稳定性 代码完美开源 傻瓜式操作,一次设置永久使用
测试课本程序运行 修改main.cpp文件 原main.cpp文件内容: #include "OpenCV_example.hpp" #include <iostream> int main() { return 0; } 运行一个程序案例: 假设要运行课本案例的Logo.cpp,在main.cpp文件的main函数里写上一行:run_logo(); 设置运行参数(run>>Edit Configurations),讲working directory设置为当前工程的路径
【框架完整】毕业答辩PPT模板.pptx
内容概要:本文详细介绍了三种方法来应对DeepSeek服务器繁忙问题,着重阐述了如何进行DeepSeek的本地部署,包括详细的硬件和软件环境配置建议,特别是针对不同规模参数模型的具体配置需求,同时提供了简化的部署指南。通过本地部署可以有效缓解因服务器繁忙带来的使用不便问题,同时增强数据的安全性和稳定性。此外,还讨论了一些潜在限制,如内容更新滞后和UI界面美观度问题。 适合人群:适用于希望提高使用效率和保障数据安全的技术人员或研究团队,尤其是正在面临DeepSeek云服务平台拥堵问题的人群。 使用场景及目标:为用户提供了一套全面且灵活的解决方案,使其能够在不受限于互联网的情况下独立开展深度学习相关的工作或实验;旨在帮助用户体验更快的数据处理速度,获得更加稳定可靠的服务体验。 阅读建议:为了更好地理解和实施文中提及的各项操作,请确保熟悉所在的操作系统环境,并按步骤执行每个环节,尤其是对硬件设备的选择和驱动程序的正确安装保持关注。对于初次接触此类项目的人来说,可以先从简单的轻量级配置入手逐步过渡到更为复杂的大型配置上。
dawe_3cd_02_0718
基于COMSOL的非饱和裂隙土降雨入渗特性研究:三维基质模型与VG、Brooks-Corey模型的应用分析,基于COMSOL的非饱和裂隙土降雨入渗特性研究:三维基质模型与VG、Brooks-Corey模型的应用分析,comsol非饱和裂隙土降雨入渗研究,复现lunwen(侯晓萍,樊恒辉.基于COMSOL Multiphysics的非饱和裂隙土降雨入渗特性研究[J].岩土力学,2022,43(02):563-572.),建立三维基质—裂隙土柱模型,使用“空气单元”描述坡面积水水头。 使用VG模型和Brooks-Corey模型分别描述土基质和裂隙的非饱和特性,下图为0-5天内压力水头变化以及降雨断面入渗率以及参考文献对比) ,关键词: comsol; 非饱和裂隙土; 降雨入渗研究; 三维基质-裂隙土柱模型; 空气单元描述坡面积水水头; VG模型; Brooks-Corey模型; 压力水头变化; 降雨断面入渗率; 参考文献对比。,COMSOL模型下裂隙土渗透研究:雨季三维模拟与对比分析
diminico_01_0909
anslow_04_0909
Comsol 6.2版流固耦合注浆及冒浆解析:以达西定律与固体力学模块为核心,实现渗流场与结构场流固耦合方程的嵌入学习案例。附赠参考论文与流固耦合视频教程。,基于Comsol流固耦合理论的注浆过程与冒浆现象分析(6.2版)-深入探讨达西定律模块与固体力学模块的实践应用,Comsol流固耦合注浆及冒浆分析(6.2版本) 采用其中达西定律模块及固体力学模块,通过建立质量源项、体荷载等实现上述考虑渗流场与结构场流固耦合理论方程的嵌入。 附带参考lunwen及流固耦合视频 是学习注浆扩散,流固耦合,变形很好的新手案例。 ,Comsol;流固耦合注浆;冒浆分析;达西定律模块;固体力学模块;渗流场与结构场流固耦合;质量源项;体荷载;学习案例,Comsol 6.2版流固耦合注浆分析:达西定律与固体力学模块应用案例
基于python内置的opencv的图像识别项目
0308_ba_open_report
cole_02_0507
Matlab非线性优化算法实现,基于Matlab的BFGS梯度下降算法结合Armijo线搜索法在多项式目标函数优化中的应用与最优解研究,基于matlab的非线性优化算法实现 通过梯度下降法(具体实现为 BFGS 方法),并结合 Armijo 线搜索方法,对一个多项式目标函数进行优化,找到其最优解。 开发语言:matlab ,核心关键词:Matlab; 非线性优化算法; 梯度下降法; BFGS方法; Armijo线搜索方法; 多项式目标函数; 最优解。,MATLAB中结合BFGS与Armijo线搜索实现多项式目标函数优化算法
【财通证券-2025研报】轻工行业周报:上海二手房成交亮眼,家居315营销开启.pdf
基于SS补偿网络的无线电能传输中的变频移相综合控制策略:谐振稳定与输出电压优化调节,基于多目标综合控制的无线电能传输系统:谐振稳定输出电压的变频移相控制策略。,ss补偿网络变频控制移相控制,同时控制系统保持谐振和稳定输出电压,多目标综合控制 无线电能传输 ,ss补偿网络; 变频控制; 移相控制; 谐振控制; 稳定输出电压控制; 多目标综合控制; 无线电能传输。,综合控制下的无线电能传输系统,实现稳定谐振输出与多目标管理
chang_01_0509