用户登录时需使用验证码防止恶意请求数据库,
个人首页需展示个人信息或进入联系人管理,
联系人管理页需在基础的增、删、改、查上进一步实现分页查、模糊查、批量删功能。
分页查,我们需要获取一些数据:联系人总记录数 totalCount
、总页码 totalPage
、每页的数据集合 List
、当前页码 currentPage
、每页显示的记录数 rows
。
我们可以将这五种数据当成属性放在实体类 Page
中,在servlet中获取数据后放在request域交由前端展示。
参考源码:
/**
* 分页查询需要的实体类Page.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
*/
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
属性即可: ,当然不要忘记在复选框外面添加
标签。
在servlet中获取同一个 name
属性的标签值,使用的是 request.getParameterValues("uid")
方法,它将返回一个String数组 String[]
,我们遍历数组得到id并对该id下的数据进行删除,遍历完成即批量删除完成。
验证码在这里是用的 标签显示:
其中的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 筛选条件;
二是前端传参到后端的几种方法:
使用 表单可根据文本框的
name
属性传参它的 value
值。且使用 method="post"
提交表单,可使参数值不显示在地址栏。
使用 标签,在
href
属性后使用 ?
和 &&
确定传参的键值和数量,如:查看个人信息
,但a标签的传值是get方法,地址栏中会显示参数的所有信息。
如果想用 标签传值,又不想参数显示在地址栏,那么可以通过js生成
表单进行post方法提交:
查看个人信息
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);
}