JSP自定义标签之查询一条数据

JSP自定义标签
placeholder image
admin 发布于:2015-11-17 17:09:48
阅读:loading

基本描述

自定义标签在一些后台管理系统中其实还是很有用途的,至少在做一些基础数据维护的功能上开发效率能够得到非常大的提高,比如说可以有:自定义标签查询分页、查询一条数据、查询一个下拉框,以及联动下拉框等等,完全可以是一个标签,一条sql语句搞定,没有不好维护,只能是标签写的不好,这里走一波实际应用中的自定义标签吧,不从基础示例开始,只是分享下实现方案,以及能够解决哪种问题。

本次主要围绕查询一条数据的明细功能为需求来分析一个通用的查询标签的实现方案。查询明细往往也用在很多很多地方,比如查看数据,修改之前的数据回显,等等,所以如果需要快速的实现一个功能,我认为没有比使用自定义标签的方式来的更快了,因为它直接在我们的显示层面上做实现,实现则是靠标签去实现的,配合jstl的core标签库,基本上也是可以解决一切问题的,不要说写在页面上不好维护,因为页面上是可以看不见任何的<% %>逻辑代码的,闲话少说。

记得工作的第一家公司所用的技术核心就是自定义标签,从form表单开始,囊括了下拉框标签(支持一组联动)、超链接标签(将网页跳转的方式转换为ajax提交标签)、文件上传标签(带进度),逻辑判定标签(与c:if类似),数据查询分页标签、表单提交标签(将网页跳转转换为ajax提交数据)、弹出框标签(基于jqueryui框架)、导入script标签(输出<script src='xxx.js'></script>)等等等等,一系列标签从表单提交一直到后台处理全部都有封装,使用起来如果不考虑性能与效率,一天做10个带有查询列表分页的维护功能一点不夸张。其中一个最叼的是一个表达式解析,暂时叫它自定义表达式,el表达式写法是${xxx},这里的表达式为[{xxx}],凡是满足这个写法的表达式都有自己的解析逻辑,其实现是正则表达式,至于逻辑处理全是使用这种表达式与逻辑判定标签处理的,故它这里使用了嵌套标签,由于涉及到大量的自定义标签与自定义表达式会导致学习成本稍高(其实学习成本并不高,只是这种便捷式的技术并非行业通用的,在这里会了,走出去会完全派不上用场;另一方面时间长了人也容易变“傻”),不过个人则建议使用自定义标签来获取数据,逻辑上的处理则配合jstl的强大的标签去做解析与逻辑处理是最好的,毕竟jstl的标签还是使用很方便的;另一个则是学习或使用成本较低,完全是使用大家都会的jstl技术。

一般含有内容体的标签是用以输出内容体中的数据,一般标签的处理逻辑为,由标签开始标记开始——>获取参数处理逻辑——>标签结束输出内容体,不考虑标签嵌套的情况,使用自定义标签与jstl的core标签基本上就解决问题了,自定义的嵌套标签好像正式场景还没怎么遇到过,就不赘述。上一个不专业的流程图如下:

至于本文所讲的查询一条数据标签的逻辑处理过程也是比较简单的,简约而不简单,看看它的处理逻辑吧,如下图所示:


流程.gif

至于本文所讲的查询一条数据标签的逻辑处理过程也是比较简单的,简约而不简单,看看它的处理逻辑吧,如下图所示:

详细流程.gif

上图就直接是搞windows自带的画图工具手绘的,将就看看吧,以前也写过很多版本的代码,最后觉得这几个参数就足够了,而且使用的时候简单,方便,接下来先从使用层面上来描述一下吧,毫无疑问这是在jsp页面上做的事情:

参数描述

参数sql,很多时候我们为了使用方便直接在jsp页面上写一些查询逻辑的sql语句;

参数sqlKey,有的时候为了统一方便的去管理sql语句,可以将sql语句单独的配置起来,由配置文件去单独维护;

参数javaBeanClassName,查询语句返回一条数据的结果集,将结果集转换为一个VO对象,在页面上使用el表达式,利用对象.属性的方式去访问对象的属性值,当然此参数也不为必输项,如果没有此参数或者此参数为空,则将结果集转换为map对象,访问的方式一样是对象.属性的方式,然而这里的属性就成了map的key了,两者访问上的完全一致;

参数var,后台返回的一个数据集对象,为了方便的访问,或者说我们把一切的管理都交给页面标签体,则就需要在标签体中能够完全的访问此对象,故就将数据集保存在页面范围内,换句话就是将数据保存至pageContext范围内。

使用示例

1、导入标签库自不必说

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%@ taglib prefix="my" uri="/tags"%>

2、直接写sql示例,将sql查询出的结果集转换为map对象进行输出

<my:queryOne var="sysMenu"

        sql="SELECT

            userid AS 'userId' ,

            realname 'realName' ,

            sex 'sex',

            birthday 'birthday' ,

            accountid 'accountId'

        FROM

            sysuser

        WHERE

            userId = 1">

        <table width="300" border="1" style="border-collapsecollapse;">

            <tr>

                <th>编号:</th><td>${sysMenu.userId }</td>

            </tr>

            <tr>

                <th>姓名:</th><td>${sysMenu.realName }</td>

            </tr>

            <tr>

                <th>出生日期:</th><td>${sysMenu.birthday }</td>

            </tr>

        </table>

    </my:queryOne>

3、写sqlKey示例,将sql查询出的结果集转换为javabean对象进行输出

<my:queryOne var="sysMenu" sqlKey="demo.tag.queryUserById" javaBeanClassName="com.frame.modules.system.model.SysUser">

        <table width="300" border="1" style="border-collapsecollapse;">

            <tr>

                <th align="right">编号:</th><td>${sysMenu.userId }</td>

            </tr>

            <tr>

                <th align="right">姓名:</th><td>${sysMenu.realName }</td>

            </tr>

            <tr>

                <th align="right">出生日期:</th><td>${sysMenu.birthday }</td>

            </tr>

        </table>

</my:queryOne>

4、将sql查询出的数据集转换为javabean对象、将sqlKey查询出的数据集转换为map对象这些就不用说了,类似

此种实现方案存在的问题与解决办法

任何一种实现方案都有其存在的问题,比如说讨论一下实际使用时会出现的问题:

1)如果sql中存在动态传递参数,sql改如何写呢?

答:如果是直接访问改jsp页面进行参数传递时,获取传递的参数可以使用${param.属性名},param的方式是获取传递给页面的参数,与request.getParameter("属性名");的方式一致;如果访问的是action(或者controller或者servlet)可以在后台里面获取参数,将参数的值进行特殊处理,比如传递过来的中文需要解码,则将解码后的值再setAttribute至request范围,然后再在页面上获取,当然也可以将整个sql语句放在request范围,由页面获取;当然更可以写<%%>代码去处理,不过并不建议这么干。

2)如果查询不到数据怎么处理呢?

答:如果sql语句并未查询到数据,则不影响页面数据的显示,直接将内容体的内容输出,完全是看内容体怎么写的,比如内容体中可以获取var中的对象来判断是否为空,再做处理都是可以的。

3)sql查询出的数据集中的数据库字段是USER_NAME的形式,而我的javabean对象中是userName的属性,或者我map中的key定义完全想与java的属性规范一样,改怎么做?

答:写sql时,使用别名来处理,每个字段对应一个别名,别名是最后的处理属性。

4)如果查询明细的标签中存在动态可变的查询逻辑怎么处理呢?比如我传递的参数有name属性,则sql中存在name的where条件,否则不包括name的where条件,改如何处理呢?

答:此种逻辑建议再后台处理类中实现,也见过一种写法如:and name like '%${param.name}%',这种写法倒是也可以,因为如果name属性为null,el表达式在处理时会输出空白,所以为空时的where条件就变成了and name like '%%',不为空时为:and name like '%姓名%' ,实际上数据量大点的时候name like '%%' 与 没有这个and条件的效率是完全不一样的,这个可以试试,所以更建议使用后台的方式,注:后面会说道sqlKey的方式,对于这种动态的sql查询方式有很友好的实现方式,完全配置即可,后续的标签再详细描述。

5)如果查询的参数中含有',这些特殊字符呢,是否会被注入查询?

答:此种问题可在系统全局处理的,参考本系统中的请求包装器的实现。另外,配置sqlKey的方式是防注入sql的形式。

其他问题暂时还没遇到过。。。

代码实现比较简单,实现的处理逻辑都已经说清楚了,至于自己实现起来应该是完全可以,由于标签处的代码继承体系稍微有点多,我就不具体整理代码,需要的留言,我单独发吧。如果非要有个运行效果,参考下图:

说明.jpg

说明:当前示例原始为JSP页面的动态示例,可从博客V1版本中开放的源码中获取,dmeo页面路径为“/demo/myTag/queryOne.jsp”。


 点赞


 发表评论

当前回复:作者

 评论列表


留言区