联系人管理系统 [JavaWeb项目]


该项目要求【联系人管理系统】

用户登录时需使用验证码防止恶意请求数据库,

个人首页需展示个人信息或进入联系人管理,

联系人管理页需在基础的增、删、改、查上进一步实现分页查模糊查批量删功能。

重点一 分页查

分页查,我们需要获取一些数据:联系人总记录数 totalCount、总页码 totalPage、每页的数据集合 List<T>、当前页码 currentPage、每页显示的记录数 rows

我们可以将这五种数据当成属性放在实体类 Page<T>.java 中,在servlet中获取数据后放在request域交由前端展示。

参考源码:

/**
 * 分页查询需要的实体类Page<T>.java
 */
public class Page<T> {
    
    
    private int totalCount; // 总记录数
    private int totalPage ; // 总页码
    private List<T> list ; // 每页的数据
    private int currentPage ; //当前页码
    private int rows;//每页显示的记录数
    //生成getter()/setter()方法……
}
//在servlet中调用分页代码,获取联系人数据并存入request域(控制层)
Map<String, String[]> condition = request.getParameterMap();
String currentPage = request.getParameter("currentPage");
String rows = request.getParameter("rows");
if (currentPage==null || currentPage.equals("")){
    
    
    currentPage = "1";
}
if (rows==null || rows.equals("")){
    
    
    rows = "5";
}

MainService service = new MainService();
Page<People> allPeopleByP = service.getAllPeopleByP(currentPage, rows, condition);

request.setAttribute("pb", allPeopleByP);
request.setAttribute("condition", condition);
request.getRequestDispatcher("/list.jsp").forward(request, response);
/**
 * MainService.java中分页功能的实现代码(逻辑代码层)
 */
public class MainService {
    
    
    private PeopleDao peopleDao = new PeopleDao();
    public Page<People> getAllPeopleByP(String _currentPage, String _rows, Map<String, String[]> condition){
    
    
        Page<People> peoplePage = new Page<People>();
        int currentPage = Integer.parseInt(_currentPage);//当前页
        int rows = Integer.parseInt(_rows);//每页的条数
        if (currentPage <= 0){
    
    
            currentPage = 1;
        }
        int totalCount = peopleDao.getCountByPage(condition);//联系人总记录数
        int start = (currentPage-1) * rows;//从start行数据开始获取
        List<People> allByPage = peopleDao.getAllByPage(start, rows, condition);//每页的数据集合
        int totalPage = (totalCount % rows)  == 0 ? totalCount/rows : (totalCount/rows) + 1;//总页码
        peoplePage.setCurrentPage(currentPage);
        peoplePage.setRows(rows);
        peoplePage.setTotalCount(totalCount);
        peoplePage.setList(allByPage);
        peoplePage.setTotalPage(totalPage);
        return peoplePage;
    }
}
/**
 * PeopleDao.java,对联系人的CURD(数据交互层)
 */
public class PeopleDao{
    
    
    /**
     * 使用druid连接池
     */
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    /**
     * 分页查询在某条件下的people表中的总记录数(联系人的总记录数)
     * @return int
     */
    public int getCountByPage(Map<String, String[]> condition) {
    
    
        String sql = "select count(*) from people where 1=1";//查询表中所有数据
        StringBuilder sbu = new StringBuilder(sql);//将sql语句转为StringBuilder类,进行分页查询内容的添加
        Set<String> keySet = condition.keySet();//准备遍历map
        List<Object> params = new ArrayList<Object>();//创建List集合存放分页查询参数
        for (String key : keySet){
    
    
            //如果map中有参数当前页或者行数,则继续往下执行代码
            if ("currentPage".equals(key) || "rows".equals(key)){
    
    
                continue;
            }
            //获取当前页/行数的值value
            String value = condition.get(key)[0];
            if (value!=null && !value.equals("")){
    
    //如果value不为空
                sbu.append(" and ").append(key).append(" like ? ");//添加sql语句的内容
                params.add("%" + value + "%");//将value添加到List集合
            }
        }
        sql = sbu.toString();
        return template.queryForObject(sql, Integer.class, params.toArray());
    }
    /**
     * 分页查询people表中的所有数据
     * @return List<People>
     */
    public List<People> getAllByPage(int start, int rows, Map<String, String[]> condition) {
    
    
        String sql = "select * from people where 1=1";//查询表中所有数据
        StringBuilder sbu = new StringBuilder(sql);//将sql语句转为StringBuilder类,进行分页查询内容的添加
        Set<String> keySet = condition.keySet();//准备遍历map
        List<Object> params = new ArrayList<Object>();//创建List集合存放分页查询参数
        for (String key : keySet){
    
    
            //如果map中有参数当前页或者行数,则继续往下执行代码
            if ("currentPage".equals(key) || "rows".equals(key)){
    
    
                continue;
            }
            //获取当前页/行数的值value
            String value = condition.get(key)[0];
            if (value!=null && !value.equals("")){
    
    //如果value不为空
                sbu.append(" and ").append(key).append(" like ? ");//添加sql语句的内容
                params.add("%" + value + "%");//将value添加到List集合
            }
        }
        sbu.append(" limit ?,? ");
        params.add(start);
        params.add(rows);
        sql = sbu.toString();
        return template.query(sql, new BeanPropertyRowMapper<People>(People.class), params.toArray());
    }
}

重点二 模糊查

模糊查主要在于sql语句的编写,在数据库中我们是这样写的:select * from 表名 where 字段名 like '%输入值%'

但在java代码中,我们需要注意 like 关键字的后面,'% 两者的位置,错误经常在这两个地方:String sql = "select * from 表名 where 字段名 like '%?%'";

输入值 前后都加 % ,是左右都模糊,只要该字段下的值含有该 输入值 ,那么就返回这些结果。

输入值 左边添加 % ,是模糊该字段下的值的左边部分,只对比查找最右边是否有该 输入值

复习一下,sql语句中的like关键字使用语法:

-- like 一般和通配符一起使用,通配符有
-- %(百分号),匹配任意多个字符,包含0个字符
-- _(下划线),匹配单个字符 


-- 查询姓名为‘王’的学生信息
select * from student where stuname like '王%';
-- 查询姓名第二个字是‘一’的学生信息
select * from student where stuname like '_一%';

重点三 批量删

说到批量处理,我们一般都是对单个数据进行的增删改,所以在批量删除这一点上,我们只需要想办法获取到批量的数据集合(数据一般是表字段编号id),遍历这个集合,依次执行删除操作即可。

在删除数据时,我们一般使用该条数据的唯一编号id作为条件进行删除,那么我们只需要从前端获取批量的数据id就可以了。

前端我们只需要给复选框添加 name 属性和 value 属性即可:<input type="checkbox" name="uid" value="${user.id}"> ,当然不要忘记在复选框外面添加 <form> 标签。

在servlet中获取同一个 name 属性的标签值,使用的是 request.getParameterValues("uid") 方法,它将返回一个String数组 String[] ,我们遍历数组得到id并对该id下的数据进行删除,遍历完成即批量删除完成。

重点四 登录页的动态验证码

验证码示例

验证码在这里是用的 <img> 标签显示:

<label for="verifycode">验证码:</label>
<input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码" style="width: 120px;"/>
<a href="javascript:refreshCode()"><img src="${pageContext.request.contextPath}/getVCode" title="看不清点击刷新" id="vcode"/></a>

其中的js函数:

function refreshCode(){
    
    
    //设置img标签src属性
    //src属性中添加time参数是为了验证码生成不重复
    document.getElementById("vcode").src = "${pageContext.request.contextPath}/getVCode?time" + new Date().getTime();
}

在servlet中生成动态验证码:

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;

@WebServlet("/getVCode")
public class GetVCode extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //服务器通知浏览器不要缓存
        response.setHeader("pragma","no-cache");
        response.setHeader("cache-control","no-cache");
        response.setHeader("expires","0");
        //在内存中创建一个长80,宽30的图片,默认黑色背景
        //参数一:长
        //参数二:宽
        //参数三:颜色
        int width = 80;
        int height = 30;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //获取画笔
        Graphics g = image.getGraphics();
        //设置画笔颜色为黑色
        g.setColor(Color.BLACK);
        //填充图片
        g.fillRect(0,0, width,height);
        //产生4个随机验证码,12Ey
        String checkCode = getCheckCode();
        System.out.println("生成的验证码是:" + checkCode);
        //将验证码放入HttpSession中
        request.getSession().setAttribute("CHECKCODE_SERVER", checkCode);
        //设置画笔颜色为白色
        g.setColor(Color.LIGHT_GRAY);
        //设置字体的小大
        g.setFont(new Font("黑体",Font.BOLD,24));
        //向图片上写入验证码
        g.drawString(checkCode,15,25);
        //将内存中的图片输出到浏览器
        //参数一:图片对象
        //参数二:图片的格式,如PNG,JPG,GIF
        //参数三:图片输出到哪里去
        ImageIO.write(image,"PNG",response.getOutputStream());
    }
    
    /**
     * 产生4位随机字符串
     */
    private String getCheckCode() {
    
    
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghigklmnopqrstuvwxyz";
        int size = base.length();
        Random r = new Random();
        StringBuffer sb = new StringBuffer();
        for(int i=1;i<=4;i++){
    
    
            //产生0到size-1的随机值
            int index = r.nextInt(size);
            //在base字符串中获取下标为index的字符
            char c = base.charAt(index);
            //将c放入到StringBuffer中去
            sb.append(c);
        }
        return sb.toString();
    }
}

不重点五 增、删、改

JavaWeb项目的增删改,从获取关键数据,到调用逻辑代码,实现数据交互,都无太多需要注意的地方,这里只写两点。

一是复习经常到的增删改的sql语句:

-- 增
insert into 表名 values(, ……);
insert into 表名 set 列名=, 列名=, ……;
-- 删
delete from 表名 where 筛选条件;
delete from 表名;
truncate table 表名;
-- 改
update 表名 set 字段=新值, 字段=新值, …… where 筛选条件;

二是前端传参到后端的几种方法:

  1. 使用 <form> 表单可根据文本框的 name 属性传参它的 value 值。且使用 method="post" 提交表单,可使参数值不显示在地址栏。

  2. 使用 <a> 标签,在 href 属性后使用 ?&& 确定传参的键值和数量,如:<a href="home.jsp?myId=${requestScope.userId}&&myTel=${requestScope.userTel}">查看个人信息</a> ,但a标签的传值是get方法,地址栏中会显示参数的所有信息。

  3. 如果想用 <a> 标签传值,又不想参数显示在地址栏,那么可以通过js生成 <form> 表单进行post方法提交:

    <a href="javascript:nextHref('home.jsp',{'myId':'${requestScope.userId}'},{'myTel':'${requestScope.userTel}'});">查看个人信息</a>
    
    function nextHref(to, p, p2) {
          
          
        var myForm = document.createElement("form");
        myForm.method = "post";
        myForm.action = to;
        for (var i in p){
          
          
            var myInput = document.createElement("input");
            myInput.setAttribute("name", i);
            myInput.setAttribute("value", p[i]);
            myForm.appendChild(myInput);
        }
        for (var j in p2){
          
          
            var myInput = document.createElement("input");
            myInput.setAttribute("name", j);
            myInput.setAttribute("value", p2[j]);
            myForm.appendChild(myInput);
        }
        document.body.appendChild(myForm);
        myForm.submit();
        document.body.removeChild(myForm);
    }
    

猜你喜欢

转载自blog.csdn.net/weixin_60808029/article/details/124269587