sql语句模糊查询单引号问题,及jquery方法扩展,struts2拦截器

  • 在sql语句中使用单引号模糊查询可能报错,例如:查询的单引号与%%两端的单引号匹配了形成断句,从而导致查询失败。所以要将单引号转义,变成两个单引号 '' 就行了。
SELECT * from ft_providers WHERE last_name like '%'%';          //报错

SELECT * from ft_providers WHERE last_name like '%''%';         //正确

  • 那么在前端或者java里面就要将查询字符串进行替换,java里面比较简单,有replaceAll( )方法。但是js中没有,则可以用正则表达式来全局替换。
var account = $("#query_account").val().replace(new RegExp("'","gm"),"''"); //将单引号变成两个单引号,防止数据库模糊查询出错 g:表示全局匹配 m表示执行多行匹配
  • 我们也可以编写String对象的原型方法,来添加一个replaceAll()方法:
 String.prototype.replaceAll = function(s1,s2){
      return this.replace(new RegExp(s1,"gm"),s2);
 }

str.replaceAll("'","''");               //使用自定义替换全局
  • 在js语句中,当很多页面很多模糊查询的条件时,都要运用上面的方法进行一遍替换操作,很麻烦。
function queryDataInfo(){
            $('#datagrid').datagrid('load',{
                   'vo.account': $("#query_account").val().replaceAll("'","''"),
                   'vo.storeId': $("#query_storeId").val().replaceAll("'","''"),
                   'vo.isAble': $("#query_isAble").combobox('getValue')
            });
            $("#query_dialog").dialog('close');
       }

既然都是通过val()方法取值然后替换,则干脆扩展val()方法直接全部替换:
可能出现问题:
  1. 当取值中确实有单引号,而我们并不需要去进行模糊查询操作,则可能获取的值与传递的值不一致。
  2. 所有这样扩展只能用于本例中用于模糊查询,一般form表单也不用一个一个取值去传递,所以这权当是一次学习扩展方法,以后有想满足自己什么功能自己再修改就是了。
//一定要写在这里面,不然会报错
$(function(){

     /**
      * 修改Jquery的val() 方法,进行全局替换' 为''
      * 用于在sql模糊查询中,一个单引号会对sql语句造成影响,两个单引号则形成转义作用
      * @param options
      * @returns
      */
     (function ($) {                                       //形成一个闭包
            var originalVal = $.fn.val;                    //获取原val方法
            $.fn.val = function(value) {
              if (arguments.length >= 1) {                 //判断是否传入参数,来判断是赋值还是取值
                return originalVal.call(this, value);      //赋值的话则执行原方法
              }
              var r = originalVal.call(this);              //执行原方法
              return r.replace(new RegExp("'","gm"),"''"); //扩展:一个单引号变成两个单引号
            };
     })(jQuery);
});

  • 上面是将Jquery原型val方法处理了,但是难免会在某些地方出现不可预知的问题。怎么办?其实这种,逻辑更愿意放在后台代码处理,而不是前台。所以查阅了相关资料,可以利用拦截器或者过滤器来处理字段。
我们来简单区分一下这两者的区别:
      过滤器:能过滤所有的请求, 依赖与servlet容器,基于回调函数,不能获取值。
      拦截器 : 只拦截Action请求,基于java的反射机制,能够获取值栈的值。能够多次调用。
     所以,要满足我们的需求,需要处理参数值,所以使用拦截器再好不过了。而过滤器则不能实现功能。如下为参数值方法拦截器实现,并在方法中处理单引号为双单引号。
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

/**
 * 查询值拦截器
 * 用于sql语句模糊查询时,关于单引号查询进而在此转义
 * @author aggerChen
 *
 */
public class QueryValueInterceptor extends MethodFilterInterceptor {
   
     @SuppressWarnings("rawtypes")
     @Override
     protected String doIntercept(ActionInvocation invocation) throws Exception {
          HttpServletRequest request = ServletActionContext.getRequest();          //获取请求
          String type = request.getHeader("X-Requested-With");                     //获取请求头
              
          if(type == null) return invocation.invoke();                             //type为null则表示非ajax请求。本项目查询方式都是ajax请求的,所以在此来排除一些其他的请求,比如表单                             

          Map<String,String[]> map =  request.getParameterMap();                   //获取请求中所有的参数map
          Iterator it = map.entrySet().iterator();
          //迭代
        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            String key = (String) entry.getKey();
            String[] values = (String[]) entry.getValue();
            if(key.indexOf("vo.")!=-1){                                 //判断是否是对象传参,vo.xxx 则为查询请求
              if(!"".equals(values[0])){
                   values[0] = values[0].replaceAll("'", "''");         //将一个单引号处理为两个单引号
              }
            }
        }
        return invocation.invoke();
     }

}

在struts.xml中配置拦截器。此示例只展示过滤器相关配置。
将默认拦截器设置为loginAndroleInterceptor拦截器栈,此栈中先进入roleInterceptor拦截器,再引入loginStack拦截器栈。loginStack栈中先经过登录拦截器,在经过本例自定义的查询条件拦截器,最后经过struts默认拦截器。
struts默认拦截器一定是在自定义拦截器最后再经过的。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
     <!-- 引入默认拦截器 -->
     <include file="struts-default.xml" />

     <package name="base-packege" extends="struts-default">
          <interceptors>
              <!-- 登陆拦截器 -->
              <interceptor name="loginInterceptor" class="com.fortis.cms.interceptor.LoginInterceptor"></interceptor>
              <!-- 角色拦截器 -->
              <interceptor name="roleInterceptor" class="com.fortis.cms.interceptor.RoleInterceptor"></interceptor>
              <!-- 查询条件值拦截器  本例自定义拦截器-->
              <interceptor name="queryValueInterceptor" class="com.fortis.cms.interceptor.QueryValueInterceptor"></interceptor>
              <!--登录拦截器栈  -->
              <interceptor-stack name="loginStack">
                   <interceptor-ref name="loginInterceptor">
                        <param name="excludeMethods">login,notNeedRoleForwardLogin</param>
                   </interceptor-ref>
                   <interceptor-ref name="queryValueInterceptor"></interceptor-ref>
                   <interceptor-ref name="defaultStack"></interceptor-ref>
              </interceptor-stack>
              <!--登录和角色拦截器栈  -->
              <interceptor-stack name="loginAndroleInterceptor">
                   <interceptor-ref name="roleInterceptor">
                       <param name="excludeMethods">login,notNeedRole*,queryMenuTree</param>
                   </interceptor-ref>
                   <interceptor-ref name="loginStack" />
              </interceptor-stack>
          </interceptors>
          <!--设置默认拦截器栈  -->
          <default-interceptor-ref name="loginAndroleInterceptor"></default-interceptor-ref>
         
     </package>
</struts>





总结:这是在项目中遇到的问题,这也是我解决的思路历程,暂时没报错了,不过其他地方调用val()有没有问题还没有一一去验证,权当是一次联系重写方法了。拦截器处理的话,应该是不会出错了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值