JavaWeb自学笔记(二)
学习视频:BV12J411M7Sj
文章目录
8、JSP
Java Server Pages
: Java服务端页面,和Servlet一样,用于动态web技术
写法和html相近
区别:
- html只给用户静态数据
- jsp页面中可以潜伏java代码,可以给用户提供动态数据
8.1 JSP原理
问:jsp是怎么运行的?
-
代码层面jsp没有变化
-
服务器中
(根据系统配置可能有所不同)查看自己的
用户/AppData/local/JetBrains/IntelliJidea/tomcat
路径中有一个work目录。
浏览器想服务器发送请求,不管访问什么资源,其实都在访问Servlet。
jsp最终会被转换成java类,这个类继承了Servlet
jsp生成的类中有三个常见方法
//初始化
public void jspInit() {
}
//销毁
protected void _jspDestroy() {
}
//JSPService
public void _jspService(HttpServletRequest var1, HttpServletResponse var2) ;
-
判断请求
-
内置了一些对象
final javax.servlet.jsp.PageContext pageContext; //页面上下文 javax.servlet.http.HttpSession session = null; //session final javax.servlet.ServletContext application; //applicationContext final javax.servlet.ServletConfig config; //config javax.servlet.jsp.JspWriter out = null; //out final java.lang.Object page = this; //page:当前 HttpServletRequest request; //请求 HttpServletResponse response; //响应
-
输出页面前增加的代码
response.setContentType("text/html"); //设置相应页面类型 pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("<html>\n"); out.write("<body>\n"); out.write("<h2>Hello Wd!</h2>\n"); out.write("</body>\n"); out.write("</html>\n");
-
以上的对象可以在jsp中直接使用
<html> <body> <h2>Hello World!</h2> <% //这里调用java对象 String name="alice"; %> name:<%=name%> </body> </html>
在jsp页面中,java代码会原封不动地输出,html代码都会专用out.write写入。
8.2 JSP基本语法
需要的依赖
<dependencies>
<!-- servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!-- jsp依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- JSTL表达式依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- standard标签库-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
jsp支持java语法
8.2.1 jsp表达式
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- JSP表达式
作用:将程序的输出放到客户端
用法 <%= 变量或表达式%>
--%>
<%= new java.util.Date()%>
</body>
</html>
8.2.2 jsp脚本片段
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- JSP表达式
作用:将程序的输出放到客户端
用法 <%= 变量或表达式%>
--%>
<%= new java.util.Date()%>
<%--jsp脚本片段--%>
<%
int sum=0;
for(int i=0;i<50;i++){
sum+=i;
out.println("<h1>sum["+i+"]="+sum+"</h1>");
}
%>
</body>
</html>
8.2.3 脚本片段再实现
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%--jsp脚本片段1--%>
<%
int sum=0;
for(int i=0;i<50;i++){
sum+=i;
out.println("<h1>sum["+i+"]="+sum+"</h1>");
}
%>
<%--jsp脚本片段2--%>
<%
int b=100;
%>
</body>
</html>
一个jsp页面下的脚本片段处于同一个作用域中。
<%-- 在脚本中嵌入html元素--%>
<%
for(int i=0;i<5;i++){
%>
<h1> xxxxxtyyyyy <%=i%> </h1>
<% } %>
8.2.4 jsp声明
<%!
static{
System.out.println("loading page");
}
private int globalvar=110000;
public void staticMethod(){
System.out.println("this is a static method");
}
%>
注:JSP声明会被编译到JSP生成的java类中。其他的脚本会被生成到_jspService
方法中。
<!--HTML注释-->
<%--JSP注释--%>
HTML的注释可以在客户端显示,JSP注释不会。
8.3 jsp指令
<%@page args......%>
<%@ include file="xxx"%>
自定义错误页面
目录结构
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%-- 如果不在web.xml中配置错误跳转的话,可以加上这一句
<%@ page errorPage="error/500.jsp" %>
--%>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
//算数错误会跳转到500
int x=1/0;
%>
</body>
</html>
500.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--定制的500错误页面--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1 align="center" font-color="red">500</h1>
<img src="${pageContext.request.contextPath}/img/500page.png" alt="null">
</body>
</html>
404.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1 align="center" font-color="red">404</h1>
<img src="${pageContext.request.contextPath}/img/404page.jpeg" alt="null">
</body>
</html>
web.xml
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
测试效果
网页拼接
header.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>我是header</h1>
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>我是footer</h1>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--<%@ page errorPage="error/500.jsp" %>--%>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- 三个页面合并为一个,这里要注意合并的页面中是否有重名的变量--%>
<%@ include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@ include file="common/footer.jsp"%>
<hr>
<%-- jsp标签
拼接页面,本质还是三个页面--%>
<jsp:include page="common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="common/footer.jsp"/>
</body>
</html>
8.4 9个内置对象
- PageContext 存储
- Request 存储
- Response
- Session 存储
- Application ServletContext 存储
- config ServletConfig
- out
- page 不用了解
- exception
<%
//保存的数据只在一个页面中有效
pageContext.setAttribute("name1","robot1");
//保存的数据只在一次请求中有效,请求转发会携带这个数据
request.setAttribute("name2","robot2");
//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
session.setAttribute("name3","robot3");
//保存的数据只在服务器中有效,从打开服务器到关闭服务器
application.setAttribute("name4","robot4");
%>
request:客户端向服务器发送请求,产生的数据,用户看完就没用了。如:新闻,看完就可以直接删除。
session:客户端向服务器发送请求,产生的数据,用户用完后可能还会用。如:购物车。
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用。如:聊天程序。
8.5 JSP标签、JSTL标签、EL表达式
需要的依赖
<!-- JSTL表达式依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- standard标签库-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表达式:${}
- 获取数据
- 执行运算
- 获取web开发的常用对象(不常用)
jsp表达式
参数传递测试
<%--jsptag.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
http://localhost:8080/jsptag.jsp?name=infinite&age=123
--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="infinite"></jsp:param>
<jsp:param name="age" value="123"></jsp:param>
</jsp:forward>
</body>
</html>
<%--jsptag2.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--取出参数--%>
用户: <%=request.getParameter("name")%>
age:<%=request.getParameter("age")%>
</body>
</html>
JSTL标签
https://www.runoob.com/jsp/jsp-jstl.html
目的:扩展标签的功能
核心标签 (重要)
格式化标签
SQL标签
XML标签
JSTL使用步骤
- 引入对于的taglib
- 使用其中的方法
- 在tomcat中要引入相关的jstl包,否则会报错:JSTL解析错误
管理员登录
coretag.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--通过 taglib引入标签库--%>
<%-- 标签库的位置上网复制即可--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>if 测试</h4>
<hr>
<form action="coretag.jsp" method="get">
<%--
EL表达式获取表单中的数据
${param.参数名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>
<%--判断是不是管理员--%>
<c:if test="${param.username=='admin'}" var="isadmin">
<c:out value="管理员登录"/>
</c:if>
<c:out value="${isadmin}"></c:out>
</body>
</html>
测试结果
成绩评定
corewhen.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--定义一个变量score 值为85--%>
<c:set var="score" value="85"/>
<c:choose>
<c:when test="${score>=90}">
A
</c:when>
<c:when test="${score>=80}">
B
</c:when>
<c:when test="${score>=70}">
C
</c:when>
<c:when test="${score>=60}">
D
</c:when>
<c:when test="${score<60}">
E
</c:when>
</c:choose>
</body>
</html>
遍历数组
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
ArrayList<String> people = new ArrayList<>();
people.add(0,"张三");
people.add(1,"李四");
people.add(2,"王五");
people.add(3,"赵六");
people.add(4,"田七");
request.setAttribute("list",people);
%>
<%--var 每次遍历的变量
items 要遍历的对象
--%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/><br>
</c:forEach>
<hr>
<%-- for(int i=1;i<=3;i+=2)--%>
<c:forEach var="people" items="${list}" begin="1" end="3" step="2">
<c:out value="${people}"/> <br>
</c:forEach>
</body>
</html>
9、JavaBean
实体类
JavaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM(对象关系映射)
- 表–>类
- 字段–>属性
- 行记录–>对象
People.java
假设有一个存储个人信息的数据表。people对象代表相关记录
package com.infinite.pojo;
public class People {
private int id;
private String name;
private int age;
private String address;
//constructor()
//getter() and setter()
}
javabean.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
//People people=new People();
//people.setAddress();
//.....
//people.getAddress();
//.....
%>
<jsp:useBean id="people" class="com.infinite.pojo.People"/>
<jsp:setProperty name="people" property="address" value="A市"/>
<jsp:setProperty name="people" property="age" value="18"/>
<jsp:setProperty name="people" property="id" value="250"/>
<jsp:setProperty name="people" property="name" value="alice"/>
姓名:<jsp:getProperty name="people" property="name"/>
id:<jsp:getProperty name="people" property="id"/>
年龄:<jsp:getProperty name="people" property="age"/>
地址:<jsp:getProperty name="people" property="address"/>
</body>
</html>
测试效果
10、MVC三层架构
MVC: Model、view、Controller 模型、视图、控制器
10.1 早期的架构
用户直接访问控制层,控制层可以直接操作数据库
servlet-->CRUD-->db
缺点:程序臃肿,难维护
servlet的代码包括:处理请求、响应、试图跳转、处理JDBC、处理业务代码、处理逻辑代码
JDBC作为数据库操作的中间件,相当于在控制层和数据库之间又多了一层,用于解决Mysql、Oracle、SqlServer等不同厂商数据库的兼容性问题。同样的中间件还有ODBC、QODBC(QT相关)
注:虽然JSP也可以嵌入java代码,但是为了加强代码的可维护性,要尽量避免这么做。其他层同理。
10.2、改进的MVC三层架构
Model
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD(Dao)
View
- 展示数据
- 提供链接发起Servlet请求(a、form、img…)
Controller(Servlet)
- 接受用户请求:(req:请求参数、session信息)
- 交给业务层处理对应的代码
- 控制视图的跳转
一个登录的流程
登录-->接受用户的登录请求-->处理用户的请求(获取用户的登录参数:username、password)-->交给业务层处理登陆业务(判断用户名密码是否正确:事务)-->Dao层查询用户名和密码是否正确-->db
11、Filter(过滤器)
目的:过滤网站的数据
- 处理中文乱码
- 登录验证
跟Servlet一样,要实现过滤器,可以通过相关的接口实现。
11.1 将消息过滤为utf-8编码
目录
ShowServlet.java
package com.infinite.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//resp.setCharacterEncoding("utf-8"); 该操作交给过滤器实现
resp.getWriter().write("张三李四"); //若不加处理会直接显示一堆问号
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
CharacterEncodingFilter
package com.infinite.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化完成");
}
//chain: 链。可能有好几个过滤器
/*
1.过滤器中的所有代码,在过滤特定请求的时候都会执行
2.必须要让过滤器执行
filterChain.doFilter(servletRequest,servletResponse)方法
* */
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
System.out.println("过滤器执行前");
filterChain.doFilter(servletRequest,servletResponse); //让请求继续执行,否则程序会被截止
System.out.println("过滤器执行后");
}
//销毁:web服务器关闭后,过滤器会销毁
@Override
public void destroy() {
System.out.println("CharacterEncodingFilter已销毁");
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>com.infinite.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.infinite.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- 只要是/servlet下的请求,都会经过这个过滤器-->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
</web-app>
测试效果
12、监听器
现已不常用
实现一个监听器接口,用以观察并反馈用户的动作
查看同时在线人数
OnlineCountListener.java
package com.infinite.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineCountListener implements HttpSessionListener {
//创建session监听器
//一旦创建session就会触发这个事件
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
ServletContext ctx = httpSessionEvent.getSession().getServletContext();
Integer onlineCount=(Integer) ctx.getAttribute("OnlineCount");
if(onlineCount==null){
onlineCount=new Integer(1);
}
else{
int count=onlineCount.intValue();
onlineCount=new Integer(count+1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
//销毁session监听器
//一旦销毁session就会触发这个事件
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
ServletContext ctx = httpSessionEvent.getSession().getServletContext();
Integer onlineCount=(Integer) ctx.getAttribute("OnlineCount");
System.out.println(httpSessionEvent.getSession().getId());
if(onlineCount==null){
onlineCount=new Integer(0);
}
else{
int count=onlineCount.intValue();
onlineCount=new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
}
/*
session的销毁:
1.手动销毁 getSession().invalidate();
2.自动销毁 web.xml中自定义session过期时间
* */
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>当前有<span><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span></h1>
</body>
</html>
web.xml
<!-- 注册监听器-->
<listener>
<listener-class>com.infinite.listener.OnlineCountListener</listener-class>
</listener>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
测试效果
13、过滤器、监听器的常见应用
监听器:GUI中常用
用户登录跳转
需求:用户登录后才能进入主页,注销后不能再进入主页
-
用户登录后,向Session中放入用户的数据
-
进入主页的时候要判断用户是否已经登录。(用过滤器实现)
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest) servletRequest; HttpServletResponse response=(HttpServletResponse) servletResponse; if(request.getSession().getAttribute(Constant.USER_SESSION)==null){ response.sendRedirect("/error.jsp"); } filterChain.doFilter(servletRequest,servletResponse); }
目录
SysFilter.java
package com.infinite.filter;
import com.infinite.util.Constant;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest) servletRequest;
HttpServletResponse response=(HttpServletResponse) servletResponse;
System.out.println(request.getSession().getAttribute(Constant.USER_SESSION));
if(request.getSession().getAttribute(Constant.USER_SESSION)==null){
response.sendRedirect("/error.jsp");
}
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
LoginServlet
package com.infinite.servlet;
import com.infinite.util.Constant;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取前端请求参数
String username = req.getParameter("username");
if(username.equals("admin")){ //登录成功
req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");
}
else{
resp.sendRedirect("/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
LogoutServlet
package com.infinite.servlet;
import com.infinite.util.Constant;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_session=req.getSession().getAttribute(Constant.USER_SESSION);
if(user_session!=null){
req.getSession().removeAttribute(Constant.USER_SESSION);
resp.sendRedirect("/login.jsp");
}
else{
resp.sendRedirect("/login.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录</h1>
<form action="/servlet/login" method="post">
<input type="text" name="username" required>
<input type="submit">
</form>
</body>
</html>
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1 align="center" font-color="red">用户名错误或没有权限</h1>
<a href="/login.jsp">返回登录页面</a>
</body>
</html>
sys/success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>主页</h1>
<p><a href="/servlet/logout">注销</a></p>
</body>
</html>
web.xml
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.infinite.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.infinite.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.infinite.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
测试效果
14、JDBC
目的:为不同厂商的数据库提供统一驱动接口
14.1、基本用法
users表
CREATE TABLE `users` (
`id` int NOT NULL,
`name` varchar(40) DEFAULT NULL,
`password` varchar(40) DEFAULT NULL,
`email` varchar(60) DEFAULT NULL,
`birthday` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO users(id,name,password,email,birthday) VALUES(1,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO users(id,name,password,email,birthday) VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO users(id,name,password,email,birthday) VALUES(3,'王五','123456','ww@qq.com','2000-01-01');
pom.xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
TestJdbc.java
package com.infinite.jdbc;
import java.sql.*;
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 用以防止中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库 。 数据库对象
Connection connection = DriverManager.getConnection(url, username, password);
//3.向数据库发送SQL语句的对象statement。可用于执行SQL语句
Statement statement = connection.createStatement();
//4.编写SQL。此处返回查询的结果集
String sql="select * from users";
ResultSet resultSet = statement.executeQuery(sql);
//4.1增删改
//sql="delete from users where id=a";
//int i=statement.executeUpdate(sql);
while(resultSet.next()){
System.out.println("id="+resultSet.getObject("id"));
System.out.println("name="+resultSet.getObject("name"));
System.out.println("password="+resultSet.getObject("password"));
System.out.println("email="+resultSet.getObject("email"));
System.out.println("birthday="+resultSet.getObject("birthday"));
}
//6.关闭数据库连接
resultSet.close();
statement.close();
connection.close();
}
}
测试效果
14.2 预编译sql用法
package com.infinite.jdbc;
import java.sql.*;
import java.util.Date;
public class TestJdbc2 {
public static void main(String[] args) throws Exception {
//配置信息
//useUnicode=true&characterEncoding=utf-8 用以防止中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库。 数据库对象
Connection connection = DriverManager.getConnection(url, username, password);
//3.使用预编译SQL
String sql="insert into users(id,name,password,email,birthday) value(?,?,?,?,?);";
//4.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,4); //给第一个'?'占位符设置值
preparedStatement.setString(2,"赵六"); //给第二个'?'占位符设置值
preparedStatement.setString(3,"123456");
preparedStatement.setString(4,"zl@qq.com");
preparedStatement.setDate(5, new java.sql.Date(new java.util.Date().getTime()));
//5.执行SQL
int i=preparedStatement.executeUpdate();
if(i>0) {
System.out.println("插入成功");
}
//6.关闭数据库连接
preparedStatement.close();
connection.close();
}
}
junit单元测试
@Test
pom.xml
<!-- 单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
TestJdbc3.java
package com.infinite.jdbc;
import org.testng.annotations.Test;
public class TestJdbc3 {
//这里可以直接运行,不必启动main方法
@Test
public void test(){
System.out.println("Hello");
}
}
测试效果
事务
ACID:原子性、一致性、隔离性、持久性。 目的:保护数据的安全
开启事务
事务提交
事务回滚
关闭事务
A:1000
B:1000
A(900)--100-->B(1100)
account表
CREATE TABLE `account` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(40) DEFAULT NULL,
`money` float DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO account('name',money) VALUES('A',1000);
INSERT INTO account('name',money) VALUES('B',1000);
INSERT INTO account('name',money) VALUES('C',1000);
TestJdbc3.java
package com.infinite.jdbc;
import org.testng.annotations.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestJdbc3 {
@Test
public void test() throws Exception {
//配置信息
//useUnicode=true&characterEncoding=utf-8 用以防止中文乱码
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
Connection connection=null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库 。 数据库对象
connection = DriverManager.getConnection(url, username, password);
//3.通知数据库开启事务。此处关闭了自动提交
connection.setAutoCommit(false);
String sql = "update account set money=money-100 where name-'A'";
connection.prepareStatement(sql).executeUpdate();
//制造异常
//int i = 1 / 0;
String sql2 = "update account set money=money-100 where name-'B'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();
System.out.println("success");
}
catch (Exception e){
try{
connection.rollback();
}
catch (SQLException e1){
e1.printStackTrace();
}
e.printStackTrace();
}
finally {
connection.close();
}
}
}
项目:超市订单管理系统(SMBMS)
需求
数据库对象:
项目搭建准备工作
-
搭建一个maven项目
-
配置tomcat并测试
-
导入jar包(依赖)
- jsp、servlet、mysql驱动、jstl、standard等
-
创建项目包结构(pojo用于存实体类)
-
对应数据库编写实体类(ORM映射:表-类映射)
-
编写基础公共类
- 数据库配置文件
# resources/db.properties driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/smbms?useSSL=true&useUnicode=true&characterEncoding=utf-8 username=root password=a13587491757A
-
编写操作数据库的类
package com.infinite.dao; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; /** * @author ShmeBluk * @version 1.0 * @ClassName: BaseDAO * @Desc: 数据库操作基类 * @package com.infinite.dao * @project smbms * @date */ public class BaseDao { private static String driver; private static String url; private static String user; private static String password; /** * 静态代码块,读取配置信息 */ static { Properties prop = new Properties(); InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties"); try { prop.load(is); } catch (IOException e) { e.printStackTrace(); } driver = prop.getProperty("driver"); url = prop.getProperty("url"); user = prop.getProperty("user"); password = prop.getProperty("password"); } /** * @return Connection * @throws ClassNotFoundException * @throws SQLException * @Desc 获取数据库连接 */ public static Connection getConnection() throws ClassNotFoundException, SQLException { Class.forName(driver); Connection conn = DriverManager.getConnection(url, user, password); return conn; } /** * @param conn * @param args * @return ResultSet 查询结果集 * @throws SQLException * @Desc 通用的查询操作 */ public static ResultSet query(Connection conn, String sql, Object... args) throws SQLException { PreparedStatement ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i+1, args[i]); } ResultSet rs = ps.executeQuery(); rs.getMetaData(); return rs; } /** * @param conn * @param sql * @param args * @return int 受影响的行数 * @throws SQLException * @Desc 通用的增删改操作 */ public static int update(Connection conn, String sql, Object... args) throws SQLException { PreparedStatement ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i+1, args[i]); } int column = ps.executeUpdate(); return column; } /** * @Desc 关闭资源操作 * @param resultSet ResultSet * @param ps PreparedStatement * @param conn Connection * @return boolean 是否修改成功 */ public static boolean closeResource(ResultSet resultSet, PreparedStatement ps, Connection conn) { boolean flag = true; try { if (resultSet != null) resultSet.close(); } catch (SQLException throwables) { flag = false; throwables.printStackTrace(); } try { if (ps != null) ps.close(); } catch (SQLException throwables) { flag = false; throwables.printStackTrace(); } try { if (conn != null) conn.close(); } catch (SQLException throwables) { flag = false; throwables.printStackTrace(); } return flag; } }
-
编写字符编码过滤器(Filter/CharacterEncodingFilter.java)
-
导入静态资源
登录功能
流程图:
-
编写前端页面
-
设置首页
<!--web.xml--> <!-- 设置欢迎页面--> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list>
-
编写dao层用户登录的接口
//获取登录的用户 public User getLoginUser(Connection conn, String userCode) throws SQLException;
-
实现第三步的接口
package com.infinite.dao.user; import com.infinite.dao.BaseDao; import com.infinite.pojo.User; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import static com.infinite.dao.BaseDao.closeResource; import static com.infinite.dao.BaseDao.query; /** * @author ShmeBluk * @version 1.0 * @ClassName: UserDAOImpl * @Desc: 针对user数据表操作的具体实现类 * @package com.shme.dao * @project smbms * @date 2020/6/23 9:52 */ public class UserDaoImp1 implements UserDao { public User getLoginUser(Connection conn, String userCode) throws SQLException { String sql = "select * from smbms_user where userCode=?"; ResultSet rs=BaseDao.query(conn,sql,userCode); User user=new User(); if(conn!=null) { while (rs.next()) { 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.setPhone(rs.getString("phone")); user.setAddress(rs.getString("address")); user.setUserRole(rs.getInt("userRole")); user.setCreatedBy(rs.getInt("createdBy")); user.setCreationDate(rs.getTimestamp("creationDate")); user.setModifyBy(rs.getInt("modifyBy")); user.setModifyDate(rs.getTimestamp("modifyDate")); } BaseDao.closeResource(rs,null,null); } return user; } }
-
业务层(service)接口
//用户登录接口 public User login(String userCode, String password);
-
业务层实现
package com.infinite.service.user;
import com.infinite.dao.BaseDao;
import com.infinite.dao.user.UserDao;
import com.infinite.dao.user.UserDaoImp1;
import com.infinite.pojo.User;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
public class UserServiceImp1 implements UserService{
//业务层会引用dao层,所以要调入dao层
private UserDao userDao;
public UserServiceImp1(){
userDao=new UserDaoImp1();
}
/**
* @Desc 通过传入的用户名查询数据库中的信息
* @param userCode 用户名(英文缩写)
* @return User 数据库中查到的用户
*/
public User login(String userCode) {
Connection connection=null;
User user=null;
try{
connection= BaseDao.getConnection();
user=userDao.getLoginUser(connection,userCode);
}
catch (ClassNotFoundException | SQLException e){
e.printStackTrace();
}
finally {
BaseDao.closeResource(null,null,connection);
}
return user;
}
}
-
编写Servlet(控制层,调用业务层代码)
登录功能
package com.infinite.servlet.user; import com.infinite.pojo.User; import com.infinite.service.user.UserService; import com.infinite.service.user.UserServiceImp1; import com.infinite.util.Constants; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取用户名和密码 String userCode=req.getParameter("userCode"); String password=req.getParameter("userPassword"); System.out.println("前端:"+userCode+":"+password); //和数据库中的密码进行比较,调用业务层 UserService userService=new UserServiceImp1(); User user=userService.login(userCode); //查询用户 System.out.println(user); System.out.println("数据库:"+user.getUserCode()+":"+user.getUserPassword()); if(user.getId()!=null){ //将用户的信息放入Session if(password.equals(user.getUserPassword())) { req.getSession().setAttribute(Constants.USER_SESSION, user); resp.sendRedirect("jsp/frame.jsp"); System.out.println("登录成功"); } else{ req.setAttribute("error","密码错误"); req.getRequestDispatcher("login.jsp").forward(req,resp); System.out.println("密码错误"); } } else{ req.setAttribute("error","用户不存在"); req.getRequestDispatcher("login.jsp").forward(req,resp); System.out.println("用户不存在"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
注册功能
-
测试
可能遇到的问题
Could not initialize class dao.BaseDao。实际表现为登录后反馈500。
可参考博客:https://blog.csdn.net/GodGump/article/details/109348414?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4.pc_relevant_default&utm_relevant_index=6
注销功能
logoutServlet.java
package com.infinite.servlet.user;
import com.infinite.util.Constants;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().removeAttribute(Constants.USER_SESSION);
resp.sendRedirect(req.getContextPath()+"/login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml
<!--退出请求注册-->
<servlet>
<servlet-name>logoutServlet</servlet-name>
<servlet-class>com.infinite.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>logoutServlet</servlet-name>
<url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>
登录拦截优化
SysFilter.java
package com.infinite.filter;
import com.infinite.pojo.User;
import com.infinite.util.Constants;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("SysFilter初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse resp=(HttpServletResponse) response;
User user=(User)req.getSession().getAttribute(Constants.USER_SESSION);
System.out.println(user);
if(user==null){
resp.sendRedirect(req.getContextPath()+"/error/403.jsp");
System.out.println("用户未登录");
}
else{
System.out.println("用户已登录");
chain.doFilter(req,resp);
}
System.out.println("SysFilter已过滤");
}
@Override
public void destroy() {
System.out.println("SysFilter销毁");
}
}
web.xml
<!--登陆过滤器-->
<filter>
<filter-name>sysFilter</filter-name>
<filter-class>com.infinite.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sysFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>
修改密码
-
导入相关的前端素材
<li><a href="${pageContext.request.contextPath }/jsp/pwdmodify.jsp">密码修改</a></li>
-
写项目时,建议从底层向上写(如Dao–>Service–>Servlet)
-
UserDao层
public int updatePassword(Connection comm,String newPassword,int id) throws SQLException;
-
UserDao实现
//UserDaoImp1.java public int updatePassword(Connection conn, String newPassword, int id) throws SQLException { String sql="update `smbms_user` set `userPassword`=? where `id`=?"; int update=BaseDao.update(conn,sql,newPassword,id); return update; }
-
UserServive层
public Boolean updatePassword(String newPassword, int id);
-
UserService实现
//UserServiceImp1.java public Boolean updatePassword(String newPassword, int id) { Boolean flag=false; Connection conn=null; int update=0; try{ conn=BaseDao.getConnection(); update=userDao.updatePassword(conn,newPassword,id); } catch (Exception e){ e.printStackTrace(); } finally { if(update>0){ flag=true; } BaseDao.closeResource(null,null,conn); } return flag; }
-
UserServlet层(通过将常用代码片段提取成新方法,实现代码复用)
private void updatePassword(HttpServletRequest req,HttpServletResponse resp)throws ServletException, IOException{ Object o=req.getSession().getAttribute(Constants.USER_SESSION); String newPassword=req.getParameter("newpassword"); boolean flag=false; if(o!=null && newPassword!=null && newPassword.length()!=0){ UserService userService=new UserServiceImp1(); flag=userService.updatePassword(newPassword,((User)o).getId()); if(flag){ req.setAttribute(Constants.MSG,"密码修改成功,请重新登录。"); req.getSession().removeAttribute(Constants.USER_SESSION); resp.sendRedirect(req.getContextPath()+"/relogin.jsp"); System.out.println("密码修改成功"); return ; } else{ req.setAttribute(Constants.MSG,"密码修改失败,请使用原密码登录。"); } } else{ req.getRequestDispatcher("/jsp/pwdmodify.jsp").forward(req,resp); System.out.println("密码修改失败。"); } }
使用Ajax优化密码修改功能
js/pwdmodify.js
var oldpassword = null;
var newpassword = null;
var rnewpassword = null;
var saveBtn = null;
$(function(){
oldpassword = $("#oldpassword");
newpassword = $("#newpassword");
rnewpassword = $("#rnewpassword");
saveBtn = $("#save");
oldpassword.next().html("*");
newpassword.next().html("*");
rnewpassword.next().html("*");
oldpassword.on("blur",function(){
$.ajax({
type:"GET",
url:path+"/jsp/user.do",
data:{method:"pwdmodify",oldpassword:oldpassword.val()}, //ajax传递的参数
dataType:"json", //目前比较主流的前后端交互方式
success:function(data){
if(data.result == "true"){ //旧密码正确
validateTip(oldpassword.next(),{"color":"green"},imgYes,true);
}else if(data.result == "false"){ //旧密码输入不正确
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 原密码输入不正确",false);
}else if(data.result == "errorSession"){ //当前用户session过期,请重新登录
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 当前用户session过期,请重新登录",false);
}else if(data.result == "error"){ //旧密码输入为空
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请输入旧密码",false);
}
},
error:function(data){
//请求出错
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请求错误",false);
}
});
}).on("focus",function(){
validateTip(oldpassword.next(),{"color":"#666666"},"* 请输入原密码",false);
});
newpassword.on("focus",function(){
validateTip(newpassword.next(),{"color":"#666666"},"* 密码长度必须是大于6小于20",false);
}).on("blur",function(){
if(newpassword.val() != null && newpassword.val().length >= 6
&& newpassword.val().length < 20 ){
validateTip(newpassword.next(),{"color":"green"},imgYes,true);
}else{
validateTip(newpassword.next(),{"color":"red"},imgNo + " 密码输入不符合规范,请重新输入",false);
}
});
rnewpassword.on("focus",function(){
validateTip(rnewpassword.next(),{"color":"#666666"},"* 请输入与上面一致的密码",false);
}).on("blur",function(){
if(rnewpassword.val() != null && rnewpassword.val().length >= 6
&& rnewpassword.val().length < 20 && newpassword.val() == rnewpassword.val()){
validateTip(rnewpassword.next(),{"color":"green"},imgYes,true);
}else{
validateTip(rnewpassword.next(),{"color":"red"},imgNo + " 两次密码输入不一致,请重新输入",false);
}
});
saveBtn.on("click",function(){
oldpassword.blur();
newpassword.blur();
rnewpassword.blur();
if(
oldpassword.attr("validateStatus") == "true" &&
newpassword.attr("validateStatus") == "true"
&& rnewpassword.attr("validateStatus") == "true"){
if(confirm("确定要修改密码?")){
$("#userForm").submit();
}
}
});
});
fastjson依赖
<!--fastjson-->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
UserServlet层
private void modifyPassword(HttpServletRequest req,HttpServletResponse resp)throws IOException{
User o=(User)req.getSession().getAttribute(Constants.USER_SESSION);
String oldpassword=req.getParameter("oldpassword");
System.out.println("Session中的密码:" + o.getUserPassword());
System.out.println("用户输入的旧密码:" + oldpassword);
HashMap<String ,String> resultMap=new HashMap<>();
if(o==null){
resultMap.put("result","errorSession");
}
else if(StringUtils.isNullOrEmpty(oldpassword)){
resultMap.put("result","error");
}
else{
if(o.getUserPassword().equals(oldpassword)){
resultMap.put("result","true");
}
else{
resultMap.put("result","false");
}
}
//设置返回json字符串
resp.setContentType("application/json");
PrintWriter out=resp.getWriter();
out.write(JSONArray.toJSONString(resultMap));
out.flush();
out.close();
}
用户管理功能
图示:
-
导入分页的工具类
com.infinite.util.PageSupport.java
package com.infinite.util; public class PageSupport { //数据库中数据总条目数 private int totalDataNumber; //当前页码 private int currentPageCode; //每页显示条目数(页面大小) private int pageSize; //总页数 private int PageNumber; //页码getter public int getCurrentPageCode() { return currentPageCode; } //页码setter public void setCurrentPageCode(int currentPageCode) { //判断输入页码是否大于0 if (currentPageCode > 0 && currentPageCode <= PageNumber) { this.currentPageCode = currentPageCode; } } //页面大小getter public int getPageSize() { return pageSize; } //页面大小setter public void setPageSize(int pageSize) { //判断页面大小是否大于零 if (pageSize > 0) { this.pageSize = pageSize; } } //页数getter public int getPageNumber() { return PageNumber; } //页数setter public void setPageNumber(int pageNumber) { PageNumber = pageNumber; } //数据总数getter public int getTotalDataNumber() { return totalDataNumber; } //数据总数setter public void setTotalDataNumber(int totalDataNumber) { //判断totalDataNumber是否大于零 if (totalDataNumber > 0) { this.totalDataNumber = totalDataNumber; setPageNumberByRs(); } } //计算查询的数据能够显示的总页数 public void setPageNumberByRs() { //判断是否定义了pageSize if (pageSize > 0) { /** * 能走到这里说明`totalDataNumber>0&&pageSize>0` * 那么相除的结果:要么为零,要么大于零 */ if (totalDataNumber % pageSize == 0) { //刚好除尽 PageNumber = totalDataNumber / pageSize; } else/* (totalDataNumber % pageSize > 0) */{ //有余数,总页数加一页 PageNumber = (totalDataNumber / pageSize) + 1; } } else { PageNumber = 0; } } }
-
导入用户列表页面
1、获取用户数量
-
UserDao
public int getUserCount(Connection conn, String userName, int userRole) throws SQLException;
-
UserDaoImp1
public int getUserCount(Connection conn, String userName, int userRole) throws SQLException { StringBuffer sql=new StringBuffer(); sql.append("select count(1) as count from smbms_user u , smbms_role r where u.userRole=r.id"); //若存在用户名筛选条件 if(!StringUtils.isNullOrEmpty(userName)){ sql.append(" and u.userName like ?"); userName="%"+userName+"%"; System.out.println("userName: "+userName); } //若存在角色筛选条件 if(userRole>0){ sql.append(" and u.userRole = ?"); } System.out.println("UserDaoImpl->getUserCount():" + sql); ResultSet rs; if((!StringUtils.isNullOrEmpty(userName)) && (userRole>0)){//用户和角色都存在 rs=query(conn,sql.toString(),userName,userRole); System.out.println("情况一"); } else if ((!StringUtils.isNullOrEmpty(userName)) && (userRole <= 0)) { //用户名存在,用户角色不存在 rs = query(conn, sql.toString(), userName); System.out.println("情况二"); } else if ((StringUtils.isNullOrEmpty(userName)) && (userRole > 0)) { //用户名不存在,用户角色存在 rs = query(conn, sql.toString(), userRole); System.out.println("情况三"); } else /*((StringUtils.isNullOrEmpty(userName)) && (userRole < 0))*/ { //用户名和用户角色都不存在 rs = query(conn, sql.toString()); System.out.println("情况四"); } //获得符合条件的用户个数 int i=0; if(rs.next()){ i=rs.getInt("count"); System.out.println("rs中的个数: "+i); } closeResource(rs,null,null); return i; }
-
UserService
int getUserCount(String userName,int userRole);
-
UserServiceImp1
public int getUserCount(String userName, int userRole){ Connection conn=null; int count=0; try{ conn=BaseDao.getConnection(); count=userDao.getUserCount(conn,userName,userRole); } catch (ClassNotFoundException e1){ e1.printStackTrace(); } catch (SQLException e2){ e2.printStackTrace(); } finally { BaseDao.closeResource(null,null,conn); } return count; }
2、获取用户列表
-
UserDao
List<User> getUserList(Connection conn, String userName, int userRole, int currentPageCode, int pageSize) throws SQLException;
-
UserDaoImp1
public List<User> getUserList(Connection conn, String userName, int userRole, int currentPageCode, int pageSize) throws SQLException { ArrayList<User> userList = new ArrayList<>(); StringBuffer sql = new StringBuffer(); sql.append("select u.*,r.roleName as userRoleName from smbms_user u,smbms_role r where u.userRole=r.id"); //如果有用户名筛选条件 if (!StringUtils.isNullOrEmpty(userName)) { sql.append(" and u.userName like ?"); userName = "%" + userName + "%"; } //如果有角色筛选条件 if (userRole > 0) { sql.append(" and u.userRole=?"); } //单页记录数 int offset = (currentPageCode - 1) * pageSize; sql.append(" order by r.id limit ?,?"); ResultSet rs; if ((!StringUtils.isNullOrEmpty(userName)) && (userRole > 0)) { //用户名和用户角色都存在 rs = query(conn, sql.toString(), userName, userRole, offset, pageSize); System.out.println("情况一"); System.out.println("sql:" + sql.toString()); System.out.println("用户名:" + userName); System.out.println("用户角色:" + userRole); System.out.println("起始索引:" + offset); System.out.println("页面大小:" + pageSize); } else if ((!StringUtils.isNullOrEmpty(userName)) && (userRole <= 0)) { //用户名存在,用户角色不存在 rs = query(conn, sql.toString(), userName, offset, pageSize); System.out.println("情况二"); System.out.println("sql:" + sql.toString()); System.out.println("用户名:" + userName); System.out.println("起始索引:" + offset); System.out.println("页面大小:" + pageSize); } else if ((StringUtils.isNullOrEmpty(userName)) && (userRole > 0)) { //用户名不存在,用户角色存在 rs = query(conn, sql.toString(), userRole, offset, pageSize); System.out.println("情况三"); System.out.println("sql:" + sql.toString()); System.out.println("用户角色:" + userRole); System.out.println("起始索引:" + offset); System.out.println("页面大小:" + pageSize); } else /*((StringUtils.isNullOrEmpty(userName)) && (userRole < 0))*/ { //用户名和用户角色都不存在 rs = query(conn, sql.toString(), offset, pageSize); System.out.println("情况四"); System.out.println("sql:" + sql.toString()); System.out.println("起始索引:" + offset); System.out.println("页面大小:" + pageSize); } while (rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setUserCode(rs.getString("userCode")); user.setUserName(rs.getString("userName")); user.setGender(rs.getInt("gender")); user.setBirthday(rs.getDate("birthday")); user.setPhone(rs.getString("phone")); user.setUserRole(rs.getInt("userRole")); user.setUserRoleName(rs.getString("userRoleName")); userList.add(user); } BaseDao.closeResource(rs,null,null); return userList; }
-
UserService
List<User> getUserList(String userName, int userRole, int currentPageCode, int pageSize)
-
UserServiceImp1
public List<User> getUserList(String userName, int userRole, int currentPageCode, int pageSize){ Connection conn=null; List<User>userList=null; try{ conn=BaseDao.getConnection(); if(currentPageCode>0 && pageSize>0){ userList=userDao.getUserList(conn,userName,userRole,currentPageCode,pageSize); System.out.println(userList); } } catch (ClassNotFoundException e1){ e1.printStackTrace(); } catch (SQLException e2){ e2.printStackTrace(); } finally { BaseDao.closeResource(null,null,conn); } return userList; }
3、获取角色操作
角色相关的操作要另外写一个包,以实现职责统一
-
RoleDao
package com.infinite.dao.role; import com.infinite.pojo.Role; import java.sql.Connection; import java.sql.SQLException; import java.util.List; public interface RoleDao { /** * 获取角色列表 * @param conn Connection 数据库连接 * @return List<Role> 角色集合 */ List<Role> getRoleList(Connection conn) throws SQLException; }
-
RoleDaoImp1
package com.infinite.dao.role; import com.infinite.pojo.Role; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import static com.infinite.dao.BaseDao.query; public class RoleDaoImp1 implements RoleDao{ /** * 获取角色列表 * @param conn Connection 数据库连接 * @return List<Role> 角色集合 */ @Override public List<Role> getRoleList(Connection conn) throws SQLException { String sql = "select * from smbms_role"; ResultSet rs = query(conn, sql); ArrayList<Role> roleList = new ArrayList<>(); while (rs.next()){ Role role = new Role(); role.setId(rs.getInt("id")); role.setRoleCode(rs.getString("roleCode")); role.setRoleName(rs.getString("roleName")); roleList.add(role); } return roleList; } }
-
RoleService
package com.infinite.service.role; import com.infinite.pojo.Role; import java.util.List; /** * @author ShmeBluk * @version 1.0 * @ClassName: RoleService * @Desc: 角色service层接口 * @package com.infinite.service * @project smbms * @date 2020/7/10 15:32 */ public interface RoleService { /** * 获取用户角色列表 * @return List<Role> 用户列表 */ List<Role> getRoleList(); }
-
RoleServiceImp1
package com.infinite.service.role; import com.infinite.dao.BaseDao; import com.infinite.dao.role.RoleDao; import com.infinite.dao.role.RoleDaoImp1; import com.infinite.pojo.Role; import java.sql.Connection; import java.sql.SQLException; import java.util.List; public class RoleServiceImp1 implements RoleService{ private RoleDao roleDAO; public RoleServiceImp1(){ roleDAO = new RoleDaoImp1(); } /** * 获取用户角色列表 * @return List<Role> 用户列表 */ @Override public List<Role> getRoleList() { Connection conn = null; List<Role> roleList = null; try { conn = BaseDao.getConnection(); roleList = roleDAO.getRoleList(conn); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException throwables) { throwables.printStackTrace(); } finally { BaseDao.closeResource(null,null,conn); } return roleList; } }
4、用户显示的Servlet
- 获取前端的数据
- 通过传入参数判断请求是否需要执行
- 为了实现分页,需要计算出当前页面和总页面、页面大小等
- 用户列表展示
- 返回到前端
UserServlet.java
private void query(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
//从请求中获取参数
String queryName=req.getParameter("queryName");
String pageIndex=req.getParameter("pageIndex");
String temp=req.getParameter("queryUserRole");
int queryUserRole=0; //初始化赋值,避免查询时出现异常
//页面大小
int pageSize=Constants.PAGE_SIZE;
//当前页码
int currentPageCode=1;
//判断是否有用户名筛选
if(queryName==null){
//没有用户名限制,就赋值为空字符串,避免查询报错
queryName="";
}
//判断是否有角色筛选
if(temp!=null && !temp.equals("")){
queryUserRole=Integer.parseInt(temp);
}
//判断传入页码是否正确
if(pageIndex!=null){
try{
currentPageCode=Integer.parseInt(pageIndex);
}
catch (NumberFormatException e){
e.printStackTrace();
resp.sendRedirect("error.jsp");
}
}
//获取符合条件的用户个数
UserService userService=new UserServiceImp1();
int totalDataNumber=userService.getUserCount(queryName,queryUserRole);
//计算数据显示的总页数
PageSupport pageSupport=new PageSupport();
pageSupport.setCurrentPageCode(currentPageCode);
pageSupport.setPageSize(pageSize);
pageSupport.setTotalDataNumber(totalDataNumber);
int pageNumber=pageSupport.getPageNumber(); //总页数
//控制首页和尾页
if(currentPageCode<1){
currentPageCode=1;
}
else if(currentPageCode>pageNumber){
currentPageCode=pageNumber;
}
//将查到的用户数据存入Attribute中
List<User> userList=userService.getUserList(queryName,queryUserRole,currentPageCode,pageSize);
Iterator<User> iterator=userList.iterator();
while(iterator.hasNext()){
User user=iterator.next();
System.out.println("用户: "+user);
}
req.setAttribute("userList",userList);
//将查询到的角色数据存入Attribute中
RoleService roleService = new RoleServiceImp1();
List<Role> roleList = roleService.getRoleList();
for(Role role : roleList){
System.out.println("用户角色:"+role);
}
req.setAttribute("roleList", roleList);
//将需要的参数存到Attribute中
req.setAttribute("queryUserName", queryName);
req.setAttribute("queryUserRole", queryUserRole);
req.setAttribute("totalPageCount", pageNumber);
req.setAttribute("totalCount", totalDataNumber);
req.setAttribute("currentPageNo", currentPageCode);
//转发:url不变
req.getRequestDispatcher("userlist.jsp").forward(req, resp);
}
后续的增删改等功能总体思想和查询一样
ist = roleDAO.getRoleList(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
BaseDao.closeResource(null,null,conn);
}
return roleList;
}
}
### 4、用户显示的Servlet
1. 获取前端的数据
2. 通过传入参数判断请求是否需要执行
3. 为了实现分页,需要计算出当前页面和总页面、页面大小等
4. 用户列表展示
5. 返回到前端
> UserServlet.java
```java
private void query(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
//从请求中获取参数
String queryName=req.getParameter("queryName");
String pageIndex=req.getParameter("pageIndex");
String temp=req.getParameter("queryUserRole");
int queryUserRole=0; //初始化赋值,避免查询时出现异常
//页面大小
int pageSize=Constants.PAGE_SIZE;
//当前页码
int currentPageCode=1;
//判断是否有用户名筛选
if(queryName==null){
//没有用户名限制,就赋值为空字符串,避免查询报错
queryName="";
}
//判断是否有角色筛选
if(temp!=null && !temp.equals("")){
queryUserRole=Integer.parseInt(temp);
}
//判断传入页码是否正确
if(pageIndex!=null){
try{
currentPageCode=Integer.parseInt(pageIndex);
}
catch (NumberFormatException e){
e.printStackTrace();
resp.sendRedirect("error.jsp");
}
}
//获取符合条件的用户个数
UserService userService=new UserServiceImp1();
int totalDataNumber=userService.getUserCount(queryName,queryUserRole);
//计算数据显示的总页数
PageSupport pageSupport=new PageSupport();
pageSupport.setCurrentPageCode(currentPageCode);
pageSupport.setPageSize(pageSize);
pageSupport.setTotalDataNumber(totalDataNumber);
int pageNumber=pageSupport.getPageNumber(); //总页数
//控制首页和尾页
if(currentPageCode<1){
currentPageCode=1;
}
else if(currentPageCode>pageNumber){
currentPageCode=pageNumber;
}
//将查到的用户数据存入Attribute中
List<User> userList=userService.getUserList(queryName,queryUserRole,currentPageCode,pageSize);
Iterator<User> iterator=userList.iterator();
while(iterator.hasNext()){
User user=iterator.next();
System.out.println("用户: "+user);
}
req.setAttribute("userList",userList);
//将查询到的角色数据存入Attribute中
RoleService roleService = new RoleServiceImp1();
List<Role> roleList = roleService.getRoleList();
for(Role role : roleList){
System.out.println("用户角色:"+role);
}
req.setAttribute("roleList", roleList);
//将需要的参数存到Attribute中
req.setAttribute("queryUserName", queryName);
req.setAttribute("queryUserRole", queryUserRole);
req.setAttribute("totalPageCount", pageNumber);
req.setAttribute("totalCount", totalDataNumber);
req.setAttribute("currentPageNo", currentPageCode);
//转发:url不变
req.getRequestDispatcher("userlist.jsp").forward(req, resp);
}
后续的增删改等功能总体思想和查询一样
注
着重理解javaweb的原理,后续学习框架(SSM,Spring等等)后,javaweb中的内容会被不断封装简化,需要写的代码量也会减少。