简介:轻量封装Spring MVC
因为本人在国内最大的电子商务公司工作期间,深感一个好的Web框架可以大大提高工作效率,而一个不好的Web框架,又可以大大的降低开发效率。所以,在根据笔者在从事电子商务开发的这几年中,对各个应用场景而开发的一个轻量封装Spring MVC的一个Web框架。
笔者工作的这几年之中,总结并开发了如下几个框架: summercool-web(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文件夹中
一、summercool-petstore应用结构
1. petstore-module.xml配置文件说明
<bean name="petstore" class="org.summercool.web.module.WebModuleConfigurer"> <property name="moduleName" value="petstore" /> <property name="uriExtension" value=".htm" /> <property name="moduleBasePackage" value="org.summercool.platform.web.module" /> <property name="context" value="/" /> <property name="contextPackage" value="/petstore/" /> </bean> <bean class="org.summercool.web.module.WebModuleUriExtensionConfigurer"> <property name="uriExtensions"> <util:list> <value>.htm</value> </util:list> </property> </bean>
说明:1) 该配置项的详细说明,笔者已经在上一篇进行了详细说明,地址是:http://dragonsoar.iteye.com/blog/1454095
2) 现在笔者就拿summercool-petstore应用来进行详细的说明:
A. 应用模块扫描
moduleBasePackage + contextPackage = 完整的该应用模块的招扫描路径
扫描该完整包路径下面的:controllers和widgets文件夹
比如说:summercool-petstore应用下面的controllers的文件夹下面的IndexController.java --> /index.htm
规则如下:
1. moduleBasePackage + contextPackage = org.summercool.platform.web.module.petstore
2. context = /
3. org.summercool.platform.web.module.petstore.controllers = /
4. uriExtension = .htm
所以:
1. org.summercool.platform.web.module.petstore.controllers.IndexController.java = /index.htm
该问应用地址:http://127.0.0.1:8080 或 http://127.0.0.1:8080/index.htm
B. 应用处理的请求
1. org.summercool.web.module.WebModuleUriExtensionConfigurer --> list --> .htm
2. 上面这个配置中,配置的是只有url地址扩展名为.htm的才会交给summercool框架处理
3. 如,我们要是访问: http://127.0.0.1:8080/index.php
二、summercool-petstore的Controller和Widget开发
1. Controller开发
1) Controller的扫描规则是: /IndexController.java --> /index.htm
2) 扫描的附件条件是,被扫描加载的Controller类,必须是实现Sprng MVC的标准Controller接口和类名必须是以Controller结尾。
2. 笔者拿/LoginController.java举例
package org.summercool.platform.web.module.petstore.controllers; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; public class IndexController extends AbstractController { @Override protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception { return new ModelAndView("/petstore/views/index"); } }
1) 因为IndexController继承自AbstractController,而该类实现了Controller接口,所以可以被扫描进来
2) ModelAndView接口不细说了,因为AbstractController是Spring MVC的标准类,所以不做详细介绍了。
说明:笔者强烈建议应用的请求,如果只是页面展示不涉及到表单提交的请继承AbstractController,AbstractController的处理流程图如下:
3. 笔者再拿/LoginController.java进行表单提交的举例
package org.summercool.platform.web.module.petstore.controllers; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; 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.config.cookie.CookieUtils; import org.summercool.platform.web.module.petstore.config.cookie.UserDO; import org.summercool.platform.web.module.petstore.formbean.LoginFormBean; @SuppressWarnings("deprecation") public class LoginController extends SimpleFormController { public LoginController() { setBindOnNewForm(true); setCommandName("loginFormBean"); setCommandClass(LoginFormBean.class); } @Override protected void onBindOnNewForm(HttpServletRequest request, Object command) throws Exception { LoginFormBean loginFormBean = (LoginFormBean) command; loginFormBean.setUserName("请输入用户名和密码");loginFormBean.setPassword(""); } @Override protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors) throws Exception { LoginFormBean loginFormBean = (LoginFormBean) command; // if (StringUtils.isEmpty(loginFormBean.getUserName()) || StringUtils.isEmpty(loginFormBean.getPassword())) { errors.reject("-1", "用户名或密码不能为空"); return; } if ("admin".equals(loginFormBean.getUserName()) && "111111".equals(loginFormBean.getPassword())) { UserDO userInfo = new UserDO(); userInfo.setId(0L); userInfo.setUserName("admin"); userInfo.setPassword("111111"); CookieUtils.clearCookie(request); CookieUtils.writeCookie(request, userInfo); } else { errors.reject("-2", "用户名或密码错误"); } } @Override protected ModelAndView onSubmit(Object command) throws Exception { return new ModelAndView("redirect:/index.htm"); } }
1) 笔者认为SimpleFormController是Spring MVC中最经典的一个Controller接口的抽象实现。为什么呢?因为SimpleFormController考虑到了很多来应对各种复杂的场景,下面笔者就一一的做出说明。
2) 比如说,有一种应用场景;在用户登录时要给出一句提示语,如:“请输入用户名和密码”等这样的字眼显示在form表单中的userName的输入字段,但是在password字段则每次登录页面都必须要清空,不能让浏览器记录我们的登录用户名和密码。
那么,LoginController中下面代码片段可以实现上面的需求:
public LoginController() { setBindOnNewForm(true); setCommandName("loginFormBean"); setCommandClass(LoginFormBean.class); } @Override protected void onBindOnNewForm(HttpServletRequest request, Object command) throws Exception { LoginFormBean loginFormBean = (LoginFormBean) command; loginFormBean.setUserName("请输入用户名和密码");loginFormBean.setPassword(""); }
<!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"> <fieldset> <@spring.bind "loginFormBean.*"/> <div class="input"> 用户: <input type="text" size="30" name="userName" id="userName" class="medium" value="${(loginFormBean.userName)!}"> </div> <div class="input"> 密码: <input type="password" size="30" name="password" id="password" class="medium" value="${(loginFormBean.password)!}"> </div> <#if (status.error)!> <#list status.errors.allErrors as error> <div class="alert alert-error"> ${error.defaultMessage} </div> </#list> </#if> <div class="actions"> <input type="submit" value="提交" class="btn"> <button class="btn" type="reset">取消</button> </div> </fieldset> </form> <hr> ${widget("/petstore/widgets/footer")} </div> </body> </html>
说明:setBindOnNewForm(true); 代表,当进入且第一次页面请求显示Login表单时,是否执行onBindOnNewForm()函数。
什么是当进入且第一次页面请求显示Login表单呢?意思就是说,当请求一个Login表单时,那么这就是一次请求,如果在请求/login.htm时的请求是get请求,那么Spring MVC会认为这是进入且第一次页面请求。反则,如果已经显示此页面,然后提交form表单,那么这是一次post请求,那么Spring MVC会认为这不是第一次页面请求,则不会在重新返回显示页面的时候再执行onBindOnNewForm()函数了。
在/index.ftl的页面模版中,我们可以看出,每次"userName"和"password"输入框都是通过“CommandObject”对象的值拿出来的,所以就可以做到每次第一次进入登录页面的时候,都给出指定的提示信息和密码为空的设置了。
3) 上面提到了会在Form表单提交后还会返回/login.htm页面,那么会在什么情况下返回到/login.htm页面呢?那当然是在提表交单发生错误的情况下了。笔者认为SimpleFormController在处理错误处理这块也非常的经典;如:在Form 表单提交的时,SimpleFromController会先执行onBindAndValidate()函数,如果该函数在校验输入参数的时候发生异常,则使用errors对象添加错误信息;当该函数返回后,Spring MVC会判断errors对象是否为空,如果为空,则执行onSubmit()函数,如果不为空,则返回到/index.htm页面。
SimpleFormController笔者认为真的是非常经典,里面还有两个函数需要介绍:refferenceData()和showForm()函数。
refferenceData():当每次显示form表单页面的时候都执行此函数
showForm():当onSubmit()函数执行完成后想继续返回到Form表单的提交页面,而直接执行此函数即可返回到Form表单的提交页面。
SimpleFormController处理流程图如下:
4. Widget函数讲解
1) 首先,我们还是先看一下/login.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"> <fieldset> <@spring.bind "loginFormBean.*"/> <div class="input"> 用户: <input type="text" size="30" name="userName" id="userName" class="medium" value="${(loginFormBean.userName)!}"> </div> <div class="input"> 密码: <input type="password" size="30" name="password" id="password" class="medium" value="${(loginFormBean.password)!}"> </div> <#if (status.error)!> <#list status.errors.allErrors as error> <div class="alert alert-error"> ${error.defaultMessage} </div> </#list> </#if> <div class="actions"> <input type="submit" value="提交" class="btn"> <button class="btn" type="reset">取消</button> </div> </fieldset> </form> <hr> ${widget("/petstore/widgets/footer")} </div> </body> </html>
2) 上面有两个${widget()}的freemarker函数笔者请各位码农注意一下:
${widget("/petstore/widgets/header")} ${widget("/petstore/widgets/footer")}
说明:通过查看大家可能也知道这两个函数具体是什么意思了;对!是加载局部的ftl页面模版。那么,码农们可能又要怀疑了,freemarker不是有<#include>标签吗?为什么还要再弄一个${widget()}函数呢,是不是多此一举了。答案当然是否定的;因为显示一个局部页面的时候,我们肯定还要在局部页面里面加一些业务逻辑,而<#include>标签是无法做到的,而${widget()}函数则可以。
规则:${widget("/petstore/widgets/header")} --先加载--> /petstore/widgets/HeaderWidget.java --再加载--> /petstore/widgets/header.ftl (HeaderWidget.java可选,即如果没有Widget类,则直接加载header.ftl页面)
而我们想在显示"header.ftl"局部页面的时候,我们可以将一部分显示的业务逻辑和"header.ftl"局部页面需要显示的页面数据通过此类加载;那么我们查看下"HeaderWidget.java"类,如下:
package org.summercool.platform.web.module.petstore.widgets; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.summercool.platform.web.module.petstore.config.cookie.CookieUtils; import org.summercool.web.servlet.view.freemarker.FreeMarkerWidget; public class HeaderWidget implements FreeMarkerWidget { public void referenceData(HttpServletRequest request, Map<String, Object> model) { model.put("userName", CookieUtils.getUserName(request)); } }
说明:上面的代码中可以看出,"header.ftl"页面中会显示登录人的用户名信息,那么用户名的信息则就是通过referenceData()函数加载的,model是"header.ftl"的页面变量信息map。
补充:从此篇结束后,summercool框架的基本使用则就不是任何问题了,下一篇笔者会介绍AroundPipeline、PreProcessPipeline、PostProcessPipeline和ExceptionPipeline,并会结合权限处理和异常处理等给出实例的应用实例和相关解决方案。
相关推荐
笔者工作的这几年之中,总结并开发了如下几个框架: 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-...
uniapp实战商城类app和小程序源码,包含后端API源码和交互完整源码。
本课程是 PHP 进阶系列之 Swoole 入门精讲,系统讲解 Swoole 在 PHP 高性能开发中的应用,涵盖 协程、异步编程、WebSocket、TCP/UDP 通信、任务投递、定时器等核心功能。通过理论解析和实战案例相结合,帮助开发者掌握 Swoole 的基本使用方法及其在高并发场景下的应用。 适用人群: 适合 有一定 PHP 基础的开发者、希望提升后端性能优化能力的工程师,以及 对高并发、异步编程感兴趣的学习者。 能学到什么: 掌握 Swoole 基础——理解 Swoole 的核心概念,如协程、异步编程、事件驱动等。 高并发处理——学习如何使用 Swoole 构建高并发的 Web 服务器、TCP/UDP 服务器。 实战项目经验——通过案例实践,掌握 Swoole 在 WebSocket、消息队列、微服务等场景的应用。 阅读建议: 建议先掌握 PHP 基础,了解 HTTP 服务器和并发处理相关概念。学习过程中,结合 官方文档和实际项目 进行实践,加深理解,逐步提升 Swoole 开发能力。
matlab齿轮-轴-轴承系统含间隙非线性动力学 基于matlab的齿轮-轴-轴承系统的含间隙非线性动力学模型,根据牛顿第二定律,建立齿轮系统啮合的非线性动力学方程,同时也主要应用修正Capone模型的滑动轴承无量纲化雷诺方程,利用这些方程推到公式建模;用MATLAB求解画出位移-速度图像,从而得到系统在不同转速下的混沌特性,分析齿轮-滑动轴承系统的动态特性 程序已调通,可直接运行 ,关键词:Matlab;齿轮-轴-轴承系统;含间隙非线性动力学;牛顿第二定律;动力学方程;修正Capone模型;无量纲化雷诺方程;位移-速度图像;混沌特性;动态特性。,基于Matlab的齿轮-轴-轴承系统非线性动力学建模与混沌特性分析
2024年移动应用隐私安全观测报告.pdf
本电影评论网站管理员和用户。管理员功能有个人中心,用户管理,电影类别管理,电影信息管理,留言板管理,论坛交流,系统管理等。用户可以对电影进行评论。因而具有一定的实用性。本站是一个B/S模式系统,采用SSM框架,MYSQL数据库设计开发,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得电影评论网站管理工作系统化、规范化。 本系统的使用使管理人员从繁重的工作中解脱出来,实现无纸化办公,能够有效的提高电影评论网站管理效率。 关键词:电影评论网站;SSM框架;MYSQL数据库 1系统概述 1 1.1 研究背景 1 1.2研究目的 1 1.3系统设计思想 1 2相关技术 2 2.1 MYSQL数据库 2 2.2 B/S结构 3 2.3 Spring Boot框架简介 4 3系统分析 4 3.1可行性分析 4 3.1.1技术可行性 4 3.1.2经济可行性 5 3.1.3操作可行性 5 3.2系统性能分析 5 3.2.1 系统安全性 5 3.2.2 数据完整性 6 3.3系统界面分析 6 3.4系统流程和逻辑 7 4系统概要设计 8 4.1概述 8 4.2系统结构 9 4.
2023-04-06-项目笔记-第四百三十六阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.434局变量的作用域_434- 2025-03-13
基于STM32的流量计智能流速流量监测、水泵报警系统(泵启动 1100027-基于STM32的流量计智能流速流量监测、水泵报警系统(泵启动、阈值设置、LCD1602、超阈值报警、proteus) 功能描述: 基于STM32F103C8单片机实现的智能流速、流量,流量计设计 实现的功能是通过信号发生器模拟齿轮传感器,检测流量的大小,同时计算流过液体的总容量 可以设置最大流过的总容量,当超过设定值后通过蜂鸣器与LED灯指示 当没有超过则启动水泵控制电路带动液体流动 1、流速检测 2、流量统计 3、阈值显示与设置(通过按键实现阈值的调节或清零) 4、水泵启动 5、超阈值报警 有哪些资料: 1、仿真工程文件 2、PCB工程文件 3、原理图工程文件 4、源代码 ,核心关键词: 基于STM32的流量计; 智能流速流量监测; 水泵报警系统; 阈值设置; LCD1602; 超阈值报警; Proteus仿真; STM32F103C8单片机; 齿轮传感器; 信号发生器; 流量统计; 蜂鸣器与LED灯指示; 水泵控制电路。,基于STM32的智能流量监测与报警系统(阈值可调、流速与流量监
(灰度场景下的平面、海底、船、受害者)图像分类数据集【已标注,约1100张数据】 数据经过预处理,可以直接作为分类网络输入使用 分类个数【4】:平面、海底、船、受害者【具体查看json文件】 划分了训练集、测试集。存放各自的同一类数据图片。如果想可视化数据集,可以运行资源中的show脚本。 图像分类、分割网络改进:https://blog.csdn.net/qq_44886601/category_12858320.html 计算机视觉完整项目:https://blog.csdn.net/qq_44886601/category_12816068.html
arkime无geo下的oui文件
人脸识别项目实战
人脸识别项目实战
CAD 2025 二次开发dll
人脸识别项目源码实战
c语言学习
基于扩张状态观测器eso扰动补偿和权重因子调节的电流预测控制,相比传统方法,增加了参数鲁棒性 降低电流脉动,和误差 基于扩张状态观测器eso补偿的三矢量模型预测控制 ,基于扩张状态观测器; 扰动补偿; 权重因子调节; 电流预测控制; 参数鲁棒性; 电流脉动降低; 误差降低; 三矢量模型预测控制,基于鲁棒性增强和扰动补偿的电流预测控制方法
c语言学习
UE开发教程与学习方法记录.zip