目录
Gitee仓库:狂神-javaWeb: 学习狂神的课程,练习项目 - Gitee.com
一、会话
1、什么是会话
**会话:**用户打开一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,这个过程可以称之为会话。
**有状态会话:**一个同学曾经来过教室,下次再来的教室的时候,我们会知道这个同学,曾经来过,称之为有状态会话。
http是一个无状态的协议
什么是无状态:就是说这次请求和上一次请求没有任何关系,互不认识。
这种无状态的好处是快速。
坏处是假如我们想要把www.zhihu.com/login.html
和www.zhihu.com/index.html
关联起来,必须使用某些手段和工具。
2、会话保持的两种技术
cookie
- 客户端技术(响应,请求),是把用户的数据写给浏览器,浏览器保存(可以保存多个);
session
- 服务端技术,把用户的数据写到用户独占的session中,服务器端保存(保存重要的信息,避免服务器的资源浪费);
二、Cookie
1、什么是Cookie
cookie:一般会保存在本地的用户目录下/Users/AppData/Local下
一个网站cookie是否存在上限?
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,每个web站点最多存放20个cookie( 不同的浏览器会有所不同)
- cookie大小有限制4kb
- 浏览器上限是300个cookie
怎样删除cookie
- 不设置有效期,关闭浏览器,自动失效
- 设置有效期时间为0
Cookie分类
- 会话级别cookie:cookie保存在浏览器端,会随着浏览器的关闭,cookie销毁。
- 持久化级别cookie:cookie保存在浏览器端,指定在磁盘上。可以去设置cookie的生存时间
方法名 | 描述 |
setMaxAge(int expiry) | 设置cookie的生存时间。 单位:秒。 在这里int的取值可以是:-1 默认是会话级别的cookie 0 但是cookie立即被销毁 1 持久化级别的cookie 存活时间是1秒 如果没有设置,cookie只缓存浏览器缓存中,浏览器关闭,cookie删除。 如果设置有效时间,在时间范围内,cookie被写入到浏览器端,关闭浏览器下次访问仍可获得,直到过期。 |
2、实现案例
CookieServlet.java
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 防止页面乱码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
// 获取Cookie
Cookie[] cookies = req.getCookies();
PrintWriter writer = resp.getWriter();
// 判断是否登陆过
if (cookies != null) {
writer.write("请求的Cookie为:" + Arrays.toString(cookies));
writer.println("<br/>");
writer.write("你上次访问的时间为:");
for (Cookie cookie : cookies) {
if (cookie.getName().equals("lastLoginTime")) {
long time = Long.parseLong(cookie.getValue());
Date date = new Date(time);
writer.write(date.toLocaleString());
}
}
} else {
writer.write("这是你第一次访问本网站");
}
resp.addCookie(new Cookie("lastLoginTime", System.currentTimeMillis() + ""));
}
设置有效期为0
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
// 设置有效期为0
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
运行结果
三、Session(重点)
1、什么是Session
- 服务器会给每一个用户(浏览器)创建一个session对象;
- 一个session独占一个浏览器,只要浏览器没有关闭,session就存在;
- 用户登录之后,整个网站它都可以访问。–》保存用户的信息;保存购物车的信息
2、Session的生命周期
创建:
第一次调用request.getSession();
销毁:
1.服务器非正常关闭时销毁session(服务器正常关闭不会销毁,因为session数据是存在服务器端的,和浏览器无关)
D:\develop\apache-tomcat-8.5.29\work\Catalina\localhost\servlet5(序列化session的位置)
2.手动销毁 session.invalidate();
3.默认不操作,超过30分钟自动销毁(文件位置在Tomcat配置文件web.xml中)
3、项目实战
项目结构
同Cookie项目一样
web.xml
<servlet>
<servlet-name>SessionCreateServlet</servlet-name>
<servlet-class>com.kuang.servlet.SessionCreateServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionCreateServlet</servlet-name>
<url-pattern>/SessionCreateServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>SessionGetServlet</servlet-name>
<servlet-class>com.kuang.servlet.SessionGetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionGetServlet</servlet-name>
<url-pattern>/SessionGetServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>SessionInvalidateServlet</servlet-name>
<servlet-class>com.kuang.servlet.SessionInvalidateServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionInvalidateServlet</servlet-name>
<url-pattern>/SessionInvalidateServlet</url-pattern>
</servlet-mapping>
创建并存放Session
public class SessionCreateServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
// 获取session对象
HttpSession session = req.getSession();
session.setAttribute("name", "小狂狂");
session.setAttribute("person", new Person("扶她"));
//获取session的id
String id = session.getId();
if (session.isNew()) {
resp.getWriter().write("session创建成功,id:" + id);
} else {
resp.getWriter().write("session已经在服务器中存在了,id:" + id);
}
}
获取Session
public class SessionGetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
// 获取session对象
HttpSession session = req.getSession();
String name = (String) session.getAttribute("name");
Person person = (Person) session.getAttribute("person");
PrintWriter writer = resp.getWriter();
if (name != null) {
writer.write("从session中获取的name为:" + name);
} else {
writer.write("从session中获取的name为空");
}
if (person != null) {
writer.write("从session中获取的person为:" + person);
} else {
writer.write("从session中获取的person为空");
}
}
销毁Session
public class SessionInvalidateServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
// 获取session对象
HttpSession session = req.getSession();
session.invalidate();
}
启动服务器,查看结果
清空Session后再访问SessionGetServlet
四、JSP原理剖析
1、什么是JSP
java server pages:java服务器端页面,也是servlet一样,用于动态web技术!
html和jsp的区别
- html只给用户提供静态数据
- jsp页面中可以嵌入java代码,为用户提供动态数据
2、Jsp底层分析
思路:jsp到底怎么执行的?
-
代码层面看不出啥(jsp)
- 服务器内部工作
tomcat中有一个work目录
idea使用tomcat的会在idea的tomcat中生产一个work目录
本机地址:C:\Users\simmons333\AppData\Local\JetBrains\IntelliJIdea2020.3\tomcat\ed738b46-17ae-4582-8720-e70bfabc348a\work\Catalina\localhost\ROOT\org\apache\jsp
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问servlet
jsp最终也会被转换为一个java类
jsp本质上就是一个servlet
内部也有初始化、销毁、服务方法
//2.内置一些对象
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:当前
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {}
在jsp页面中
只要是java代码就会原封不动的输出
如果是html代码,就会被转换为out.write(" <title>Title</title>\r\n");
这样的格式输出到前端
五、jsp基础语法和指令
任何语言都有自己的语法,java有,jsp作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可),java所有语法都支持。
1、jsp表达式
项目结构
导入依赖
<!-- 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>
jsp的表达式:<%%>
2、jsp脚本片段
打印1到100的和
<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
out.print("<h1>sum=" + sum + "</h1>");
%>
在for循环代码中嵌入html元素
<%--在代码中嵌入html元素--%>
<%
for (int j = 0; j < 5; j++) {
%>
<h2>hello<%=j%></h2>
<%
}
%>
查看生成的jsp文件内容
3、jsp声明
jsp声明的表达式:<%!%>
<%--申明,会被编译到jsp生成java代码的类中!--%>
<%!
static {
System.out.println("jsp中的静态代码块");
}
private String globalVar = "全局变量";
public void test1() {
System.out.println("我进入了公共方法里");
}
%>
<%--其他的,就会被生成到_jspService方法中!--%>
<%
test1();
%>
jsp声明,会被编译到jsp生成java代码的类中!其他的,就会被生成到_jspService方法中!
<!--Html的注释--%>
<%--其他的,就会被生成到_jspService方法中!--%>
发现:jsp的注释,不会在客户端显示,html会!
4、jsp指令
启动含有报错代码的jsp页面
<%
int i = 1 / 0;
%>
页面显示后台的报错日志
定制错误页面500.jsp
<%--定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>
再次启动含有报错代码的jsp页面
还可以在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">
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
</web-app>
<%@include "%> || jsp:include 引入标签
header.jsp
<h1>这是header页面</h1>
footer.jsp
<h1>这是footer页面</h1>
demo5.jsp
<%-- include 会将两个页面合二为一 注意页面合并后的冲突(比如两个页面都定义了int i = 10 这种会报错)--%>
<%@include file="include/header.jsp" %>
<h1>demo5页面</h1>
<%-- jsp标签 拼接页面 本质还是三个 推荐使用这种,这种不会出现上面的int i=10冲突的情况,因为本质还是三个页面 --%>
<jsp:include page="include/footer.jsp" %>
从源码角度分析2者的区别
5、Jsp标签库
六、jsp内置对象及作用域
九大内置对象
- PageContext【存东西】
- Request 【存东西】
- Response
- Session【存东西】
- Application(ServletContext)【存东西】
- config(ServletConfig)
- out
- page 【基本用不到】
- exception
JSP四大作用域:
从小到大: pageContext、request、session、ServletContext
pageContext1.jsp
<%--内置对象--%>
<%
pageContext.setAttribute("页面对象", "pageContext");
request.setAttribute("请求对象", "request");
session.setAttribute("会话对象", "session");
application.setAttribute("应用对象", "application");
//从pageContext取出,我们通过寻找的方式来
String name1 = (String) pageContext.findAttribute("页面对象");
String name2 = (String) pageContext.findAttribute("请求对象");
String name3 = (String) pageContext.findAttribute("会话对象");
String name4 = (String) pageContext.findAttribute("应用对象");
String name5 = (String) pageContext.findAttribute("对象");
%>
<%--使用el表达式输出 ${} --%>
<h1>取出的值为</h1>
<h3>name1:${页面对象}</h3>
<h3>name2:${请求对象}</h3>
<h3>name3:${会话对象}</h3>
<h3>name4:${应用对象}</h3>
<h3>name5:${对象}</h3>
<h3>name5:<%=name5%></h3>
启动项目测试
pageContext2.jsp
跨页面获取pageContext内的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--使用el表达式输出 ${} --%>
<h1>取出的值为</h1>
<h3>name1:${页面对象}</h3>
<h3>name2:${请求对象}</h3>
<h3>name3:${会话对象}</h3>
<h3>name4:${应用对象}</h3>
<h3>name5:${对象}</h3>
pageContext3.jsp
父对象包含子对象的功能,
<%
pageContext.forward("/index.jsp");
// 等价于 request.getRequestDispatcher("/index.jsp").forward(request, response);
%>
七、EL表达式、JSP标签、JSTL标签
导入相关依赖
</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>
1、EL表达式
EL表达式能做的就是读 相当于数据库中 select
EL表达式写法: ${ }
- 获取数据
- 执行运算:${1+2}
- 获取web开发的常用对象
- 调用java方法
2、JSP标签
jspTag1.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- http://localhost:8080/jsp/jspTag/jsptag2.jsp?name=zyy&age=18 --%>
<jsp:forward page="/jspTag/jspTag2.jsp">
<jsp:param name="name" value="zyy"/>
<jsp:param name="age" value="18"/>
</jsp:forward>
</body>
</html>
javaBean
User.java
package com.kuang.pojo;
import lombok.Data;
@Data
public class User {
private String name;
private String address;
}
jspTag2.jsp
<%@ page import="com.kuang.pojo.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:useBean id="User" class="com.kuang.pojo.User" scope="page"/>
<jsp:setProperty name="User" property="name" value="jordon"/>
<jsp:setProperty name="User" property="address" value="chicago"/>
name:<jsp:getProperty name="User" property="name"/>
address:<jsp:getProperty name="User" property="address"/>
</body>
</html>
3、JSTL标签
jstl标签库的使用就是为了弥补html标签的不足;它自定义了许多标签,可以供我们使用,标签的功能和java代码一样!
-
核心标签(掌握)
-
格式化标签
-
sql标签
-
xml标签
他和javaScript的定义变量都用var,比较相似
JSTL标签库使用步骤:
-
引用对应的taglib
-
使用其中的方法
-
在tomcat也需要引入jstl的包,否则会报错
jstlTag1.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>coreif测试</h4>
<form action="success.jsp" method="get">
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登陆">
</form>
</body>
</html>
启动项目测试
点击登录,跳转到成功页面
八、MVC三层架构
诞生原因
servlet--CRUD[增加(Create)、检索(Retrieve)、更新(Update)和删除(Delete)]-->数据库
弊端:程序十分臃肿,不利于维护 servlet的代码中:处理请求、响应、视图跳转、处理jdbc、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
九、过滤器Filter
Filter:过滤器,用来过滤网站的数据,减少代码数量
- 处理中文乱码
- 登录验证…
filter开发步骤
-
导包
-
编写过滤器
-
配置web.xml
HelloServlet.java
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 一定会乱码
resp.getWriter().println("你好");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
CharacterEncodingFilter.java
package com.kuang.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("GBK");
response.setCharacterEncoding("GBK");
System.out.println("CharacterEncodingServlet执行前。。。。");
//让请求继续走,如果不写程序到这里就被拦截停止了!
chain.doFilter(request, response);
System.out.println("CharacterEncodingServlet执行后。。。。");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingServlet创建了");
}
@Override
public void destroy() {
System.out.println("CharacterEncodingServlet销毁了");
}
}
web.xml
<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"
metadata-complete="true">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/servlet/HelloServlet</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CharacterEncodingServlet</filter-name>
<filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingServlet</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
</web-app>
启动项目,访问乱码页面
配置上CharacterEncodingServlet
Servlet在服务器启动时创建
Servlet在服务器关闭时销毁
每次请求被过滤的Servlet,Filter就执行一次
页面不乱码了
十、监听器Listener
监听器的实现有几百个,一般是用于页面的事件监听
1、实现人数监听器
OnlineCountListener.java
package com.kuang.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
// 统计在线人数
public class OnlineCountListener implements HttpSessionListener {
// 一旦创建Session就会执行一次该监听器
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("OnlineCountListener创建了");
System.out.println(se.getSession().getId());
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount == null) {
onlineCount = 1;
} else {
onlineCount += 1;
}
servletContext.setAttribute("onlineCount", onlineCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("OnlineCountListener销毁了");
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount == null) {
onlineCount = 0;
} else {
onlineCount -= 1;
}
servletContext.setAttribute("onlineCount", onlineCount);
se.getSession().invalidate();
}
}
web.xml
<listener>
<listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>
index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" %>
<html>
<body>
<h2>Hello World!</h2>
<h1>当前共有<span><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人访问</h1>
</body>
</html>
启动项目测试
谷歌浏览器
edge浏览器
2、监听器在GUI中的应用
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* @ClassName: TestPanel
* @Description: TODO 类描述
* @Author: zyy
* @Date: 2021/12/02 15:15
* @Version: 1.0
*/
public class TestPanel {
public static void main(String[] args) {
Frame frame = new Frame("测试");
Panel panel = new Panel();
frame.setLayout(null);
frame.setBounds(300, 300, 500, 500);
frame.setBackground(new Color(0, 0, 255));
panel.setBounds(50, 50, 300, 300);
panel.setBackground(new Color(255, 0, 0));
frame.add(panel);
frame.setVisible(true);
//添加一个窗口关闭的监听事件
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
十一、Filter实现登录权限拦截
用户登录之后才能进入主页!用户注销后就不能进入主页了!
- 用户登录后,向session中放入用户信息
- 进入主页的时候要判断用户是否已经登录(要求:在过滤器中实现)
项目结构
LoginServlet.java
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userName = req.getParameter("username");
if ("admin".equals(userName)) {
req.getSession().setAttribute("USER_SESSION", req.getSession().getId());
// 登录成功跳转
resp.sendRedirect("/FilterListener/sys/success.jsp");
} else {
// 登录失败
resp.sendRedirect("/FilterListener/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
LogoutServlet.java
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object userSession = req.getSession().getAttribute("USER_SESSION");
if (userSession != null) {
req.getSession().removeAttribute("USER_SESSION");
// 跳转到登录页面
resp.sendRedirect("/FilterListener/login.jsp");
} else {
// 跳转到登录页面
resp.sendRedirect("/FilterListener/login.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
LoginFilter
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("LoginFilter执行中。。。。");
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse rep = (HttpServletResponse) response;
String session = (String) req.getSession().getAttribute("USER_SESSION");
if (session == null) {
// 跳转错误页面
rep.sendRedirect("/FilterListener/login.jsp");
}
// 让请求继续走,如果不写程序到这里就被拦截停止了!
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LoginFilter创建了");
}
@Override
public void destroy() {
System.out.println("LoginFilter销毁了");
}
}
web.xml
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.kuang.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.kuang.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/servlet/LogoutServlet</url-pattern>
</servlet-mapping>
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.kuang.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
启动服务,查看效果
当访问/sys目录下的页面时,触发LoginFilter拦截器
十二、JDBC复习
1、预编译语句
导入JDBC依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
jdbc固定步骤:
- 加载驱动
- 连接数据库
- 创建Statement
- 编写sql
- 执行sql
- 关闭连接
查询方法
package com.kuang.JDBC;
import java.sql.*;
public class driver {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/smbms?useSSL=false&useUnicode=true&characterEncoding=utf-8";
String user = "root";
String pwd = "";
try {
//1. 加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 连接数据库
Connection con = DriverManager.getConnection(url, user, pwd);
//3. 向数据库发送sql的对象Statement
Statement statement = con.createStatement();
//4.sql
String str = "select * from users";
//5.执行sql
ResultSet rs = statement.executeQuery(str);
while (rs.next()) {
System.out.println("id=" + rs.getInt("id"));
System.out.println("name=" + rs.getString("name"));
System.out.println("password=" + rs.getString("password"));
System.out.println("email=" + rs.getString("email"));
System.out.println("birthday=" + rs.getString("birthday"));
}
//6.关闭
rs.close();
statement.close();
con.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
插入方法
package com.kuang.JDBC;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class prepareStatement {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/smbms?useSSL=false&useUnicode=true&characterEncoding=utf-8";
String user = "root";
String pwd = "";
try {
//1. 加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 连接数据库
Connection con = DriverManager.getConnection(url, user, pwd);
//3.sql
String str = "insert into users(id, name, password, email, birthday) values (?,?,?,?,?)";
//4. 预编译
PreparedStatement statement = con.prepareStatement(str);
statement.setInt(1, 1);
statement.setString(2, "小红");
statement.setString(3, "yyyy");
statement.setString(4, "xiaohong@sina.com");
statement.setDate(5, new java.sql.Date(System.currentTimeMillis()));
//5.执行sql
int count = statement.executeUpdate();
if (count > 0) {
System.out.println("插入成功!");
}
statement.close();
con.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2、JDBC事务
要么都成功,要么都失败
ACID原则:保证数据的安全
导入依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
sql语句
# 开启事务
start transaction ;
# 模拟转账
update account set money=money-100 where name='A';
update account set money=money+100 where name='B';
# 回滚
rollback ;
# 提交
commit;
测试类
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class testTransactional {
@Test
public void test() {
String url = "jdbc:mysql://localhost:3306/smbms?useSSL=false&useUnicode=true&characterEncoding=utf-8";
String user = "root";
String pwd = "";
Connection con = null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(url, user, pwd);
//开启事务 这里不开启事务的话异常情况就会有问题 false是开启
con.setAutoCommit(false);
con.prepareStatement("update users set money=money-100 where name='A'").executeUpdate();
//制造错误
// int i = 1 / 0;
con.prepareStatement("update users set money=money+100 where name='B'").executeUpdate();
con.commit();
System.out.println("success");
} catch (Exception e) {
System.out.println("error rollback");
if (con != null) {
try {
con.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
} finally {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
查看运行事务时打印的日志