1、Jar 包
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<!--统一版本属性管理-->
<lombok.version>1.18.12</lombok.version>
<junit.version>4.11</junit.version>
<mysql.version>5.1.47</mysql.version>
<fastjson.version>1.2.62</fastjson.version>
</properties>
<dependencies>
<!-- servlet begin -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- servlet end -->
<!-- lombok begin -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- lombok end -->
<!-- junit begin -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- junit end -->
<!-- mysql-connector-java begin -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- mysql-connector-java end -->
<!-- fastjson begin 做数据转JSON格式 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- fastjson begin -->
<!-- 邮件发送需要的jar包 -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
<version>1.6.7</version>
</dependency>
<!-- 邮件发送需要的jar包end -->
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<!-- apache的commons-long 使用StringUtils.isEmpty()做非空校验 -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- apache的commons-long end>
</dependencies>
jdbc.properties
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/kh96_smbms?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8
user=root
password=root
2、登录 登出
2.1 系统常量
系统常量要习惯放在常量类中,方便以后的代码扩展和维护;
public class CommConstant {
//系统默认当前页码 为1
public static final Integer DEFAULT_INT_PAGE_NO = 1;
//系统默认 每页容量为 5
public static final Integer DEFAULT_INT_PAGE_SIZE = 5;
//系统默认提示信息
public static final String SYS_TIP_MESSAGE = \"message\";
//系统默认登录session信息 :id
public static final String SYS_USER_SESSION_ID = \"userId\";
public static final String SYS_USER_SESSION_USER_CODE = \"userCode\";
public static final String SYS_USER_SESSION_USER_PWD = \"userPwd\";
}
2.2 登录表单
<form class=\"loginForm\" action=\"${pageContext.request.contextPath }/userServlet?method=login\" name=\"actionForm\" id=\"actionForm\" method=\"post\" >
<div class=\"info\">${error }</div>
<div class=\"inputbox\">
<label for=\"user\">用户名:</label>
<input type=\"text\" class=\"input-text\" id=\"userCode\" name=\"userCode\" placeholder=\"请输入用户名\" required/>
</div>
<div class=\"inputbox\">
<label for=\"mima\">密码:</label>
<input type=\"password\" id=\"userPassword\" name=\"userPassword\" placeholder=\"请输入密码\"/>
</div>
<div class=\"subBtn\">
<input type=\"submit\" value=\"登录\"/>
<input type=\"reset\" value=\"重置\"/>
<input type=\"button\" id=\"codeLogin\" value=\"邮箱登录\"/>
</div>
</form>
2.3 登录方式
2.3.1 一般登录
- 获取用户名和密码,跳转到登录请求,查询用户是否存在;
- 存在将登录用户对象存放到sesssion域中(方便展示用户信息),跳转到用户展示页面;
- 不存在转发到登录页面(携带错误提示信息回来);
2.3.2 邮箱登录
- 输入用户名是判断用户是否开启邮箱登录(邮箱字段是否有值)
- 开启就可以使用邮箱登录按钮,不开启就不能使用
- 点击邮箱登录后,后台异步发送验证码,并跳转到邮件登录页面
授权码获取-> qq邮箱获取授权码
2.3.2.1 判断用户是否开启邮箱验证登录
开启,邮件登录按钮可以使用;
没有开启,邮件登录不可以使用;
是否开启邮箱验证登录javascript
//对验证码登录的处理
//一开始的验证码登录按钮不能使用,只有用户邮箱存在才可以使用
//这里有个问题,用户编码不唯一(用编码查询用户邮箱),最好使用唯一的字段进行登录,查邮箱的时候才好查找
//校验用户邮箱是否存在
//一开始 不可以使用邮箱登录,用户名正确才可以
$(\"#codeLogin\").attr(\"disabled\",\"true\");
$(\"#codeLogin\").css(\"background-color\",\"#aaa\");
$(\"#userCode\").blur(function () {
$.getJSON(\"userServlet?method=checkUserCodeExist\",{\"userCode\":$(\"#userCode\").val()} ,function(data){
//判断添加返回结果
//alert(data);
if(data == true){
//alert(\"用户邮箱存在\");
$(\"#codeLogin\").attr(\"disabled\",false);
$(\"#codeLogin\").css(\"background-color\",\"#54a4d7\"); //蓝色
}else{
//alert(\"用户没有开启邮箱登录!!!\");
$(\"#codeLogin\").attr(\"disabled\",true);
$(\"#codeLogin\").css(\"background-color\",\"#aaa\"); //灰色
}
});
});
是否开启邮箱验证servlet
//根据用户编码查看用户邮箱是否存在
public void checkUserCodeExist(HttpServletRequest req, HttpServletResponse resp) throws Exception {
System.out.println(\"=============根据用户编码查看用户邮箱是否存在=====================\");
//获取用户编码
String userCode = req.getParameter(\"userCode\");
//调用业务层查看用户邮箱是否存在
User emailLoginUser = userService.getUserByUserCode(userCode);
if(emailLoginUser != null && emailLoginUser.getUserEmail() != null){
//如果用户存在,且有邮箱
System.out.println(userCode+\"用户邮箱为===》userEmail=\"+emailLoginUser.getUserEmail());
//将用户存入session域中,当邮箱登录成功之后,用emailLoginUser 替换 loginUser
req.getSession().setAttribute(\"emailLoginUser\",emailLoginUser);
resp.getWriter().print(true);
}else{
System.out.println(userCode+\"用户没有开启邮箱登录!!!\");
resp.getWriter().print(false);
}
}
2.3.2.1 异步请求发送验证码
异步请求发送验证码javascript
//发送验证码 跳转到验证码登录页面
$(\"#codeLogin\").click(function () {
$.getJSON(\"userServlet?method=sendEmail\",null ,function(data){
//判断添加返回结果
//alert(data)
if(data == true){
alert(\"请注意接收验证码!!!\");
location.href = \"emailLogin.jsp\";
}else{
alert(\"验证码发送失败!!!\");
}
});
});
异步发送验证码servlet
//发送验证码
public void sendEmail(HttpServletRequest req, HttpServletResponse resp) throws Exception {
System.out.println(\"=============发送验证码=====================\");
//获取 session中的 emailLoginUser
User emailLoginUser = (User)req.getSession().getAttribute(\"emailLoginUser\");
//发送验证码
//随机生成6位 验证码
String emailCode = \"143233\";
System.out.println(\"验证码==》\"+emailCode);
//发送
//new SendEmilCode().sendCode(emailLoginUser.getUserEmail(),emailCode);
//多线程 异步发送
new Sendmail(emailLoginUser.getUserEmail(),emailCode).start();
//并将验证码存到session中,方便验证
req.getSession().setAttribute(\"emailCode\",emailCode);
resp.getWriter().print(true);
}
发送验证码工具类
public class Sendmail extends Thread {
//发邮件的人
private String from = \"发件人邮箱\";
//邮箱的用户名
private String username = \"邮箱的用户名\";
//邮箱的密码
private String password = \"邮箱授权码\";
//发送邮件的服务器地址
private String host = \"smtp.qq.com\";
//收邮件的人
private String loginUserEmail;
//发送打验证码
private String sendEmailCode;
public Sendmail(String loginUserEmail,String sendEmailCode){
this.loginUserEmail = loginUserEmail;
this.sendEmailCode = sendEmailCode;
}
//重写run方法的实现,在run方法中发送邮件给指定的用户
@Override
public void run() {
try{
Properties prop = new Properties();
prop.setProperty(\"mail.host\", host);
prop.setProperty(\"mail.transport.protocol\", \"smtp\");
prop.setProperty(\"mail.smtp.auth\", \"true\");
// 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put(\"mail.smtp.ssl.enable\", \"true\");
prop.put(\"mail.smtp.ssl.socketFactory\", sf);
//1、创建定义整个应用程序所需的环境信息的 Session 对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication(\"2663092414@qq.com\",\"gvxxjbnfmouoeacd\");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect(host, username, password);
//4、创建邮件
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from)); //发件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress(loginUserEmail)); //收件人
message.setSubject(\"《超市订单管理系统》登录验证码\"); //邮件的标题
String info = \"<h1 style=\'color: pink\'>尊敬的用户您的动态登录验证码为:\"+sendEmailCode+\",请不要将验证码转发给他人!!!</h1>\";
message.setContent(info, \"text/html;charset=UTF-8\");
message.saveChanges();
//发送邮件
ts.sendMessage(message, message.getAllRecipients());
ts.close();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
2.3.3 判断验证码是否正确
判断验证码javascript
//验证验证码是否正确
$(\"#emailLogin\").click(function () {
$.getJSON(\"userServlet?method=emailLogin\",{\"checkCode\":$(\"#checkCode\").val()} ,function(data){
//判断添加返回结果
//alert(data);
if(data == true){
alert(\"登录成功\");
location.href = \"${pageContext.request.contextPath}/jsp/frame.jsp\";
}else{
alert(\"验证码错误!!!\");
}
});
return false;
});
判断验证码servlet
//判断用户验证码是否正确
public void emailLogin(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(\"=============判断用户验证码是否正确 emailLogin =====================\");
//获取用户 输入的验证码
String checkCode = req.getParameter(\"checkCode\");
//获取session中 发送给用户的验证码
String emailCode = (String) req.getSession().getAttribute(\"emailCode\");
//判断验证码是否正确
//获取 session中的 emailLoginUser
User emailLoginUser = (User)req.getSession().getAttribute(\"emailLoginUser\");
if(checkCode.equals(emailCode)){
//登录成功
//用 emailLoginUser 替换session 中的 loginUser
req.getSession().setAttribute(\"loginUser\",emailLoginUser);
System.out.println(emailLoginUser.getUserCode()+\"用户邮箱验证登录成功!!!\");
resp.getWriter().print(true);
}else {
System.out.println(emailLoginUser.getUserCode()+\"用户邮箱验证登录失败!!!\");
resp.getWriter().print(false);
}
}
2.4 登出
- 跳转到用户退出请求
- 移除session中的用户对象
- 重定向到用户登录页面
<a href=\"${pageContext.request.contextPath }/userServlet?method=userLogOut\">退出</a>
3、分页条件查询
条件分页查询的重点在于,要拿到查询条件和分页条件;
为了方便获取参数,和在分页跳转的时候,方便 多页面 使用一个公用的跳转部分;
将分页参数隐藏在form表单中,提交表单的时候将分页参数一起提交;
3.1 html
userlist.jsp
<%@include file=\"/jsp/common/head.jsp\"%>
<div class=\"right\">
<div class=\"location\">
<strong>你现在所在的位置是:</strong>
<span>用户管理页面</span>
</div>
<div class=\"search\">
<form id=\"searchForm\" method=\"post\" action=\"${pageContext.request.contextPath }/userServlet?method=userList\">
<span>用户名:</span>
<input name=\"queryName\" class=\"input-text\" type=\"text\" id=\"queryName\" value=\"${(pageSupport.callBackInfo)[0]}\">
<span>用户角色:</span>
<select name=\"queryUserRole\">
<option value=\"0\" <c:if test=\"${(pageSupport.callBackInfo)[1] == 0 }\" > selected </c:if>>--请选择--</option>
<c:forEach items=\"${roleList}\" var=\"role\">
<option value=\"${role.id}\" <c:if test=\"${(pageSupport.callBackInfo)[1] == role.id }\" > selected </c:if>>--${role.roleName}--</option>
</c:forEach>
</select>
<!-- 当前页面参数 和 页面容量-->
<input type=\"hidden\" name=\"pageNo\" id=\"pageNo\" value=\"${pageSupport.currPageNo == null ? 1 : pageSupport.currPageNo}\"/>
<input type=\"hidden\" name=\"pageSize\" id=\"pageSize\" value=\"${pageSupport.pageSize == null ? 5 : pageSupport.pageSize}\"/>
<!-- 当前排序字段 和 排序方式-->
<input type=\"hidden\" name=\"orderBy\" id=\"orderBy\" value=\"${pageSupport.orderBy == null ? \'id\' : pageSupport.orderBy}\"/>
<input type=\"hidden\" name=\"ascOrDesc\" id=\"ascOrDesc\" value=\"${pageSupport.ascOrDesc == null ? \'asc\' : pageSupport.ascOrDesc}\"/>
<input value=\"查 询\" type=\"submit\" id=\"searchbutton\">
<a href=\"${pageContext.request.contextPath}/jsp/useradd.jsp\" >添加用户</a>
</form>
</div>
<!--用户-->
<table class=\"providerTable\" cellpadding=\"0\" cellspacing=\"0\">
<tr class=\"firstTr\">
<th width=\"10%\">用户编码</th>
<th width=\"20%\">用户名称</th>
<th width=\"10%\">性别</th>
<th width=\"10%\">年龄</th>
<th width=\"10%\">电话</th>
<th width=\"10%\">用户角色</th>
<th width=\"30%\">操作</th>
</tr>
<c:forEach items=\"${pageSupport.data}\" var=\"user\">
<tr>
<td>
<span>${user.userCode}</span>
</td>
<td>
<span>${user.userName}</span>
</td>
<td>
<span>${user.gender == 1 ? \"女\" : \"男\"}</span>
</td>
<td>
<span>${user.birthday}</span>
</td>
<td>
<span>${user.phone}</span>
</td>
<td>
<!-- 遍历用户角色列表 -->
<c:forEach items=\"${roleList}\" var =\"role\" varStatus=\"status\">
<!-- 根据用户的userRole 与 角色的 id 匹配对应的 角色 -->
<c:if test=\"${ role.id eq user.userRole}\" var=\"flag\">
<span>${role.roleName}</span>
</c:if>
</c:forEach>
</td>
<td>
<span><a class=\"viewUser\" href=\"${pageContext.request.contextPath }/userServlet?method=userInfo&id=${user.id}\" ><img src=\"${pageContext.request.contextPath }/images/read.png\" alt=\"查看\" title=\"查看\"/></a></span>
<span><a class=\"modifyUser\" href=\"${pageContext.request.contextPath }/userServlet?method=toUserMod&id=${user.id}\"><img src=\"${pageContext.request.contextPath }/images/xiugai.png\" alt=\"修改\" title=\"修改\"/></a></span>
<span><a class=\"deleteUser\" href=\"${pageContext.request.contextPath }/userServlet?method=userDel&id=${user.id}\" onClick=\"return confirm(\'是否确认删除${user.userName}用户\')\" ><img src=\"${pageContext.request.contextPath }/images/schu.png\" alt=\"删除\" title=\"删除\"/></a></span>
</td>
</tr>
</c:forEach>
</table>
<input type=\"hidden\" id=\"totalPageCount\" value=\"1\"/>
<c:import url=\"rollpage.jsp\">
<c:param name=\"totalCount\" value=\"1\"/>
<c:param name=\"currentPageNo\" value=\"1\"/>
<c:param name=\"totalPageCount\" value=\"1\"/>
</c:import>
</div>
</section>
<%@include file=\"/jsp/common/foot.jsp\" %>
3.2 pageSupport
主要有三类数据:
1、分页参数
2、回显参数 (条件查询的条件)
3、条件分页查询的数据
public class PageSupport<T> {
//当前页,显示页码
private int currPageNo = 1;
//页面容量
private int pageSize = 5;
//总条数(带条件查询的总条数)
private int totalCount;
//总页数(根据总条数和页面容量)
private int totalPage;
//分页条件查询的数据
private T data;
//回显 查询数据
private List<String> callBackInfo;
//排序字段
private String orderBy = \"id\";
//升序 还是 降序
private String ascOrDesc = \"asc\";
//设置总条数的时候 计算总页数
public void setTotalCount(int totalCount) {
//当存在总条数,确定总页数
this.totalCount = totalCount;
//计算总页数
this.totalPage = this.totalCount % this.pageSize == 0 ?
this.totalCount / this.pageSize :
this.totalCount / this.pageSize + 1;
}
public int getCurrPageNo() {
return currPageNo;
}
public void setCurrPageNo(int currPageNo) {
//页码特殊处理
if(currPageNo < 1 || this.totalCount == 0 ){
currPageNo = 1;
}else if(currPageNo > this.totalPage){
currPageNo = this.getTotalPage();
}
this.currPageNo = currPageNo;
}
.......
}
3.3 userList 方法
分页 条件查询用户列表
- 获取 条件查询参数
- 获取 分页参数pageNo,pageSize
- 获取 排序参数
- 条件查询 总条数
- 创建 分页对象(指定data的类型,一般 List)
- 设置 pageSize (必须先放pageSize)
- 设置 totalCount (再放totalCount),pageSupport计算总页数
- 创建 回显数据集合,放入需要回显的数据
- 查询分页条件查询的 数据集合List
- 将数据集合放入pageSupport的data中
- 将pageSupport放入request中,方便转发后 遍历数据,和 回显数据
- 查询角色列表(展示 用户信息 的时候 和 条件查询的 时候需要使用)
- 将角色列表集合放入session域中 (这一类需要经常使用的参数,可以放到session中,不过修改后要重置)
- 转发 到用户展示页面 userlist.jsp
// 分页 条件查询用户列表
public void userList(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(\"=============条件 分页 查询用户列表=====================\");
//获取 条件查询 参数
String queryName = req.getParameter(\"queryName\");
String queryUserRole = req.getParameter(\"queryUserRole\") == null ? \"0\" : req.getParameter(\"queryUserRole\");
//获取 分页 参数
//获取显示的当前页码
Integer pageNo = Integer.parseInt( req.getParameter(\"pageNo\") == null ? \"1\" : req.getParameter(\"pageNo\") );
Integer pageSize = Integer.parseInt( req.getParameter(\"pageSize\") == null ? \"5\" : req.getParameter(\"pageSize\") );
//排序条件
String orderBy = req.getParameter(\"orderBy\") == null ? \"id\" : req.getParameter(\"orderBy\");
String ascOrDesc = req.getParameter(\"ascOrDesc\") == null ? \"asc\" : req.getParameter(\"ascOrDesc\");
//根据条件查询获取用户 总数
int totalCount = userService.getUserListTotalByQueryNameAndQueryUserRole(queryName,Integer.parseInt(queryUserRole));
//创建分页对象
PageSupport<List<User>> pageSupport = new PageSupport<List<User>>();
//先放pageSize
pageSupport.setPageSize(pageSize);
//再放totalCount
pageSupport.setTotalCount(totalCount);
//创建回显数据
List callBackInfo = new ArrayList();
//pageSupport 中放入回显数据
//查询条件
callBackInfo.add(queryName);
callBackInfo.add(queryUserRole);
pageSupport.setCallBackInfo(callBackInfo);
//当前页码
pageSupport.setCurrPageNo(pageNo);
//页面容量
pageSupport.setPageSize(pageSize);
//排序条件
pageSupport.setOrderBy(orderBy);
//排序 方式 asc desc
pageSupport.setAscOrDesc(ascOrDesc);
//查询所有的用户详情列表
List<User> userList = userService.getUserListByQueryNameAndQueryUserRole(queryName,Integer.parseInt(queryUserRole),pageSupport);
System.out.println(\"=============条件 分页 查询用户列表 参数=============\");
System.out.println(\"查询参数==》queryName = \" + queryName);
System.out.println(\"查询参数==》queryUserRole = \" + queryUserRole);
System.out.println(\"排序参数==》orderBy = \" + orderBy);
System.out.println(\"排序参数==》ascOrDesc = \" + ascOrDesc);
System.out.println(\"分页参数==》pageNo = \" + pageNo);
System.out.println(\"分页参数==》pageSize = \" + pageSize);
System.out.println(JSON.toJSONStringWithDateFormat(userList,\"yyyy-MM-dd\"));
//req.setAttribute(\"userList\",userList);
//将数据放入分页对象中
pageSupport.setData(userList);
//将分页对象放进request域中
req.setAttribute(\"pageSupport\",pageSupport);
//查询所有的 用户角色
List<Role> roleList = roleService.findRoleList();
System.out.println(\"=============查询所有的用户角色===============\");
System.out.println(JSON.toJSONStringWithDateFormat(roleList,\"yyyy-MM-dd\"));
//将roleList 放进session域中,方便其他的地方直接调用,不用再次查询
req.getSession().setAttribute(\"roleList\",roleList);
//内部转发到用户列表页面
req.getRequestDispatcher( \"/jsp/userlist.jsp\").forward(req,resp);
//req.getContextPath()+\"/jsp/userlist.jsp\" 带项目名的时候不能这样会 拼接两次 项目名
//req.getRequestDispatcher( req.getContextPath()+\"/jsp/userlist.jsp\").forward(req,resp);
}
3.4 Dao层实现方法
3.4.1 selectUserListTotalByQueryNameAndQueryUserRole
条件查询用户列表 总数
//条件查询用户列表 总数
@Override
public int selectUserListTotalByQueryNameAndQueryUserRole(String queryName, Integer QueryUserRole) {
int total = 0;
//SQl
String executeSql = \"select count(1) as \'total\' \\n\"
+ \"from smbms_user where 1=1 \";
//params
List<Object> params = new ArrayList<Object>();
//拼接参数 和 sql
if(null != queryName && !\"\".equals(queryName)){
executeSql += \" and userName like concat(\'%\',?,\'%\') \";
params.add(queryName);
}
if(null != QueryUserRole && 0 != QueryUserRole){
executeSql += \" and userRole = ? \";
params.add(QueryUserRole);
}
try {
//执行
executeSelect(executeSql, params.toArray());
//处理数据
while (rs.next()) {
total = rs.getInt(\"total\");
}
}catch(Exception e){
e.printStackTrace();
}finally {
releaseResource(conn,pstmt,rs);
}
return total;
}
3.4.2 SelectUserListByQueryNameAndQueryUserRole
条件 分页 查询用户列表
1、定义返回的参数
2、定义sql
3、动态拼接查询条件
3、动态拼接查询参数(List
4、动态拼接分页条件
5、动态拼接分页参数(List
6、执行sql
7、处理数据
其中 timestampdiff(year,birthday, now()) 计算年龄的函数,最后说明;
//条件 分页 查询用户列表
@Override
public List<User> SelectUserListByQueryNameAndQueryUserRole(String queryName, Integer QueryUserRole, PageSupport pageSupport) {
List<User> userList = new ArrayList<User>();
//SQl
String executeSql = \"select id,userCode,userName,userPassword,gender,birthday,timestampdiff(year,birthday, now()) as userAge ,phone,address,userRole,createdBy,creationDate,modifyBy,modifyDate\\n\"
+ \"from smbms_user where 1=1 \";
//params
List<Object> paramList = new ArrayList<Object>();
//拼接参数 和 sql
if(null != queryName && !\"\".equals(queryName)){
executeSql += \" and userName like concat(\'%\',?,\'%\') \";
paramList.add(queryName);
}
if(null != QueryUserRole && 0 != QueryUserRole){
executeSql += \" and userRole = ? \";
paramList.add(QueryUserRole);
}
//增加分页SQL语句
executeSql += \" order by \"+pageSupport.getOrderBy()+ \" \" +pageSupport.getAscOrDesc()+\" limit ?,?\";
paramList.add((pageSupport.getCurrPageNo() - 1) * pageSupport.getPageSize());
paramList.add(pageSupport.getPageSize());
try {
//执行
executeSelect(executeSql, paramList.toArray());
//处理数据
while (rs.next()) {
User user = new User();
user.setId(rs.getInt(\"id\"));
user.setUserCode(rs.getString(\"userCode\"));
user.setUserName(rs.getString(\"userName\"));
user.setUserPassword(rs.getString(\"userPassword\"));
user.setGender(rs.getInt(\"gender\"));
user.setBirthday(rs.getDate(\"birthday\"));
user.setUserAge(rs.getInt(\"userAge\"));
user.setPhone(rs.getString(\"phone\"));
user.setAddress(rs.getString(\"address\"));
user.setUserRole(rs.getInt(\"userRole\"));
user.setCreatedBy(rs.getInt(\"createdBy\"));
user.setCreationDate(rs.getDate(\"creationDate\"));
user.setModifyBy(rs.getInt(\"modifyBy\"));
user.setModifyDate(rs.getDate(\"modifyDate\"));
userList.add(user);
}
}catch(Exception e){
e.printStackTrace();
}finally {
releaseResource(conn,pstmt,rs);
}
return userList;
}
角色列表查询省略;
不过如果角色列表有更改,需要重置session域中的角色列表集合数据;
3.5 分页跳转
- 点击分页跳转按钮,或者 切换分页条件,排序条件
- 将切换以后的分页参数,放到 表单的隐藏input中
- $(\"#searchForm\").submit(); 提交表单即可;(每个页面的表单各自提交,分页部分Javascript就可以复用)
3.5.1 分页html
<div class=\"page-bar\">
<ul class=\"page-num-ul clearfix\">
<li>共 ${pageSupport.totalCount} 条记录
<span id=\"currPageNo\">${pageSupport.currPageNo}</span>
/
<span id=\"totalPage\">${pageSupport.totalPage}</span> 页</li>
<a href=\"javaScript:void(0);\" >首页</a>
<a href=\"javaScript:void(0);\" >上一页</a>
<a href=\"javaScript:void(0);\" >下一页</a>
<a href=\"javaScript:void(0);\" >最后一页</a>
每页<select name=\"currentPageSize\" id=\"currentPageSize\">
<option value=\"3\" <c:if test=\"${pageSupport.pageSize == 3 }\" > selected </c:if>>3</option>
<option value=\"5\" <c:if test=\"${pageSupport.pageSize == 5 }\" > selected </c:if>>5</option>
<option value=\"10\" <c:if test=\"${pageSupport.pageSize == 10 }\" > selected </c:if>>10</option>
</select>条
根据<select name=\"currentOrderBy\" id=\"currentOrderBy\">
<option value=\"id\" <c:if test=\"${pageSupport.orderBy == \'id\' }\" > selected </c:if>> id </option>
<option value=\"creationDate\" <c:if test=\"${pageSupport.orderBy == \'creationDate\' }\" > selected </c:if>>创建时间</option>
</select>
<select name=\"currentAscOrDesc\" id=\"currentAscOrDesc\">
<option value=\"asc\" <c:if test=\"${pageSupport.ascOrDesc == \'asc\' }\" > selected </c:if>>升序</option>
<option value=\"desc\" <c:if test=\"${pageSupport.ascOrDesc == \'desc\' }\" > selected </c:if>>降序</option>
</select>查询
</ul>
<span class=\"page-go-form\"><label>跳转至</label>
<input type=\"text\" name=\"inputPage\" id=\"inputPage\" class=\"page-key\" />页
<button type=\"button\" class=\"page-btn\" >GO</button>
</span>
</div>
3.5.2 页面跳转处理
首页,上一页,下一页,尾页,及上一页和下一页的 隐藏;
//分页跳转
//首页
$(\".page-num-ul a:eq(0)\").click(function(){
//获取id为pageNo的input标签,并给value属性赋值
// $(\"#pageNo\").val(1);
//获取表单,并给表单name为pageNo的input标签赋值
document.forms[0].pageNo.value = 1;
$(\"#searchForm\").submit();
});
// 上一页
$(\".page-num-ul a:eq(1)\").click(function(){
// $(\"#pageNo\").val(parseInt($(\"#currPageNo\").text()) - 1);
document.forms[0].pageNo.value = parseInt($(\"#currPageNo\").text()) - 1;
$(\"#searchForm\").submit();
});
// 下一页
$(\".page-num-ul a:eq(2)\").click(function(){
// $(\"#pageNo\").val(parseInt($(\"#currPageNo\").text()) + 1);
document.forms[0].pageNo.value = parseInt($(\"#currPageNo\").text()) + 1;
$(\"#searchForm\").submit();
});
// 尾页
$(\".page-num-ul a:eq(3)\").click(function(){
// $(\"#pageNo\").val(parseInt($(\"#totalPage\").text()));
document.forms[0].pageNo.value = parseInt($(\"#totalPage\").text());
$(\"#searchForm\").submit();
});
//上一页,下一页隐藏处理
//上一页
if($(\"#currPageNo\").text() == \"1\"){
//alert($(\"#currPageNo\").text());
$(\".page-num-ul a:eq(1)\").hide();
}else {
$(\".page-num-ul a:eq(2)\").show();
}
//下一页
if($(\"#currPageNo\").text() == $(\"#totalPage\").text()){
//alert($(\"#currPageNo\").text());
$(\".page-num-ul a:eq(2)\").hide();
//.css(\"display\",\"none\");
}else {
//alert($(\"#currPageNo\").text());
$(\".page-num-ul a:eq(2)\").show();
//.css(\"display\",\"inline\");
}
//跳到指定页数
$(\".page-btn\").click(function () {
var $inputPage = $(\"#inputPage\");
if($inputPage.val() < 0 || $inputPage.val() > parseInt($(\"#totalPage\").text())){
alert(\"请输入正确的页数!!!\");
}else{
//修改表单中的当前页
// $(\"#pageNo\").val($inputPage.val());
document.forms[0].pageNo.value = $inputPage.val();
$(\"#searchForm\").submit();
}
});
3.5.3 修改分页条件,或排序条件
select的$(\"#selected\").change(function(){});
切换select选项后触发change事件;
修改每页页面大小
//修改每页页面大小 重新查询
$(\"#currentPageSize\").change(function(){
//获取修改后的 currentPageSize
var currentPageSize = $(this).children(\'option:selected\').val();
//alert(currentPageSize);
//修改提交表单的pageSize
// $(\"#pageSize\").val(currentPageSize);
document.forms[0].pageSize.value = currentPageSize;
//修改页面大小后,再主动查询一次动漫数据
//将当前页数,重置为1
// $(\"#pageNo\").val(1);
document.forms[0].pageNo = 1;
$(\"#searchForm\").submit();
});
修改查询条件
//修改查询条件
$(\"#currentOrderBy\").change(function(){
//获取修改后的 currentOrderBy
var currentOrderBy = $(this).children(\'option:selected\').val();
//修改提交表单的orderBy
// $(\"#orderBy\").val(currentOrderBy);
document.forms[0].orderBy.value = currentOrderBy;
//修改页面大小后,再主动查询一次动漫数据
//将当前页数,重置为1
// $(\"#pageNo\").val(1);
document.forms[0].pageNo.value = 1;
$(\"#searchForm\").submit();
});
修改升序或降序
//升序或降序
$(\"#currentAscOrDesc\").change(function(){
//获取修改后的 currentAscOrDesc
var currentAscOrDesc = $(this).children(\'option:selected\').val();
//修改提交表单的orderBy
// $(\"#ascOrDesc\").val(currentAscOrDesc);
document.forms[0].ascOrDesc.value = currentAscOrDesc;
//修改页面大小后,再主动查询一次动漫数据
//将当前页数,重置为1
// $(\"#pageNo\").val(1);
document.forms[0].pageNo.value = 1;
$(\"#searchForm\").submit();
});
4、查看详情
- 携带用户id跳转到用户详情请求
- 根据用户id查询到用户信息
- 存放在request域中
- 转发到用户详情页面
- EL表达式取出用户数据
查看详情a标签
<a class=\"viewUser\" href=\"${pageContext.request.contextPath }/userServlet?method=userInfo&id=${user.id}\" > 查看用户详情
5、修改用户
- 携带用户id到用户修改请求
- 根据id查询出用户信息
- 存放到request域中
- 转发到用户修改页面
- EL表达式取出用户数据(注意隐藏用户id)
用户修改a标签
<a class=\"modifyUser\" href=\"${pageContext.request.contextPath }/userServlet?method=toUserMod&id=${user.id}\">修改用户
- 修改完数据,表单提交到用户修改请求
- 用户信息修改成功后,跳转到用户条件分页查询请求,重新查询数据
用户修改页面的form表单请求
<form id=\"userForm\" name=\"userForm\" method=\"post\" action=\"${pageContext.request.contextPath}/userServlet?method=userMod\">
6、删除用户
- 携带用户id到用户删除请求
- 删除成功后,跳转到用户条件分页查询请求,重新查询数据
<a class=\"deleteUser\" href=\"${pageContext.request.contextPath }/userServlet?method=userDel&id=${user.id}\" onClick=\"return confirm(\'是否确认删除${user.userName}用户\')\" >
7、增加用户
- 跳转到用户添加页面
- 填写用户信息
- 表单提交到用户添加请求
- 添加完用户后,跳转到用户条件分页查询请求,重新查询数据
添加用户a标签
<a href=\"${pageContext.request.contextPath}/jsp/useradd.jsp\" >添加用户</a>
用户添加页面的用户添加请求表单
<form id=\"userForm\" name=\"userForm\" method=\"post\" action=\"${pageContext.request.contextPath }/userServlet?method=userAdd\">
8、修改用户密码
- 校验两次用户输入的新密码是否一样
- 判断用户的旧密码是否正确(用户密码要从数据库中查询)
- 根据登录的id修改用户密码
- 修改成功,移除session中的登录用户对象
- 重定向到跳转到用户登录页面
9、注意点
9.1 tomcat项目启动不起来
注意看路径映射是否有问题;(有没有少写 \"/\")
9.2 css获取到,但是渲染有问题
报错信息:Resource interpreted as Stylesheet but transferred with MIME type text/html;
字符编码拦截器单独对css文件的解析类型进行处理
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//设置post请求字符集 encoding为设置映射路径时,设置的初始化字符编码
servletRequest.setCharacterEncoding(encoding);
HttpServletRequest request = (HttpServletRequest) servletRequest;
//静态资源放行
//获取资源名
String url=request.getRequestURI();
//如果资源名包含css样式表、js样式表就特殊处理然后放行
if(url.contains(\".css\")) {
servletResponse.setContentType(\"text/css; charset=UTF-8\");
servletResponse.setCharacterEncoding(this.encoding);
System.out.println(\"css放行\");
//放行请求
filterChain.doFilter(servletRequest,servletResponse);
}else {
//设置响应字符集
servletResponse.setContentType(\"text/html; charset=UTF-8\");
servletResponse.setCharacterEncoding(this.encoding);
//放行请求
filterChain.doFilter(servletRequest,servletResponse);
}
}
9.3 自动导包问题
有时候自动导包导致不是自己想要的包,直接用全类名即可;
主要会再使用@WebServlet 和 @WebFilter 注解后会出现这个问题
javax.servlet.http.HttpServlet
@WebServlet(name = \"userServlet\",urlPatterns = \"/userServlet\")
public class UserServlet extends javax.servlet.http.HttpServlet{......}
javax.servlet.Filter
@WebFilter(filterName = \"characterEncodingFilter\",urlPatterns = \"/*\",initParams = {
@WebInitParam(name = \"encoding\",value = \"utf-8\")
})
//
public class CharacterEncodingFilter implements javax.servlet.Filter {......}
9.4 form表单提交 拼接路径问题
form表单的action拼接路径,注意再get提交方式时不能拼接参数,在post提交方式可以;
form表单提交方式 | action是否可以拼接参数 |
---|---|
get | 不可以(实在要使用get就在input中隐藏,这样get和post都可以) |
post | 可以 |
get提交
get提交由于不能拼接参数,所以将method参数隐藏在表单中;
action=\"${pageContext.request.contextPath }/billServlet\"
<form id=\"searchForm\" method=\"get\" action=\"${pageContext.request.contextPath }/billServlet\">
<input name=\"method\" type=\"hidden\" value=\"billList\">
......
</form>
post提交
post提交可以直接拼接参数,也可以将method参数隐藏在表单中;
action=\"${pageContext.request.contextPath }/billServlet?method=billList\"
<form id=\"searchForm\" method=\"post\" action=\"${pageContext.request.contextPath }/billServlet?method=billList\">
......
</form>
9.5转发和重定向到底要不要 + req.getContextPath()
9.5.1 req.getContextPath()
首先要知道 req.getContextPath() 获取到的是什么内容?
如果发布的项目路径为:/kh96_smbms
System.out.println(\" req.getContextPath()==》\"+req.getContextPath());
// req.getContextPath()==》 /kh96_smbms 注意它前面有 /,这个是重点
如果发布的项目名为:/
System.out.println(\" req.getContextPath()==》\"+req.getContextPath());
// req.getContextPath()==》 什么都没有,包括我们之前写发布名时的 / 也没有
知道 req.getContextPath() 获取的是什么我们就 恍然大悟了;
9.5.2 再看转发和重定向的路径区别
转发和重定向的路径区别:
- 重定向路径中如果有 \"/\",只会获取到 站点,然后拼接上我们写的路径;
- 转发路径中如果有 \"/\",会先获取到 站点 + 项目名,再拼接上我们写的路径;
所以重定向:(前提自己写的路径前有 /)
-
如果有项目名,我们一定要 加上 req.getContextPath(),获取到项目名,再拼接跳转的路径;
-
如果没有项目名,我们加上或不加上,都可以;
转发:(前提自己写的路径前有 /)
- 如果有项目名,我们不能 加上 req.getContextPath(),如果加上会多拼接上一个项目名,而找不到路径;
- 如果没有项目名,我们加上或不加上,都可以;
总结:(前提自己写的路径前有 /)
- 没有项目名,加不加 req.getContextPath() 都可以,不过建议加上;
- 有项目名:
- 重定向一定要加req.getContextPath() ;
- 转发一定不能加req.getContextPath() ;
10、sql的时间差函数
参考博客
用来计算时间的差距,年龄,距上一次登录多少天等等;
10.1 datediff()函数
只比较日期
DATEDIFF() 函数返回两个日期之间的天数。
date1 和 date2 参数是合法的日期或日期/时间表达式。 只有值的日期部分参与计算。
测试一下MySQL:
SELECT DATEDIFF(\'2018-05-09 08:00:00\',\'2018-05-09\') AS DiffDate;
//结果 0 ; 表示 2018-05-09 与 2018-05-09之间没有日期差。这里是不比较时分秒的。下面验证带上时分秒有没有差别。
SELECT DATEDIFF(\'2018-05-09 00:00:00\',\'2018-05-09 23:59:59\') AS DiffDate;
//结果 0 ;
SELECT DATEDIFF(\'2018-05-08 23:59:59\',\'2018-05-09 00:00:00\') AS DiffDate;
//结果 -1;
SELECT DATEDIFF(\'2018-05-09 00:00:00\',\'2018-05-08 23:59:59\') AS DiffDate;
//结果 1;
10.2timestampdiff()
可以计算,年,月,日的差距;
select timestampdiff(YEAR,\"2018-01-01 15:15:16\",\"2019-08-23 15:15:16\") as timestamodiff;
//结果1。相差一年。
select timestampdiff(YEAR,\"2019-08-22 15:15:19\",\"2018-12-23 15:15:16\") as timestamodiff;
//结果 -1,也是相差一年。
select timestampdiff(YEAR,\"2019-08-22 15:15:19\",\"2018-08-22 15:15:16\") as timestamodiff;
//结果0,相差不到一年
select timestampdiff(MONTH,\"2018-08-22 15:15:16\",\"2018-07-23 15:15:16\") as timestamodiff;
// 结果 0 相差不到一个月
select timestampdiff(MONTH,\"2018-08-22 15:15:16\",\"2018-07-01 15:15:16\") as timestamodiff;
// 结果 -1 相差一个月
select timestampdiff(MONTH,\"2018-08-22 15:15:19\",\"2018-09-23 15:15:16\") as timestamodiff;
// 结果 1 想差一个月
select timestampdiff(DAY,\"2018-08-22 15:15:16\",\"2018-08-23 15:15:16\") as timestamodiff;
// 结果 1 想差一天
select timestampdiff(DAY,\"2018-08-22 15:15:19\",\"2018-08-23 15:15:16\") as timestamodiff;
// 结果 0 想差不到一天
select timestampdiff(DAY,\"2018-08-23 15:15:19\",\"2018-08-22 15:15:16\") as timestamodiff;
// 结果 -1 想差一天
来源:https://www.cnblogs.com/xiaoqigui/p/16594687.html
本站部分图文来源于网络,如有侵权请联系删除。