之前页面是这样的
我们要做更多,更复杂的功能,所以把页面变更了一下
我们可以去一个前端框架里面找我们需要的代码
比如这个部分
我们可以用这个部分的代码:
下面把添加联系人与删除选中,放到右上方去
然后在最下面我们插入一个分页的动作,我们也可以直接从Bootstrap中提取源代码
仔细看一下上面,还有一个复选框没做
在表头上面添加一个新列,复选框的列
上面的页面就改造如下了
下面我们就要来完成功能
第一个登录功能
里面有一个login.html,我们还是要变成jsp页面
无非就是加一个这个语句
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
先直观的看一下这个页面
是不是有一个输入验证码,需要一个验证码图片,其实就是一个输出文件
我就拿过去,放在相应的位置
这个位置的src是不是要相应的变一下
这个位置就是插入了一张验证码
把这个验证码的源代码直接放入:
package web.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.util.Random;
/**
* 验证码
*/
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
public 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.GRAY);
//填充图片
g.fillRect(0,0, width,height);
//产生4个随机验证码,12Ey
String checkCode = getCheckCode();
//将验证码放入HttpSession中
request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
//设置画笔颜色为黄色
g.setColor(Color.YELLOW);
//设置字体的小大
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 = "0123456789ABCDEFGabcdefg";
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();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
然后重启服务器,页面就变成了
这个时候我们去完成js里面一个函数,点击验证码刷新功能
也就是在这个页面去完成上面这个refreshCode()这个函数
这里说一下切换验证码的原理
在img的src中,如果src的地址栏不变,就会从缓存中取出数据,从而不会发生一次服务器请求,这样,页面就不会刷新,从而得到新的验证码。
我们只要每次点击改变img里面src连接不就可以,也就是连接不一样,就相当于重新生成了一次验证码 ,要使连接不一样,我们后面就跟一个时间戳,时间戳永远不会重复嘛
function refreshCode() {
var date = new Date();
var verfiCode = document.getElementById("vcode");
verfiCode.src = "${pageContext.request.contextPath}/checkCodeServlet?time=" + date.getTime();
}
这里插入一个题外话,我们在使用EL表达式的时候,你不是说有内置对象可以使用嘛,为什么我在获取虚拟目录的时候,需要${pageContext.request.contextPath},而不直接${request.contextPath}呢,为什么不直接引用这个request这个对象,那么我们来看一下el的是一个内置隐式对象,我们可以拿来使用的
我们可以清楚的看到,对于request来说,确实是有一个相关的隐式对象,但这个对象是,RequestScope这个的含义是,获取request域里面 设置的值,上面我们基本可以看到获取的都是相关对象里面设置的值,而不是这个对象。所以,获取对象还是要借助PageContext这个域来做。
它可以来获取jsp内置的9个对象
下面我们来做一个登录的功能
也就是拿到用户的输入然后与数据库中的数据进行匹配
我们先来看一下之前的表
这个表里面并没有关于用户名与密码的数据,所以,我们要对表进行改造一下
加一个用户名与密码的字段
查询一下这张表,发现为空表
那么向表里插入两条数据
当然,也可以用sqlyog客户端直接修改,这里用代码,也是熟悉sql语句代码
我们在User.java里面也要把这两条字段给加上,同时要生成相应的set与get方法
然后我们就要写一个LoginServlet页面,来处理登录信息,调动service,service去调用dao层来进行一个数据的处理
下面说一个问题:为什么我们经常把一个数据表里面东西做成一个类来处理
这样可以比如我们根据用户名与密码查询了某个信息,然后可以通过Utils直接返回这个类对象给我们操作,他会自动封装我们需要的数据。
下面我们依次从servlet->service->dao去定义然后实现相应的方法
话不多说,上代码:
先来看两个前端页面
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
用户信息管理系统
index.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022/3/21
Time: 16:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
首页
欢迎你,${user.username},查询用户信吧!
LoginServlet
package web.servlet;
import domain.User;
import org.apache.commons.beanutils.BeanUtils;
import service.UserService;
import service.impl.UserServiceImpl;
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.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置数据编码
request.setCharacterEncoding("utf-8");
//拿到用户名与密码,我们用beanutils来进行处理
//拿到所有参数,参数拿到的都是字符串信息
Map map = request.getParameterMap();
//然后利用utils中的populate给她封装到一个对象里面去
User loginUser = new User();
try {
BeanUtils.populate(loginUser,map);//这个只会把我们找到匹配的值放进去,其他属性不会被赋值进去
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
UserService userService = new UserServiceImpl();
//下面我们要去到验证码的字符串信息
//先获取用户输入的信息
String verfiStr = request.getParameter("verifycode");
//然后这个验证码是被我们放到session里面去了,获取session对象拿到属性信息
String checkCodeStr = (String)request.getSession().getAttribute("CHECKCODE_SERVER");
//然后先来判断一下验证码是否正确
if(checkCodeStr != null && verfiStr.equalsIgnoreCase(checkCodeStr)) {
//这条路才是合理的
//合理就要来判断用户名与密码
//调用UserService里面的方法进行判断,当然他会去调用dao层更具体的方法
//这里会返回了实际查找到的数据
User user = userService.login(loginUser);
if(user == null) {
//跳转到login.jsp页面
request.setAttribute("loginMsg","username is error or password error");
//然后实现页面分发
request.getRequestDispatcher("/login.jsp").forward(request,response);
} else {
//这个就是成功了,直接跳转到首页,首页接收用户名
request.setAttribute("user",user);
//然后实现页面分发,跳转到首页
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
} else {
//这个就是验证码错误
request.setAttribute("loginMsg","verify code is error");
//然后还是跳转到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
再去service层面看看
UserService
import domain.User;
import java.util.List;
//用户管理的业务接口
//这里面方法命名尽可能大一点,比如登录,查找,添加
//而在dao层里面命名的方法尽可能细节一点,比如登录对应findByUsernameAndPassword这样的方法
public interface UserService {
//查询所有用户信息
public List findAll();
//判断登录
public User login(User loginUser);
}
UserServiceImpl
package service.impl;
import dao.UserDao;
import dao.impl.UserDaoImpl;
import domain.User;
import service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService {
//内部调用dao层的方法来进行查询,不要写到方法里面去
//不然每次都要来实现这个方法
UserDao userDao = new UserDaoImpl();
@Override
public List findAll() {
//内部调用dao层的方法来进行查询
return userDao.findAll();
}
@Override
public User login(User loginUser) {
return userDao.findByUsernameAndPassword(loginUser);
}
}
再去dao层看看
UserDao
package dao;
import domain.User;
import java.util.List;
/**
* 用户来操作的Dao
*/
public interface UserDao {
//查找所有用户
public List findAll();
//根据用户名与密码查找某个用户
public User findByUsernameAndPassword(User loginUser);
}
UserDaoImpl
package dao.impl;
import dao.UserDao;
import domain.User;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import util.JDBCUtils;
import java.util.List;
public class UserDaoImpl implements UserDao {
//创建一个JdbcTemplate模板对象,内部只需要传入一个数据源就ok
private JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDs());
@Override
public List findAll() {
//这个就是使用JDBCTemplate来做
//直接可以调用jdbcTemplate里面的一些方法操作
//这里是查询
String sql = "select * from user";//查询这张表的信息
//我们想的干的是啥?
//把数据库中每一行数据抽离出来,变成一个对象装载集合返回
List list = jdbcTemplate.query(sql,new BeanPropertyRowMapper(User.class));
return list;
}
@Override
public User findByUsernameAndPassword(User loginUser) {
//这里是具体的业务逻辑
String sql = "select * from user where username = ? and password = ?";
System.out.println(loginUser.getUsername() + " " + loginUser.getPassword());
//这里要返回一个对象,我们还是用JdbcTemplate来实行查询
//这个方法会给我们返回一个对象,这个方法如果没有找到实际
//就会给我们抛出一个异常,并不会直接给我们返回一个null
//所以必须把这个异常给捕获,然后返回一个null
try {
User user = jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper(User.class),loginUser.getUsername(),loginUser.getPassword());
return user;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
下面我们测试一下登录功能
验证码正确,用户或者密码输错
下面全部输入,然后进入index.jsp
下面来做一个添加联系人页面
还是按照上面来分析把一个html页面变成jsp页面
点击添加联系人,进入add.jsp页面,然后jsp页面就会跳转到一个servlet页面进行处理,service去调用dao层,然后完成之后,我们肯定要重新查询,展示在list.jsp中,所以,我们还要重新访问userListServlet页面,因为是这个页面给我们完成的查询,然后跳转到list.jsp的动作。
先把index.jsp里面修改一下
有人就说了,为什么不加${pageContext.request.contextPath}/add.jsp,因为这个是服务器内部的一个href的静态资源链接跳转,没有数据提交,也就没有请求。
现在就可以去实现addUserServlet
这个页面作用就是去调用servcie层的方法去把数据添加到数据库中,然后返回一个对象传过来,然后调用用户展示页面去展示。
话不多说,直接上代码
先来看add.jsp页面代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
添加用户
添加联系人页面
下面来看AddUserServlet
package web.servlet;
import domain.User;
import org.apache.commons.beanutils.BeanUtils;
import service.UserService;
import service.impl.UserServiceImpl;
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.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/addUserServlet")
public class AddUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置一下请求字符集,避免乱码
request.setCharacterEncoding("utf-8");
UserService userService = new UserServiceImpl();
User user = new User();
//拿到add.jsp页面传过来的数据
//封装到一个对象里面
Map map = request.getParameterMap();
//调用BeanUtils来进行封装
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//下面就要调用service里面的方法,把user添加进去
userService.add(user);
//这个时候再来处理一下页面分发
request.getRequestDispatcher("/userListServlet").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
下面去看service层实现的方法
下面去看dao层的具体实现方法
@Override
public void addUser(User user) {
//说白了就是向数据库增加一条记录
String sql = "INSERT INTO USER" +
"(name,gender,age,address,qq,email)" +
"VALUES" +
"(?,?,?,?,?,?)";
//用template模板来执行sql语句
//这里不是query
//得用update执行
jdbcTemplate.update(sql,user.getName(),user.getGender(),user.getAge(),user.getAddress(),user.getQq(),user.getEmail());
}
下面我们来做这其中的一个删除角标
分析:
删除肯定还是提交到一个servlet里面,然后调用service ,service调用dao层来实现删除
这里删除里面的href连接肯定是去访问一个delUserServlet页面,然后传一个id过去,但是这样做我们一点击删除就直接删除了,所以,这里我们调用一个javascript函数来做,当我们删除的时候给我们弹出一个确认框
看一下js代码:
function delUser(id) {
//给用户一个安全提示
if(conifrm("确定删除吗?")) {
//改变访问地址
//这里必须要注意把id给传过去
location.href = "${pageContext.request.contextPath}/delUserServlet?id=" + id;
}
}
然后我们在web层的servlet下面写DelUserServlet页面
package web.servlet;
import service.UserService;
import service.impl.UserServiceImpl;
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.io.IOException;
@WebServlet("/delUserServlet")
public class DelUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//删除不用设置字符集
//获取参数id
String id = request.getParameter("id");
//我们调用service里面delete来进行删除
UserService userService = new UserServiceImpl();
userService.delete(Integer.parseInt(id));
//然后我们需要跳转到首页去,这个是服务器内部内部跳转
//这个不会产生新请求,服务器内部跳转
// request.getRequestDispatcher("/userListServlet").forward(request,response);
//我们还可以用sendRedirect来实现跳转,这个会产生一个新请求
response.sendRedirect(request.getContextPath()+"/userListServlet");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
下面看service层
然后来看dao层
好了,继续下一个功能
上面做了删除,下面来做修改
既然要修改信息,那么点击修改的时候,这个页面就必须回显全部的信息
1.我们先要查询一个用户的信息,根据id来进行查询
2.根据id查询用户信息,然后返回一个User 对象
3.将User对象存到request中,然后转发到update.jsp页面,然后在这个页面用el 表达式来回显信息
4.然后用户,点提交,又会进入一个servlet页面,然后获取表单数据,然后封装user对象,然后修改页面,最后跳转到查询所有用户的页面
但是你要想我们要修改,就必获得某个用户的Id啊,根据id名字才能修改,我们有一个做法是在update.jsp页面设置一个隐藏域提交id
好了,直接上代码
先看一下list.jsp这个位置的跳转
在来看update.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
修改用户
修改联系人
再来看FindUserServlet
package web.servlet;
import domain.User;
import service.UserService;
import service.impl.UserServiceImpl;
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.io.IOException;
@WebServlet("/findUserServlet")
public class FindUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置字符键编码
//获取数据查询id
String id = request.getParameter("id");
//调用service
UserService userservice = new UserServiceImpl();
User user = userservice.findUser(Integer.parseInt(id));
//将User对象存到request里面
request.setAttribute("user",user);
//将页面转发到update.jsp中
request.getRequestDispatcher("/update.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
再来看dao层
然后看结果
上面数据的修改回显就成功了,下面我们就要来在update页面,在写一个servlet来提交修改数据
,首先在update页面传递一个隐藏域,把id给这个修改数据的servlet传过去
话不多说,直接上代码:UpdateUserServlet
package web.servlet;
import domain.User;
import org.apache.commons.beanutils.BeanUtils;
import service.UserService;
import service.impl.UserServiceImpl;
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.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/updateUserServlet")
public class UpdateUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置字符集编码,当我们需要处理数据的时候
//就要设置数据的字符集,不然放回数据的数据就会出现乱码
request.setCharacterEncoding("utf-8");
UserService userService = new UserServiceImpl();
User user = new User();
//把所有修改的数据全部收集起来做成一个map集合
Map map = request.getParameterMap();
try {
//会封装与类相对应的字段
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//然后调用service层,实现数据数据修改,最后,返回调用userListServlet展示修改后的页面
userService.update(user);
response.sendRedirect(request.getContextPath() + "/userListServlet");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
再来看service
再来看dao
@Override
public void updateUser(User user) {
String sql = "UPDATE USER SET NAME = ?,gender = ?,age = ?,address = ?,qq = ?,email = ? WHERE id = ?";
jdbcTemplate.update(sql,user.getName(),user.getGender(),user.getAge(),user.getAddress(),user.getQq(),user.getEmail(),user.getId());
}
然后可以直接修改结果提交。
下面来做这个删除选中的功能
删除选中分析思路,删除选中,主要还是在于如何大量提交用户的id,然后交给servlet,然后调用servcie,循环删除所有选中的id.
这里有一个小贴士就是,复选框本身我们提交的时候,就会把我们选中的值,也就说,就会把我们勾选的值进行提交,所以,如果它本身就可以帮我们把选中的值提交,那我用一个form表单把这些复选框包裹起来,然后提交就好了。而且当你选中了一个复选框,那么它的checked属性也就被自动选中了。
这里又会出现一个问题,在我们点击删除选中的时候,肯定要判断一下,你有没有选中的条目,有才提交,没有我们就啥也不做。
我们先来写前端代码,获取选中的id,然后进行提交。
先来看list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
用户信息管理系统