拦截器捕获异常
一般地,我们都是Dao、servcie层都把异常抛出,最后由Action来进行捕获。如果所有的Action都要捕获异常的话,那么就多了很多的重复代码。
因此,我们可以使用拦截器来进行统一捕获。
修改角色权限无法同步的问题
如果用户已经登录,此时修改登录用户的角色信息或角色对应的资源信息。由于用户的数据已经存在于Session中,无法及时进行数据同步。
解决方案:
在ServletContext范围内设置集合变量changeEmp,当管理员维护到某个员工的角色时,将该员工的OID放入该集合;
当管理员维护到某个角色的资源时,将该角色对应的所有员工OID放入该集合。
在登录校验时,获取完登录信息后,再次获取该集合,查看当前用户OID是否存在于该集合。如果存在于该集合中,清空当前登录人信息,将员工OID从集合中删除,同时跳转到登录界面。
- 将要修改的用户保存到集合中(记录被修改的用户)
- 等到校验的时候发现该用户是否被修改过(在集合中是否存在),如果存在,那么则强制注销,跳转回登陆页面
配置数据源
一般地,我们做开发都是直接使用tomcat来连接数据库,但是如果数据库的地址变化的时候,我们就要手动去修改连接的地址了。这样会造成一些不必要的麻烦。
所以,官方是推荐我们使用JNDI来配置数据源,使用JNDI来连接数据库的。这样即使数据库的地址变了,我们就不用手动去修改连接的地址。
步骤如下:
- 修改tomcat安装目录/conf/context.xml,添加如下配置
<Resource name="jdbc/DataSource" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" url="jdbc:mysql://localhost:3306/erpdb" driverClassName="com.mysql.jdbc.Driver" username="root" password="root" />
- 配置Web应用使用Tomcat数据源,修改WEB-INF/web.xml,添加如下配置
<resource-ref> <res-ref-name>jdbc/DataSource</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
- 接着来spring中配置我们的数据源,是从JNDI从查找出来的。
JNDI的命名,不同web服务器有不同的书写格式:
JNDI名是远端访问的通用名称,可以理解为使用该名称获取对应的资源信息。 JNDI的命名官方规范 java:comp/env/JNDI名称 Jboss java:JNDI名称 Weblogic JNDI名称
权限控制菜单树
每个菜单树需要的权限可能是不一样的,要想用权限系统去管理菜单树,就要把菜单树写成是动态的。
菜单模型设计如下:
- 菜单名称,菜单编号,所属父级菜单对象,菜单对应访问路径
在查询的时候用到了自关联
商品联动
在页面加载的时候,查询出所有供应商的数据、查询第一个供应商商品的类别以及第一个商品类别对应的所有信息集合。那么在页面上我们就可以将其展示出来了。
随后如果发生了改变的话,那么还是使用ajax来进行联动。
在添加新项的时候,对应的联动还是需要保持的,因此需要在外面套一层ajax来获取具体的数据!
//吐槽一下,这代码看得我贼鸡儿恶心,逻辑是这样子的: //首先在新增的时候我们要新增出新行的页面。 //同时下拉框的数据需要与数据库后台进行联动 //并且只能动态添加不同名称的商品,类别下所有商品已经存在了,那么就不能选择该类别了。 //还要对其不能随便修改,否则相同类型相同名称的商品又存在了。 // HTML+Jquery的拼接看得十分蛋疼....
//添加新商品 $("#add").click(function () { //设置不能修改供应商 $("#supplier").attr("disabled", "disabled"); //设置已存在的所有select全部不可点击 $(".goodsType").attr("disabled", "disabled"); $(".goods").attr("disabled", "disabled"); //发送ajax提交,将供应商id与当前已经使用的类别对应商品2个id传递到后台,并将其过滤,过滤完毕的数据传递回页面 var goodsTypeObjs = $(".goodsType"); var goodsObjs = $(".goods"); var jsonParam = {"gm.goodsType.supplier.uuid": $("#supplier").val()}; var hasUuids = ""; for (i = 0; i < goodsTypeObjs.length; i++) { hasUuids = hasUuids + $(goodsTypeObjs[i]).val(); hasUuids = hasUuids + ":"; hasUuids = hasUuids + $(goodsObjs[i]).val(); if (i != goodsTypeObjs.length - 1) { hasUuids = hasUuids + ","; } } jsonParam["hasUuids"] = hasUuids; //动态添加一个tr行 //创建tr组件 var $tr = $("<tr></tr>"); //创建td组件,生成商品类别select var typeSelectStr = "<select class='goodsType' style='width:200px'>"; for (i = 0; i < 4; i++) { typeSelectStr += "<option value='"; typeSelectStr += 111; typeSelectStr += "'>"; typeSelectStr += "类别名称" + i; typeSelectStr += "</option>"; } typeSelectStr += "</select>"; var $td1 = $("<td height='30'>" + typeSelectStr + "</td>"); $tr.append($td1); //创建td组件,生成商品select var goodsSelectStr = "<select name='gmUuids' class='goods' style='width:200px'>"; for (i = 0; i < 4; i++) { goodsSelectStr += "<option value='"; goodsSelectStr += 123; goodsSelectStr += "'>"; goodsSelectStr += "新商品名" + i; goodsSelectStr += "</option>"; } goodsSelectStr += "</select>"; var $td2 = $("<td>" + goodsSelectStr + "</td>"); $tr.append($td2); //创建td组件,生成商品数量input,默认值1 var $td3 = $("<td> <input name='nums' type='text' value='1' class='num order_num' style='width:67px;border:1px solid black;text-align:right;padding:2px' /></td>"); $tr.append($td3); var $td4 = $("<td style='padding-left:4px'><input name='prices' type='text' value='" + 222 + "' class='prices order_num' style='width:93px;border:1px solid black;text-align:right;padding:2px' /> 元</td>"); $tr.append($td4); var $td5 = $("<td class='total' align='right'>" + 222 + " 元</td>"); $tr.append($td5); var $td6 = $("<td> <a class='deleteBtn delete xiu' value='" + 112 + "'><img src='../../../images/icon_04.gif'/> 删除</a></td>"); $tr.append($td6); //在最后一个tr对象前添加该tr组件 $("#finalTr").before($tr); //注意:新添加的元素是否具有动态事件激活能力 //获取后台数据是否还有下一个可用的商品,判断添加按钮是否显示 if ("Y" == "N") { //将添加按钮设置为不可显示 $("#add").css("display", "none"); } total(); });
可以使用两种方式来进行控制数据:
SQL控制:
//获取商品类别信息,类别必须有商品,企业ID=1,过滤掉1,2商品 select distinct gt.* from tbl_goodsType gt, tbl_goods g where gt.supplierUuid = 1 and g.goodsTypeUuid = gt.uuid and g.uuid not in (1,2,3,4,5) //过滤使用过的商品,2号类别,过滤掉1,2,3,4商品 select * from tbl_goods where goodsTypeUuid = 2 and uuid not in (1,2,3,4)
程序控制:
//已经使用过的,需要过滤的商品uuid public String used; //'11','22','33','44', //ajax根据供应商的uuid获取类别和商品信息(具有数据过滤功能) public String ajaxGetGtmAndGm2(){ gtmList = goodsTypeEbi.getAllUnionBySm(supplierUuid); //由于类别数据中第一个类别的所有商品已经使用完毕,而没有将其删除,导致该商品类别对应的商品集合在下面的迭代过程中没有商品,抛出索引越界异常 //解决方案:删除掉对应的商品类别即可 //过滤掉所有商品已经使用完毕的商品类别 Goods: for(int i = gtmList.size()-1 ;i>=0;i--){ List<GoodsModel> gmListTemp = goodsEbi.getAllByGtm(gtmList.get(i).getUuid()); for(GoodsModel gmTemp : gmListTemp){ if(!used.contains("'"+gmTemp.getUuid()+"'")){ //保留该类别,直接判断下一个类别 continue Goods; } } //循环执行完毕,执行到的此处,上述循环没有进入if语句,里面的商品都使用过 gtmList.remove(i); } //上述集合中的类别一定都存在没有使用过的商品 gmList = goodsEbi.getAllByGtm(gtmList.get(0).getUuid()); //当前获取的商品信息的uuid具有重复的,要对其进行过滤 //对集合进行迭代删除,怎么做?必须逆向进行 //从gmList中取出所有的元素,挨个迭代,与本次传递过来的used进行比对,比对完发现重复的,删除掉(逆序进行) for(int i = gmList.size()-1 ;i >=0 ;i--){ Long uuid = gmList.get(i).getUuid(); //判断该uuid是否出现在used中 if(used.contains("'"+uuid+"'")){ gmList.remove(i); } } gm = gmList.get(0); return "ajaxGetGtmAndGm"; } //ajax根据商品类别uuid获取商品信息 public String ajaxGetGm(){ gmList = goodsEbi.getAllByGtm(gtmUuid); //过滤数据 for(int i = gmList.size()-1 ;i >=0 ;i--){ Long uuid = gmList.get(i).getUuid(); //判断该uuid是否出现在used中 if(used.contains("'"+uuid+"'")){ gmList.remove(i); } } gm = gmList.get(0); return "ajaxGetGm"; }
Juqery未来对象
如果在生成的代码不是当前对象的,那么绑定的事件就无法被激活了。因此需要使用live去激活未来对象。
2018年3月11日18:01:31更新!
Jquery高版本已经舍弃这个方法了,改成了on方法
订单设计
我们的订单可能分很多种:采购订单、销售订单、采购退货单、销售退货单
一般地,我们都不会将它们四种都用字段来表示出来,仅仅使用订订单状态字段进行了区分