最近三天做了XX公寓管理系统,采用JSP+Servlet+Oracle的设计方式,数据库连接池采用c3p0,总体架构为三层设计模式,利用过滤器做了登陆验证和设置页面的字符编码。以上为当前小项目采用的技术,现在还没有做完,只是做了管理员的用户管理模块和角色管理两个模块,现在针对这两个模块来总结下遇到的问题:
1、模糊查询序列问题
这个序列问题是由于我在进行连表查询时候没有将表放在正确的位置上产生的,发生的原因是因为一开始的时候做的是针对用户表的单个表查询,所以当时的数据库SQL如下:(没有问题)
--首先做查询并进行排序
SELECT * FROM auser ORDER BY u_id
--查询带rownum
SELECT a.*,ROWNUM rw FROM (SELECT * FROM auser ORDER BY u_id) a
--固化rownum并分页
SELECT * FROM (SELECT a.*,ROWNUM rw FROM (SELECT * FROM auser ORDER BY u_id) a) WHERE rw>=1 AND rw<=5
但因为页面数据显示要用到角色名称(用户表中存储的是角色ID),因此必须将角色表连接进来,因此我就没进行认真考虑直接在第二步骤就进行了左连接,然后看到了用户名称显示就直接去进行了测试,当时的SQL语句如下:
--查询带rownum
SELECT a.*,ROWNUM rw,ro_name FROM (SELECT * FROM auser ORDER BY u_id) a LEFT JOIN ROLE r ON a.role_id=r.ro_id
后来由于页面显示的问题才知道自己犯了粗心的大错,输出sql语句以后发现了这个问题,这个错误的产生实属自己的粗心导致,不应该,经过改正,正确的SQL语句如下:
--首先做查询并进行排序
SELECT a.*,ro_name FROM auser a LEFT JOIN ROLE r ON a.role_id=r.ro_id ORDER BY u_id
--查询带rownum
SELECT a.*,ROWNUM rw FROM (SELECT a.*,ro_name FROM auser a LEFT JOIN ROLE r ON a.role_id=r.ro_id ORDER BY u_id) a
--固化rownum并分页
SELECT * FROM (SELECT a.*,ROWNUM rw FROM (SELECT a.*,ro_name FROM auser a LEFT JOIN ROLE r ON a.role_id=r.ro_id ORDER BY u_id) a) WHERE rw>=1 AND rw<=5
切记:针对数据库一定要一步一步来,任何跳步觉不允许。
2、过滤器进行登录验证过滤掉了图片,CSS,JS等。
利用过滤器进行登录验证,原理是在进入任何页面之前,首先判断用户是否登录,如没登录则返回到登录页面,并提示用户请登录再访问。在写过滤器时候遇到的问题是因为一开始没有放行图片,js,css等,导致 页面的这些东西被过滤器给拦截住,在页面什么都没有显示。
后来查了资料解决了这个问题,解决方法时获得uri,通过对uri的后缀进行判断,如果是图片等格式的话就放行,贴上解决这个问题的代码:
@WebFilter("/*")
public class LoginCheck implements Filter {
public LoginCheck() {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse reps = (HttpServletResponse) response;
HttpSession session = req.getSession();
User user = (User) session.getAttribute("Admin");
String uri = req.getRequestURI();
if (uri.endsWith(".css") || uri.endsWith(".js") || uri.endsWith(".png") || uri.endsWith(".jpg")|| uri.endsWith(".gif")) {
// 如果发现是css或者js文件,直接放行
chain.doFilter(request, response);
}else{
if (user == null) {
if (uri.indexOf("LoginServlet") != -1 || uri.indexOf("login.jsp") != -1) {
chain.doFilter(request, response);
} else {
req.setAttribute("errMsg", "请登陆后再操作");
req.getRequestDispatcher("login.jsp").forward(req, reps);
return;
}
} else {
chain.doFilter(request, response);
}
}
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
3、批量删除利用Jquery实现全选和全不选
在做表格显示的时候一般都有批量删除的按钮,所以如何实现这个功能是做表单显示的必备技能,首先先实现全选和全不选的功能,下面为JQuery代码:
if($("#allDel").is(':checked')){
$('input[name="checkDel"]').each(function(){
$(this).prop("checked",true);
});
}else{
$('input[name="checkDel"]').each(function(){
$(this).prop("checked",false);
});
}
当实现了全选和全不选之后要获取选中的所有记录ID,再将此提交到Servlet进行批量删除,难点就在于如何获得所选中的ID,下面为JSP中的表格代码:
<!--每条记录前的单选框 -->
<td height="23"><input name="checkDel" type="checkbox"></td>
<!--每条记录的ID -->
<td height="23"><span class="STYLE1">${user.u_id }</span></td>
我的思路是通过input[name="checked"]获得checked的集合,然后判断集合的长度,若长度大于0,说明记录有被选中的,若不大于0,则提示用户未勾选。当集合大于0是进行集合的判断,在判断之前设置一个Array数组用于存储选中的id,在获取到所有选中ID后通过post提交交给Servlet进行相应的处理。代码如下:
var delAll = $('input[name="checkDel"]:checked');
if(delAll.length>0){
if (confirm("确定要批量删除所勾选用户吗?")) {
var id_array=new Array();
delAll.each(function() {
var id = $(this).parent().next().children().eq(0).text();
id_array.push(id);
});
var idstr=id_array.join(',');
var temp = $("<form></form>");
temp.attr("action", "UserServlet");
temp.attr("method", "post");
var flag = $('<input type="text" name="flag" value="doAllDel"/>');
var my_input = $('<input type="text" name="idstr" />');
my_input.attr('value', idstr);
temp.append(flag);
temp.append(my_input);
temp.submit();
return temp;
}else{
}
}else{
alert("未勾选要删除的用户");
}
4、外键的设置与否
一开始设置数据库时,我设置的是用户表中role_id与角色表中的ro_id进行外键关联,后来再进行角色的删除时候遇到了问题,提示违反了外键约束,这时候我想到了设置外键的这点不足之处。其实在数据库中通过事务锁可以实现删除角色的同时也删除用户表中的数据,但这样不安全不是吗?
我解决的方案是设置一个中间表,它里面有两个字段,分别是用户ID和角色ID,这样就可以使用户表和角色表进行解耦。