C02_D02_UrlRewriting
index.html
<!DOCTYPE html>
<html>
<head>
<title>会话管理技术->URL重写(URL Rewriting)</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center text-primary">会话管理技术->URL重写(URL Rewriting)</h1>
<hr>
<br>
<form action="profile.jsp" class="form-inline">
<label for="xuehao">学号: </label>
<input type="text" name="rollno" id="xuehao" class="form-control">
<input type="submit" value="查询个人信息" class="btn btn-sm btn-primary">
</form>
</div>
</body>
</html>
点击查询个人信息后:
点击查看个人成绩单后:
C02_D03_Cookie
login.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录首页</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<!--Cookie: 是Web程序创建放到客户端的小型文本文件,用于存储少量的用户信息-->
<!--Cookie由服务器端创建,和响应一起发送到客户端,存放在客户端的小型文本文件-->
<div class="container">
<form action="ls" class="form-inline text-center loginForm bg-primary">
<h1 class="text-center">用户登录</h1>
<hr>
<br>
账 号: <input type="text" name="username" class="form-control">
<br><br>
密 码: <input type="password" name="password" class="form-control">
<br><br>
<input type="submit" value="登录" class="btn btn-sm btn-default">
</form>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>登录失败页面</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<br>
<h1 class="msg-warning">
<!--点击超链接可以执行javascript代码,javascript提供对象history-->
<!--history对象的back()函数实现退回上一个页面,也就是返回的效果-->
<!--如果点击超链接想执行javascript,直接在href中编写javascript:js代码即可-->
账户或密码错误,请<a href="javascript:history.back();">返回</a>重新登录!
</h1>
<hr>
</body>
</html>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center text-success">登录成功,XXX,欢迎进入教务系统</h1>
<a href="#" class="logout">退出登录</a>
<hr><br>
<ul class="list-menu">
<li><a href="profile.jsp">查看个人信息</a></li>
</ul>
</div>
</body>
</html>
LoginServlet
package com.qdu.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/ls")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uname = req.getParameter("username");
String pwd = req.getParameter("password");
//这里设定用户名是anna,密码是1234,则登录成功
if ("anna".equals(uname) && "1234".equals(pwd)) {
//HttpServletResponse的sendRedirect()实现重定向
//也就是重定向到另一个页面作为响应内容
resp.sendRedirect("success.jsp");
} else {
resp.sendRedirect("fail.html");
}
}
}
C02_D03_Cookie
login.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录首页</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
<style>
label:hover{
cursor: pointer;
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<br>
<p class="text-danger">
* 本程序没有连接数据库,使用账户anna和密码1234可以通过登录验证 <br>
* 本程序使用Cookie实现记住用户密码的功能
</p>
<%
//JSP提供隐式对象request,表示该页面收到的请求
//通过请求对象可以获取到该程序放的所有Cookie,以Cookie数组的形式返回
Cookie[] cks=request.getCookies();
//也可能一个Cookie都没有,则无需遍历Cookie数组,直接返回
if(null==cks) return;
//定义两个变量,用于存储Cookie的值
String uname="";
String upwd="";
//如果有Cookie,则遍历Cookie数组,读取Cookie的值即可
for(Cookie c:cks){ //对于数组cks中的每个Cookie对象
//如果当前遍历的cookie的名称是username
if("username".equals(c.getName()))
uname=c.getValue(); //获取其值,存储到变量uname中
else if("userpwd".equals(c.getName())) //如果当前遍历的cookie的名称是userpwd
upwd=c.getValue(); //获取其值,存储到变量upwd中
}
%>
<!--
这里将两个文本框的值分别设置为两个Cookie的值
如果有对应的Cookie值,则会显示在文本框中
如果没有对应的Cookie值,则显示空白,也就是记住密码的功能
-->
<form action="ls" class="form-inline text-center loginForm bg-primary">
<h1 class="text-center">用户登录</h1>
<hr>
<br>
账 号: <input type="text" name="username" value="<%=uname%>" class="form-control">
<br><br>
密 码: <input type="password" name="password" value="<%=upwd%>" class="form-control">
<br><br>
<input type="checkbox" id="remember" name="rem" value="Y">
<label for="remember">记住密码</label>
<input type="submit" value="登录" class="btn btn-sm btn-default">
</form>
</div>
</body>
</html>
web.html
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<!--welcome-file-list标记用于定义程序的欢迎文件列表-->
<!--欢迎文件可以设置多个,如果前面的页面不可用,则会使用后面的页面-->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
<!-- <welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>home.html</welcome-file>
<welcome-file>home.jsp</welcome-file>-->
</welcome-file-list>
</web-app>
LoginServlet
package com.qdu.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/ls")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uname = req.getParameter("username");
String pwd = req.getParameter("password");
//创建Cookie,用于存储少量的用户信息
//Cookie是一种客户端技术,用于存储少量的用户信息
//Cookie是服务器端创建,发送到客户端,存储在客户端的小型文本文件
//使用Cookie类创建和操作Cookie
//Cookie是以键-值对的形式存储数据,键和值都是字符串
//一个Cookie只能用于存储一项信息
//默认情况下Cookie是浏览器会话范围的cookie,随着浏览器关闭,Cookie会立刻被删除
Cookie ck1 = new Cookie("username", uname);
Cookie ck2 = new Cookie("userpwd", pwd);
String rem = req.getParameter("rem");
//可以设置Cookie的最大时间,也就是Cookie存在客户端多久,单位是秒
//如果设置了最大时间,则在到期前,即使关闭浏览器再打开,Cookie依然会存在
if ("Y".equals(rem)) { //如果用户选择记住密码,则设置Cookie 存在7天
ck1.setMaxAge(7 * 24 * 60 * 60);
ck2.setMaxAge(7 * 24 * 60 * 60);
}else{ //否则立刻删除Cookie
//考虑到用户可能上次记住,存储了cookie,这次选择不记住,则该种情况下要删除Cookie
//Cookie类没有提供专门的方法用于删除一个Cookie
ck1.setMaxAge(0); //最大时间为0意味着立刻删除Cookie
ck2.setMaxAge(0);
}
//Cookie需要存储到客户端,所以需要和响应一起发送到客户端并存储在客户端
//只不过是作为响应的报头/标头发送给客户端的
//必须在设置好Cookie之后,将Cookie添加到响应对象中,才能发送到客户端
resp.addCookie(ck1);
resp.addCookie(ck2);
if ("anna".equals(uname) && "1234".equals(pwd)) {
//HttpServletResponse的sendRedirect()方法用于重定向到指定页面作为响应内容
resp.sendRedirect("success.jsp"); //succeed
} else {
resp.sendRedirect("fail.html");
}
}
}
success.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
<!--Cookie是服务器端创建,发送到客户端的小型文本文件,用于存储少量的用户信息-->
<!--一旦Cookie保存在客户端,后续再次请求该程序的任何资源,Cookie会随着请求-->
<!--一起被发送返回给服务器,这样服务器端可以读取Cookie的信息-->
<%
//JSP提供隐式对象request,表示该页面收到的请求
//通过请求对象可以获取到该程序放的所有Cookie,以Cookie数组的形式返回
Cookie[] cks=request.getCookies();
//也可能一个Cookie都没有,则无需遍历Cookie数组,直接返回
if(null==cks) return;
//定义两个变量,用于存储Cookie的值
String uname="";
String upwd="";
//如果有Cookie,则遍历Cookie数组,读取Cookie的值即可
for(Cookie c:cks){ //对于数组cks中的每个Cookie对象
//如果当前遍历的cookie的名称是username
if("username".equals(c.getName()))
uname=c.getValue(); //获取其值,存储到变量uname中
else if("userpwd".equals(c.getName())) //如果当前遍历的cookie的名称是userpwd
upwd=c.getValue(); //获取其值,存储到变量upwd中
}
%>
<br>用户:<%=uname%>
<br>密码:<%=upwd%>
<h1 class="text-center text-success">登录成功,<%=uname%>,欢迎进入教务系统</h1>
<a href="#" class="logout">退出登录</a>
<hr>
<br>
<a href="profile.jsp">查看个人信息</a>
</div>
</body>
</html>
profile.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>个人信息</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center text-warning">个人信息</h1>
<hr>
<br>
<%
//JSP提供隐式对象request,表示该页面收到的请求
//通过请求对象可以获取到该程序放的所有Cookie,以Cookie数组的形式返回
Cookie[] cks=request.getCookies();
//也可能一个Cookie都没有,则无需遍历Cookie数组,直接返回
if(null==cks) return;
//定义两个变量,用于存储Cookie的值
String uname="";
String upwd="";
//如果有Cookie,则遍历Cookie数组,读取Cookie的值即可
for(Cookie c:cks){ //对于数组cks中的每个Cookie对象
//如果当前遍历的cookie的名称是username
if("username".equals(c.getName()))
uname=c.getValue(); //获取其值,存储到变量uname中
else if("userpwd".equals(c.getName())) //如果当前遍历的cookie的名称是userpwd
upwd=c.getValue(); //获取其值,存储到变量upwd中
}
%>
<br>用户:<%=uname%>
<br>密码:<%=upwd%>
</div>
</body>
</html>
C02_D04_Session
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录首页</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
<form action="ls" class="form-inline text-center loginForm bg-cyan">
<h1 class="text-center">用户登录</h1>
<hr>
<br>
学 号: <input type="text" name="rollno" class="form-control">
<br><br>
密 码: <input type="password" name="pwd" class="form-control">
<br><br>
<input type="submit" value="登录" class="btn btn-sm btn-default">
</form>
</div>
</body>
</html>
success.jsp
<%@page import="com.qdu.pojo.Student"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center text-success">欢迎进入教务系统</h1>
<%
//根据属性名获取会话中的属性值
//如果需要转换到对应类型,需要强制转换
Student s=(Student)session.getAttribute("student");
%>
<a href="#" class="info">当前登录:<%=s.getSname() %> </a>
<a href="los" class="logout">退出登录</a>
<hr><br>
<!--jsp提供隐式对象session,用于在jsp页面上访问当前的会话对象-->
<ul class="list-menu">
<li><a href="profile.jsp">查看个人信息</a></li>
<li><a href="#">查询班级课表</a></li>
<li><a href="#">查看个人成绩</a></li>
</ul>
</div>
</body>
profile.jsp
<%@page import="com.qdu.pojo.Student"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>个人信息</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center text-warning">个人信息</h1>
<hr>
<br>
<div class="content-container">
<%
//放入会话的数据可以在程序中的任何jsp页面或servlet中获取到
//因为只要会话没有结束,则数据会一直存在于会话中,除非手动清除
Student stu=(Student)session.getAttribute("student");
%>
<br>学号: <%=stu.getSrollno() %>
<br>姓名: <%=stu.getSname()%>
<br>性别: <%=stu.getSgender()%>
<br>密码: <%=stu.getSpassword()%>
<br>班级: <%=stu.getSbatch()%>
<br>
<!--title用于指定鼠标悬到图片上的提示文字-->
<!--alt用于指定图片无法正常显示的时候的替代文字-->
<img class="photo" width="150" height="150"
src="images/<%=stu.getSrollno()%>.jpg"
alt="<%=stu.getSname()%>"
title="<%=stu.getSname()%>">
</div>
</div>
</body>
</html>
DatabaseUtil
package com.qdu.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* 数据库工具类,帮助获取到对应数据库的连接和关闭连接
*
* @author Anna
*/
public class DatabaseUtil {
private static final String DRIVER_CLASS="com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String URL="jdbc:sqlserver://localhost:1433;databaseName=QDU";
private static final String USERNAME = "sa";
private static final String PASSWORD = "sa";
/**
* 获取数据库连接
*
* @return 一个数据库连接对象
*/
public static Connection getConnection() {
try {
Class.forName(DRIVER_CLASS);
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
/**
* 关闭数据库连接
*
* @param rs 结果集对象
* @param ps 语句对象
* @param con 连接对象
*/
public static void close(ResultSet rs, PreparedStatement ps, Connection con) {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
if (null != con) {
con.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
LoginServlet
package com.qdu.servlet;
import com.qdu.dao.StudentDao;
import com.qdu.pojo.Student;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/ls")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String rollno = req.getParameter("rollno");
String pwd = req.getParameter("pwd");
StudentDao dao=new StudentDao();
Student stu=dao.findStudentByRollno(rollno);
//如果stu不为null,说明学号正确,只需要再判断密码即可
if (null!=stu&&pwd.equals(stu.getSpassword())) {
//会话技术就是为每一个浏览器用户分配一个HttpSession对象
//用于在会话期间维护一些用户数据
//getSession()获取和请求关联的会话对象,如果还没有会话对象,则创建一个新的会话对象
//getSession(false)获取和请求关联的会话对象,如果还没有会话,返回null
//HttpSession session=req.getSession(false);
HttpSession session=req.getSession();
//你可以将在会话期间共享的数据作为属性(attribute)放入会话对象
//一个属性由一个属性名和一个属性值构成,后续使用的时候通过属性名获取属性值
//属性名必须是字符串,属性的值可以是任何对象,如一个字符串,一个学生对象等
session.setAttribute("student",stu);
//session.setAttribute("number", 10);
resp.sendRedirect("success.jsp");
} else {
resp.sendRedirect("fail.html");
}
}
}
Student.java
package com.qdu.pojo;
/**
* 学生实体类,用于存储学生所有信息
*
* @author NIIT
*/
public class Student {
private String srollno;
private String sname;
private String sgender;
private String sbatch;
private String spassword;
public Student() {
}
public Student(String srollno, String sname, String spassword, String sgender, String sbatch) {
this.srollno = srollno;
this.sname = sname;
this.sgender = sgender;
this.sbatch = sbatch;
this.spassword = spassword;
}
public String getSrollno() {
return srollno;
}
public void setSrollno(String srollno) {
this.srollno = srollno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSgender() {
return sgender;
}
public void setSgender(String sgender) {
this.sgender = sgender;
}
public String getSbatch() {
return sbatch;
}
public void setSbatch(String sbatch) {
this.sbatch = sbatch;
}
public String getSpassword() {
return spassword;
}
public void setSpassword(String spassword) {
this.spassword = spassword;
}
}
StudentDao.java
package com.qdu.dao;
import com.qdu.pojo.Student;
import com.qdu.util.DatabaseUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* Dao类-数据访问对象类,专门用于访问数据库中的表 <br>
* StudentDao包含方法用于对StudentMark表执行增删改查, 这里只封装了一个方法用于查询
*
* @author Anna
*/
public class StudentDao {
/**
* 根据学号查询学生所有信息
*
* @param rollno 学生学号
* @return 包含学生所有信息的学生对象
*/
public Student findStudentByRollno(String rollno) {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = DatabaseUtil.getConnection();
ps = con.prepareStatement("select * from student where Srollno=?");
ps.setString(1, rollno);
rs = ps.executeQuery();
if (rs.next()) {
return new Student(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DatabaseUtil.close(rs, ps, con);
}
return null;
}
}
LogoutServlet
package com.qdu.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/los")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//getSession(false)获取已有的会话对象,如果还没有会话对象,则返回null
HttpSession session = req.getSession(false);
if (null != session) {//如果会话不为null
session.invalidate(); //调用invalidate()使会话无效,也就是立刻结束会话
resp.sendRedirect("index.html"); //退出登录后回到首页
//session.setMaxInactiveInterval(10*60); 单位是秒
}
}
}
C02_D06_SessionExercise
index.html
<!DOCTYPE html>
<html>
<head>
<title>天猫首页</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="images/shortcut.png" rel="shortcut icon" type="image/x-icon"/>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
<div class="top">
<div class="top_left"><img src="images/tmall.png" alt="天猫logo"></div>
<div class="top_right"><h1>欢迎来到天猫,理想生活上天猫......</h1></div>
</div>
<hr>
<h3>最新活动</h3>
<br>
<ul>
<!--可以通过url重写追加请求参数,体现是不同的产品-->
<li><a href="ps?pid=P001">卫龙辣条,你值得拥有</a></li>
<li><a href="ps?pid=P002">青岛大虾,不一样的大虾</a></li>
<li><a href="ps?pid=P003">四级真题,600包过</a></li>
<li><a href="ps?pid=P004">快乐肥宅水,你今天快乐了吗?</a></li>
</ul>
<br>
<a href="cart.jsp">查看购物车</a>
</div>
</body>
</html>
style.css
.top{
height: 120px;
}
.top_left{
width: 20%;
float:left;
}
.top_right{
width: 80%;
float:left;
}
.top_right h1{
height: 100px;
line-height: 100px;
margin-left:50px;
color: darkred;
}
.content{
position: relative;
padding-left: 300px;
width: 700px;
margin: 30px auto;
}
.pic{
position: absolute;
top: 20px;
left: 0px;
width: 250px;
height: 250px;
}
.viewcart{
position: fixed;
top: 30px;
right: 30px;
}
.title{
color: brown;
text-align: center;
}
form .form-control{
width: 60px!important;
}
.cartProduct{
position: relative;
}
.cartProduct img{
position: absolute;
top: 11px;
left: 200px;
border-radius: 100px;
border: solid lightgray 1px;
}
ul{
line-height: 30px;
}
ProductDao.java
package com.tianmao.dao;
import com.tianmao.util.DatabaseUtil;
import com.tianmao.entity.Product;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
/**
* Dao类-数据访问对象类,专门用于访问数据库中的表ProductDao包含方法用于对Product表执行增删改查
* @author Anna
*/
public class ProductDao {
/**
* 查询所有产品的列表
* @return 产品列表
*/
public List<Product> getProductList() {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
List<Product> productList=new ArrayList();
try {
con = DatabaseUtil.getConnection();
ps = con.prepareStatement("select * from Product");
rs = ps.executeQuery();
while (rs.next()) {
productList.add(new Product(rs.getString(1),rs.getString(2),rs.getFloat(3),rs.getString(4),rs.getInt(5)));
}
return productList;
} catch (Exception e) {
e.printStackTrace();
} finally{
DatabaseUtil.close(rs,ps,con);
}
return null;
}
/**
* 根据产品编号查询产品信息
* @param productId 字符串表示的产品编号
* @return 包含产品所有信息的一个Product对象,如果没有查询到该产品,则返回null
*/
public Product findProductById(String productId) {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = DatabaseUtil.getConnection();
ps = con.prepareStatement("select * from Product where productId=?");
ps.setString(1, productId);
rs = ps.executeQuery();
if (rs.next()) {
return new Product(rs.getString(1),rs.getString(2),rs.getFloat(3),rs.getString(4),rs.getInt(5));
}
} catch (Exception e) {
e.printStackTrace();
} finally{
DatabaseUtil.close(rs,ps,con);
}
return null;
}
}
ProductServlet
package com.tianmao.servlet;
import com.tianmao.dao.ProductDao;
import com.tianmao.entity.Product;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 该Servlet处理根据产品编号查询产品的请求,然后将查询出来的产品信息交给productInfo.jsp显示
*
* @author Anna
*/
@WebServlet("/ps")
public class ProductServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 获取请求参数
String pid=req.getParameter("pid");
//2. 执行业务逻辑,完成请求处理
ProductDao dao=new ProductDao();
Product pro=dao.findProductById(pid); //根据产品编号查询单个产品的所有信息
//3. 将查询到的信息共享给productInfo.jsp页面显示
//如果希望将一些信息共享到下个servlet或jsp,而不是通过会话共享
//则可以考虑将信息作为属性添加到请求对象,然后转发请求
//可以将产品对象作为一个属性放入请求对象,这里属性名是product
req.setAttribute("product", pro);
//将同一个请求对象和响应对象转发给productInfo.jsp
//这样productInfo.jsp收到的请求是同一个请求,所以可以获取到共享的数据
//forward转发
req.getRequestDispatcher("/productInfo.jsp").forward(req, resp);
}
}
productInfo.jsp
<%@page import="com.tianmao.entity.Product"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="images/shortcut.png" rel="shortcut icon" type="image/x-icon"/>
<title>产品信息</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<h1 class="text-center text-primary">产品信息</h1>
<hr>
<br>
<!--在此div中显示从数据库查询到的一个产品的所有信息-->
<%
//因为ps这个servlet转发了请求给productInfo.jsp
//所以productInfo.jsp收到的请求就是ps收到的请求,两个处理的是同一个请求
Product p=(Product)request.getAttribute("product");
%>
<div class="content">
<br>
<!--显示产品图片,图片在images文件夹中给出了,以产品的编号命名的图片-->
<img src="images/<%=p.getProductId()%>.jpg" class="pic">
<h3>产品名称: <%=p.getProductName() %> </h3>
<p>产品单价: <%=p.getProductPrice()%> </p>
<p>包装单位: <%=p.getProductUnit()%> </p>
<p>剩余库存: <%=p.getProductQty()%> </p>
<!--提交请求给cs,添加产品到购物车 shopping cart-->
<form action="cs" class="form-inline">
<b>购买数量:</b>
<input type="number" min="1" name="qty" value="1" class="form-control">
<br><br>
<!--在表单中,如果有些数据需要隐式地提交,则可以使用隐藏字段-->
<input type="hidden" name="pid" value="<%=p.getProductId()%>">
<!--为了简化程序,后续不再次查询数据库,我们考虑将产品的其他信息一起提交-->
<input type="hidden" name="pname" value="<%=p.getProductName() %>">
<input type="hidden" name="pprice" value="<%=p.getProductPrice() %>">
<input type="hidden" name="punit" value="<%=p.getProductUnit() %>">
<input type="submit" value="加入购物车" class="btn btn-sm btn-danger">
<input type="submit" value="立刻购买" class="btn btn-sm btn-warning">
</form>
</div>
<br>
<a href="cart.jsp" class="viewcart">查看购物车</a>
</body>
</html>
CartServlet
package com.tianmao.servlet;
import com.tianmao.entity.Product;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.swing.JButton;
/**
* 点击“加入购物车”按钮,添加产品到购物车,该Servlet负责处理添加到购物车的请求
*
* @author Anna
*/
@WebServlet("/cs")
public class CartServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 获取请求参数
String pid = req.getParameter("pid"); //Ctrl+Shift+上/下
String pname = req.getParameter("pname");
//byte,short,int,long,float,double,char,boolean
//Byte,Short,Integer,Long,Float,Double,Character,Boolean
float pprice = Float.parseFloat(req.getParameter("pprice"));
String punit = req.getParameter("punit");
int qty = Integer.parseInt(req.getParameter("qty"));
//为了更方便的操作产品的5项信息,可考虑将其封装成一个产品对象
//但是这里的数量表示的不是库存量,而是加入购物车的数量
Product p = new Product(pid, pname, pprice, punit, qty);
//可以考虑维护一个Product列表,用于存储购物车中所有产品的信息
//添加一个产品到购物车,也就是添加一个产品对象到该列表中
List<Product> list=null; //定义一个变量,表示购物车列表
HttpSession session=req.getSession(); //获取会话对象
//如果会话中已经有了cartList属性,说明不是第一次添加产品到购物车
//否则说明是第一次添加产品到购物车
if(null!=session.getAttribute("cartList")){
//如果已经有列表,获取该购物车列表,赋值给变量list
//因为实际放入的是一个List<Product>类型,所以可以强制转换类型
list=(List<Product>)session.getAttribute("cartList");
list.add(p); //添加本次的产品到购物车列表
}else{ //第一次添加产品到购物车
list=new ArrayList(); //创建购物车列表
list.add(p); //添加第一个产品到购物车列表
//为了让购物车列表在会话期间可访问,可将购物车列表添加到会话中
session.setAttribute("cartList",list); //将购物车列表作为一个属性添加到会话对象
}
//因为列表是在会话中,不是在请求对象中,所以直接重定向到cart.jsp页面显示购物车列表即可
resp.sendRedirect("cart.jsp");
}
}
cart.jsp
<%@page import="java.util.List"%>
<%@page import="com.tianmao.entity.Product"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="images/shortcut.png" rel="shortcut icon" type="image/x-icon"/>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
<title>购物车信息</title>
</head>
<body>
<div class="container">
<h1 class="text-center text-danger">购物车信息</h1>
<!--这里给出了购物车中一个产品的显示格式-->
<%
//根据属性名cartList获取属性值,值是一个List<Product>对象
List<Product> clist=(List)session.getAttribute("cartList");
if(null==clist){
out.println("<br><h1>尚未添加任何产品到购物车!!!</h1>");
return; //如果没有产品,无需遍历,直接返回即可,这样后面的代码都不会执行
}
//如果购物车中有产品,则执行后续代码,遍历列表
float total=0; //定义一个变量,用于存储总计金额
for(Product p:clist){ //对于集合clist中的每个产品
total+=p.getProductPrice() * p.getProductQty(); //总计金额每次在原来的基础上加上当前产品的小计金额
%>
<div class="cartProduct">
<img src="images/<%=p.getProductId()%>.jpg" width="120" height="120">
<hr>
产品名称:<%=p.getProductName() %>
<br>产品单价:<%=p.getProductPrice() %>
<br>包装单位:<%=p.getProductUnit() %>
<br>购买数量:<%=p.getProductQty() %>
<br><b class="text-primary">小计金额:<%=p.getProductPrice() * p.getProductQty()%></b>
</div>
<% } %>
<hr>
<h3 class="text-danger">总计金额:<%=total%></h3>
</div>
</body>
</html>
C02_D05_Listeners
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<title>Servlet相关的监听器</title>
</head>
<body class="bg-danger">
<div class="container">
<h1 class="text-center text-primary">Servlet相关的监听器</h1>
<hr>
<h2>(1). 会话(HttpSession)相关监听器</h2>
<br>
<a href="second.jsp" class="text-danger">* 跳转到页面2</a>
<br><br>
<a href="s1">* 开始会话</a>
<br><br>
<a href="s2">* 结束会话</a>
<br><br>
<a href="s3">* 操作会话中的属性</a>
<hr>
<h2>(2). 上下文(ServletContext)相关监听器</h2>
<br>
<a href="s4">* 操作上下文中的属性</a>
<hr>
<h2>(3). 请求(ServletRequest)相关监听器</h2>
<br>
<a href="s5">* 请求Servlet5</a>
<br><br>
<a href="s6">* 操作请求对象中的属性</a>
<hr>
</div>
</body>
</html>
second.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<title>页面2</title>
</head>
<body>
<div class="container bg-success">
<h1>页面2</h1>
<hr>
<br>
<%=session.getAttribute("name") %>
<br>
<br>
<br>
</div>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.xsd">
<listener>
<description>监听会话的创建和摧毁</description>
<listener-class>com.qdu.listener.MySessionListener</listener-class>
</listener>
<listener>
<description>监听会话对象中属性的变化</description>
<listener-class>com.qdu.listener.MySessionAttributeListener</listener-class>
</listener>
<listener>
<description>监听上下文对象的创建和摧毁</description>
<listener-class>com.qdu.listener.MyContextListener</listener-class>
</listener>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Servlet1
package com.qdu.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/s1")
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session=req.getSession();
session.setAttribute("name", "Anna");
resp.sendRedirect("index.html");
}
}
MySessionListener
package com.qdu.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* 会话监听器(HttpSessionListener)
* <br>监听会话对象的创建和摧毁事件
*
* @author Anna
*/
//创建监听器(listener),绝大部分监听器都是接口
//1. 如果想创建对应的监听器类,实现对应的监听器接口即可
//2. 在web.xml中或使用@WebListener注册监听器
//@WebListener
public class MySessionListener implements HttpSessionListener{
//该方法响应会话对象被创建而调用,并且自动传入一个参数,参数是一个事件对象
//包含事件发生的信息,如创建的会话
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("有新会话被创建,会话编号:"+se.getSession().getId());
}
//该方法响应会话对象被摧毁而调用,并且自动传入一个参数,参数是一个事件对象
//包含事件发生的信息,如创建的会话
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("有会话被摧毁,会话编号:"+se.getSession().getId());
}
}
MySessionAttributeListener
package com.qdu.listener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
/**
* 创建会话属性监听器(HttpSessionAttributeListener)
* <br>监听会话对象中属性的添加、修改和删除事件
*
* @author Anna
*/
public class MySessionAttributeListener implements HttpSessionAttributeListener{
//当监听到会话中添加了新属性后,attributeAdded()被调用
//并自动传入一个事件对象,包含事件信息
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
//通过事件对象可以获取添加的属性的信息,或者获取会话对象进行一些操作
//getName()获取添加的属性的名称,getValue()获取添加的属性的值
System.out.println("会话中添加了新属性,属性:"+event.getName()+"-"+event.getValue());
}
//当监听到会话中删除了属性后,attributeRemoved()被调用
//并自动传入一个事件对象,包含事件信息
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println("会话中删除了属性,属性:"+event.getName()+"-"+event.getValue());
}
//当监听到会话中修改了一个属性后,attributeReplaced()被调用
//并自动传入一个事件对象,包含事件信息
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println("会话中修改了属性,属性:"+event.getName()+"-"+event.getValue());
}
}
Servlet4
package com.qdu.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/s4")
public class Servlet4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//在Servlet中获取程序的上下文对象
//在Servlet中可调用继承的getServletContext()方法获取上下文对象
ServletContext ctx=getServletContext();
//放入上下文对象的属性是整个程序中可用
ctx.setAttribute("count", 1000); //第一次设置一个属性是添加属性
ctx.setAttribute("count", 2000); //第二次设置已有的属性是修改属性
ctx.removeAttribute("count"); //removeAttribute()用于删除一个属性ctx.setAttribute("count", 1000);
resp.sendRedirect("index.html");
}
}
MyContextListener
package com.qdu.listener;
//ServletContext Servlet上下文
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
//一个程序有且仅有一个上下文对象,用于在整个程序期间使用,可用于在程序中共享数据
//你觉得程序的上下文对象什么时候被创建,什么时候被摧毁?
/**
* 创建上下文监听器(ServletContextListener)
* <br>监听器上下文对象的初始化和摧毁事件
*
* @author Anna
*/
//程序上下文对象在程序启动的时候就会被创建和初始化
//一般是程序停止或关闭服务器才会导致上下文对象被摧毁
//@WebListener
public class MyContextListener implements ServletContextListener{
//当监听器监听到上下文对象被初始化,初始化也就是意味着对象被创建了
//并且自动传入一个事件对象,包含事件信息,可通过该对象获取上下文对象进行操作
@Override
public void contextInitialized(ServletContextEvent sce) {
//一般如果程序启动就需要加载一些数据到上下文对象中,方便程序后面使用
//一般需要在该方法中写代码
System.out.println("上下文对象被创建!");
}
//当监听器到上下文对象被摧毁,该方法被调用
//并且自动传入一个事件对象,包含事件信息,可通过该对象获取上下文对象进行操作
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("上下文对象被摧毁!");
}
}
MyContextAttributeListener
package com.qdu.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;
/**
* 创建上下文属性监听器(ServletContextAttributeListener)
* <br>监听上下文对象中属性的添加、修改和删除事件
*
* @author Anna
*/
@WebListener //和在web.xml中使用listener标记注册监听器等效,使用其中一个方式即可
public class MyContextAttributeListener implements ServletContextAttributeListener{
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
System.out.println("上下文对象中添加了新属性,属性:"+event.getName()+"-"+event.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
System.out.println("上下文对象中删除了属性,属性:"+event.getName()+"-"+event.getValue());
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
System.out.println("上下文对象中修改了属性,属性:"+event.getName()+"-"+event.getValue());
}
}
Servlet5
package com.qdu.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/s5")
public class Servlet5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out=resp.getWriter();
out.println("<h1>Hi, This is Servlet5!</h1>");
}
}
MyRequestListener
package com.qdu.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
/**
* 创建请求监听器(ServletRequestListener)
* <br>监听器请求对象的初始化和摧毁事件
*
* @author Anna
*/
//@WebListener
public class MyRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
System.out.println("摧毁了请求对象,请求路径为:" + req.getRequestURI());
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
System.out.println("创建了新的请求对象,请求路径为:" + req.getRequestURI());
}
}
MyRequestAttributeListener
package com.qdu.listener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
/**
* 创建请求属性监听器(ServletRequestAttributeListener)
* <br>监听请求对象中属性的添加、修改和删除事件
*
* @author Anna
*/
public class MyRequestAttributeListener implements ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent event) {
System.out.println("请求对象中添加了新属性:" + event.getName() + "-" + event.getValue());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent event) {
System.out.println("请求对象中删除了属性:" + event.getName() + "-" + event.getValue());
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent event) {
System.out.println("请求对象中修改了属性:" + event.getName() + "-" + event.getValue());
}
}
Servlet6
package com.qdu.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/s6")
public class Servlet6 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name", "小强");
req.setAttribute("name", "小红");
req.removeAttribute("name");
resp.sendRedirect("index.html");
}
}
输入5 和 2
被除数是0时
输入字母时
index.html
<!DOCTYPE html>
<html>
<head>
<title>了解状态码</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
<br>
<h1 class="text-center text-danger">了解状态码</h1>
<p>* 地址栏Url故意打错或除数输入0或字母查看状态码,该程序要求输入的是整数</p>
<p>* 该程序主要是认识和了解状态码,所以并没有让你们去写任何代码</p>
<hr>
<br>
<form action="cs" class="form-inline">
<table>
<tr>
<td colspan="2">
<h3 class="text-center">计算器</h3>
</td>
</tr>
<tr>
<td>输入被除数:</td>
<td><input type="text" name="num1" class="form-control"></td>
</tr>
<tr>
<td>输入除数:</td>
<td><input type="text" name="num2" class="form-control"></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" class="btn btn-sm btn-danger" value="计算">
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
CalculateServlet
package com.qdu.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/cs")
public class CalculateServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int a=Integer.parseInt(request.getParameter("num1"));
int b=Integer.parseInt(request.getParameter("num2"));
int result=a/b;
response.setContentType("text/html;charset=utf-8");
try (PrintWriter out = response.getWriter()) {
out.println("<br><h1>计算结果:" + result + "</h1>");
}
}
}
C02_D08_HandleError1
index.html
<!DOCTYPE html>
<html>
<head>
<title>处理错误</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h1 class="text-center text-danger">处理错误-自定义错误页面</h1>
<hr>
<br>
<ul>
<li><a href="download.html">四六级真题下载园地</a></li>
<li><a href="cet4Answer.jsp">2017年12月四级答案</a></li>
<li><a href="takeCet4Servlet">四级模拟测试</a></li>
<li><a href="secret.html">秘诀-如何取得四级600分</a></li>
</ul>
<br>
<br>
<a href="images/longmao1.gif" title="查看原图">
<img src="images/longmao1.gif" alt="行走的龙猫" width="250" height="182">
</a>
<a href="images/longmao.gif" title="查看原图">
<img src="images/longmao2.gif" alt="行走的龙猫" width="182" height="182">
</a>
</div>
</body>
</html>
目录里并没有这些资源,访问
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<!--error-page用于配置错误页面-->
<error-page>
<!--error-code指定针对的错误代码-->
<error-code>404</error-code>
<!--location:位置,用于指定错误页面的位置,也就是路径-->
<location>/error_page.jsp</location>
</error-page>
</web-app>
error_page.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>这个.. 页面没有找到!!!</title>
<style type="text/css">
body{ margin:0; padding:0; font-family: 微软雅黑; }
div#mother{ margin:0 auto; width:943px; height:572px; position:relative; }
div#errorBox{ background: url(${pageContext.request.contextPath}/images/longmao3.gif) no-repeat center left; width:943px; height:572px; margin:auto; }
div#errorText{ color:#39351e; padding:185px 0 0 456px }
div#errorText p{ width:303px; font-size:14px; line-height:26px; }
div.link{ height:50px; width:145px; float:left;background-color:red;color: black; }
div#home{ margin:0 0 0 444px;}
div#contact{ margin:0 0 0 25px;}
h1{ font-size:40px; margin-bottom:35px; }
</style>
</head>
<body>
<div id="mother">
<div id="errorBox">
<div id="errorText">
<h1>Sorry..页面没有找到!</h1>
<p>似乎你所寻找的网页已移动或丢失了。</p>
<p>请不要担心,这没事。</p>
<p>如果该资源对你很重要,请与<a href="mailto: anna@163.com">管理员</a>联系。</p>
<p>火星不太安全,我可以免费送你回地球!</p>
</div>
</div>
</div>
</body>
</html>
C02_D09_HandleError2
index.html
<!DOCTYPE html>
<html>
<head>
<title>处理错误和异常</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
<br>
<h1 class="text-center text-danger">处理错误和异常</h1>
<p>* 地址栏Url故意输入0或字母查看状态码,该程序要求输入的是整数</p>
<hr>
<br>
<form action="cs" class="form-inline">
<table>
<tr>
<td colspan="2">
<h3 class="text-center">计算器</h3>
</td>
</tr>
<tr>
<td>输入被除数:</td>
<td><input type="text" name="num1" value="100" class="form-control"></td>
</tr>
<tr>
<td>输入除数:</td>
<td><input type="text" name="num2" value="0" class="form-control"></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" class="btn btn-sm btn-danger" value="计算">
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
style.css
h1{
text-align: center;
color: brown;
}
table td{
padding: 5px;
}
CalculateServlet
package com.qdu.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/cs")
public class CalculateServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int num1 = Integer.parseInt(request.getParameter("num1"));
int num2 = Integer.parseInt(request.getParameter("num2"));
int result = 0;
result = num1 / num2;
response.setContentType("text/html;charset=utf-8");
try (PrintWriter out = response.getWriter()) {
out.println("<br><h1>计算结果:" + result + "</h1>");
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<!--可以针对错误代码配置错误页面-->
<!--
<error-page>
<error-code>500</error-code>
<location>/error_500.html</location>
</error-page>
-->
<!--也可针对异常类型配置错误页面-->
<!--exception-type标记指定针对的异常类型-->
<!--
<error-page>
<exception-type>java.lang.ArithmeticException</exception-type>
<location>/error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.NumberFormatException</exception-type>
<location>/error.jsp</location>
</error-page>
-->
<!--所有的异常类都直接或间接实现了Throwable接口,所以java.lang.Throwable表示所有异常-->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
</web-app>
error.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>异常错误页面</title>
<link rel="stylesheet" href="css/bootstrap.min.css"/>
</head>
<body class="bg-warning">
<div class="container">
<br>
<h1 class="text-center text-danger">异常错误页面</h1>
<hr>
<!--如果发生异常,转到指定的错误页面(错误页面可以是一个页面或一个servlet),
异常信息会传送到该页面,所以可以获取错误异常信息
服务器通过请求对象的setAttribute()方法将异常信息放入到请求对象
所以在错误页面,可通过请求的getAttribute()方法获取异常信息
-->
<%
out.println("<br>状态代码: " + request.getAttribute("javax.servlet.error.status_code"));
out.println("<br>异常消息: " + request.getAttribute("javax.servlet.error.message"));
out.println("<br>异常类型: " + request.getAttribute("javax.servlet.error.exception_type"));
//获取程序的上下文对象吧
ServletContext ctx = getServletContext();
//也可根据需求自己写入信息到日志
ctx.log("异常消息:"+request.getAttribute("javax.servlet.error.message"));
%>
</div>
</body>
</html>
error_500.html
<!DOCTYPE html>
<html>
<head>
<title>状态代码500-错误页面</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1 style="color: red;text-align: center;">500-服务器端出错,<a href="#">发送</a>信息给管理员!</h1>
</body>
</html>
C02_D10_setStatus
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>百搜一下,你就知道</title>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<h1>百搜-搜天下</h1>
<form>
<input type="text">
<input type="submit" value="百搜一下">
</form>
<%
//特殊的情况下,需要自行决定发送给客户端的状态码
//可调用以下两个方法
//sendError()方法 用于发送4或5开头的错误代码
//setStatus()方法 用于发送非错误状态代码
//响应报头location用于指定一个目标url
response.setHeader("location","https://www.baidu.com");
//response.setStatus(301);
//永久地 permanently 301永久重定向,说明永久定向导新的地址
//临时地 temporarily 302临时重定向,说明临时定向到新的地址
//除了用对应的数字状态码,也可使用HttpServletResponse接口中的各种常量名
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
//www.tianmao.com
//www.tianmaomao.com
//可以只指定发送的错误代码
//response.sendError(410);
//也可同时指定发送的错误代码和一个消息
//response.sendError(410, "该资源已经永久删除了!");
%>
</body>
</html>
C02_D11_sendError
index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>百搜一下,你就知道</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>百搜搜-搜天下</h1>
<form>
<input type="text">
<input type="submit" value="百搜一下">
</form>
<%
//可以只指定发送的错误代码
//response.sendError(410);
//也可同时指定发送的错误代码和一个消息
//response.sendError(410, "该资源已经永久删除了!");
%>
</body>
</html>
style.css
body{font-family:微软雅黑;}
h1{text-align: center; color:darkcyan;margin-top: 100px;}
form{width: 650px; margin: 50px auto;}
input[type="text"]{width: 500px; height: 40px; outline: none; border: solid 1px lightblue; padding: 0 10px; border-radius: 5px;}
input[type="submit"]{width: 100px; height: 42px;border-radius: 5px; background-color: chocolate; border: none;
color: white; font-size: 18px;}
input[type="submit"]:hover{cursor: pointer; background-color: crimson;}
C02_D12_RequestDispatch_ResponseRedirect
index.html
<!DOCTYPE html>
<html>
<head>
<title>请求转发和响应重定向</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<br>
<h1 class="text-center text-danger">请求转发和响应重定向</h1>
<hr>
<br>
<ul>
<li><a href="firstServlet?flag=1">1. 响应重定向-sendRedirect</a></li>
<li><a href="firstServlet?flag=2">2. 请求转发-forward</a></li>
<li><a href="firstServlet?flag=3">3. 请求转发-include</a></li>
</ul>
</div>
</body>
</html>
second.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>页面second</title>
</head>
<body>
<div style="color:red;">
<p>****************************************************************</p>
<h1>页面second的内容</h1>
<!--获取一下请求参数flag的值,看看是不是同一个请求对象-->
<p>请求参数flag: <%=request.getParameter("flag")%> </p>
<p>请求中的属性: <%=request.getAttribute("number")%> </p>
<p>****************************************************************</p>
</div>
</body>
</html>
1
FirstServlet
package com.qdu.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/firstServlet")
public class FirstServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
out.println("<br><h1>这是FirstSevlet输出的内容-开始</h1>");
//获取请求参数flag的值并将其转换成整数
int flag=Integer.parseInt(req.getParameter("flag"));
switch(flag){
case 1: //实现重定向
//1)最后显示重定向后资源的内容
//2) 地址栏显示重定向后的资源的url
//3) 整个过程中产生了2个请求,重定向是发起一个新请求,请求重定向后的资源(页面或servlet等)
resp.sendRedirect("second.jsp"); //重定向到second.jsp
break;
case 2: //调用forward()方法转发请求
//1)最后显示转发后的资源的内容
//2) 地址栏显示转发向前的资源的url
//3) 整个过程中产生了1个请求
//request请求 dispatch派遣、派发 forward转发
//请求对象的getRequestDispatcher()用于获取一个可以派发/转发请求的请求派发器对象
//一个RequestDispatcher对象是可以用于派发请求的对象,需要指定转发目标,也就是请求转发给谁
//目标的url可以用相对路径或类似绝对路径(/开头)
//RequestDispatcher rd=req.getRequestDispatcher("/second.jsp");
//调用forward()方法转发请求即可
//该方法接受两个参数,表示要转发的请求对象和响应对象
//这样导致转发请求的组件(servlet或jsp)和目标组件(servlet或jsp)收到的请求对象和响应对象都是同一个
//rd.forward(req, resp);
//也可获取了请求派遣器对象后直接操作,而不用变量接收请求派遣器对象
//如果产生了一些数据,需要共享给下个组件(servlet或jsp),一般选择转发请求
//可以将数据作为属性放入请求对象,然后转发请求
req.setAttribute("number",666666);
req.getRequestDispatcher("/second.jsp").forward(req, resp);
break;
case 3: //调用include()方法转发请求,将转发后的组件(second.jsp)的内容包含到当前组件(FirstServlet)中显示
//A->B forward转发 B
//A->B include转发 A+B
//1)最后显示转发前+后的资源的内容
//2) 地址栏显示转发向前的资源的url
//3) 整个过程中产生了1个请求
req.getRequestDispatcher("/second.jsp").include(req, resp);
break;
}
out.println("<h1>这是FirstSevlet输出的内容-结束</h1>");
}
}
C02_D13_ThreadModel1
index.html
<!DOCTYPE html>
<html>
<head>
<title>Servlet线程模型</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css"/>
</head>
<body style="background-color: antiquewhite;">
<h1>Servlet线程模型-多线程模型和单线程模型</h1>
<hr>
<br>
<a class="sa" href="servletA">请求ServletA-抽小奖</a>
<a class="sb" href="servletB">请求ServletB-抽大奖</a>
</body>
</html>
style.css
h1{
color: darksalmon;
text-align: center;
}
a{
display: block;
width: 200px;
height: 40px;
line-height: 40px;
margin: 30px auto;
background-color: darkcyan;
color: white;
text-align: center;
text-decoration: none;
}
a.sb{
background-color: red;
}
a:hover{
text-decoration: underline;
background-color: brown;
}
ServletA
package com.qdu.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//默认一个Servlet使用多线程模型处理请求, 单实例,多线程
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
//一旦一个Servlet被实例化之后,接着会被初始化,所以初始化了,说明已经实例化
//init()
//service()->doGet()/doPost()
//destroy()
//所以可以重写init()方法看看实例化几次
@Override
public void init() throws ServletException {
System.out.println("ServletA被实例化!!!");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Random rand = new Random();
int money = rand.nextInt(10001) + 10000;
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("<br><h1 style='text-align: center;'>ServletA</h1>");
out.println("<hr><br><br>");
if (money % 3 == 0) {
out.println("<h1 style='text-align: center; color: red;'>恭喜您中得" + money + "元,随便花!</h1>");
} else {
out.println("<h1 style='text-align: center; color: black;'>很遗憾,您未中奖,还是好好学习吧!</h1>");
}
}
}
}
ServletB
package com.qdu.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.SingleThreadModel;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//单线程模型: 多实例,多线程,需要实现SingleThreadModel接口,就可以应用单线程模型
@WebServlet("/servletB")
public class ServletB extends HttpServlet implements SingleThreadModel{
@Override
public void init() throws ServletException {
System.out.println("ServletB被实例化.............");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Random rand = new Random();
int money = rand.nextInt(1000001) + 1;
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("<br><h1 style='text-align: center;'>ServletB</h1>");
out.println("<hr><br><br>");
if (money % 7 == 0) {
out.println("<h1 style='text-align: center; color: red;'>恭喜您中得" + money + "元,随便花!</h1>");
} else {
out.println("<h1 style='text-align: center; color: black;'>很遗憾,您未中奖,革命尚未成功,同志仍需努力啊!</h1>");
}
}
}
}
C02_D14_ThreadModel2_Synchronization
index.html
<html>
<head>
<title>Servlet线程模型-同步化</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<br>
<h1>Servlet线程模型-同步化(Synchronization)</h1>
<hr>
<br>
<!--withdraw 取款-->
<!--deposit 存款-->
<form action="ws">
<label for="un">取款人:</label>
<input id="un" type="text" name="username" placeholder="在此输入取款人姓名">
<br><br>
<label for="acc">取自账户:</label>
<input id="acc" type="text" disabled value="621226 3803001183734">
<br><br>
<label for="accName">账户户名:</label>
<input id="accName" type="text" disabled value="李凡凡">
<br><br>
<input type="submit" value="取款100块">
</form>
</body>
</html>
style.css
h1{
color: darksalmon;
text-align: center;
}
label{
width: 90px;
display: inline-block;
}
input[type="text"]{
padding: 5px 10px;
border:solid 1px lightblue;
outline: none;
border-radius: 5px;
}
input[type="submit"]{
width: 290px;
height: 40px;
line-height: 40px;
background-color: darkcyan;
color: white;
text-align: center;
border:none;
border-radius: 5px;
}
input[type="submit"]:hover{
background-color: brown;
cursor: pointer;
}
Account
package com.qdu.entity;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* 银行账户类
*
* @author NIIT
*/
public class Account {
String name; //账户持有人姓名
int balance; //余额
public Account(String name, int balance) {
this.name = name;
this.balance = balance;
}
/**
* 传入取款人姓名,从一个账户取款100块
*
* @param who 取款人的姓名
*/
//withdraw 取款
//deposit 存款
//synchronized用于同步化一个方法,同步化的方法同一时刻只能由一个线程访问
public synchronized void withdraw100(String who) {
try {
System.out.println(who + "取款前余额:" + balance);
balance -= 100; //账户余额减少100
Thread.sleep(1000); //休眠1s
System.out.println(who + "取款后余额:" + balance);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
WithdrawServlet
package com.qdu.servlet;
import com.qdu.entity.Account;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/ws")
public class WithdrawServlet extends HttpServlet {
Account account = new Account("李凡凡", 2000);
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("username");
//取款100块
account.withdraw100(name);
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("<h1>" + name + "同志取款100成功!</h1>");
}
}
}
C02_D15_UseFilter1
index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>登录页面</title>
<link rel="stylesheet" href="css/login.css">
</head>
<body>
<br>
<br>
<div id="container">
<br>
<form method="post" action="ls.do">
<table>
<caption>用户登录</caption>
<tr>
<td>账户:</td>
<td><input name="username" type="text" value="李凡凡"></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="password" type="password" value="1234"></td>
</tr>
<tr class="foot">
<td colspan="2">
<input type="submit" value="登录">
<a href="register.html">注册</a>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
LoginServlet
package com.qdu.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/ls.do")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//可以修改请求的编码,但是一定要在获取请求参数前修改编码
//这样可以解决中文参数乱码问题,但是这里的方式只适用于post请求
//req.setCharacterEncoding("utf-8"); //该程序使用过滤器实现修改请求编码,所以这里不用了
String uname = req.getParameter("username");
String pwd = req.getParameter("password");
resp.setContentType("text/html;charset=utf-8");
try (PrintWriter out = resp.getWriter()) {
out.println("<h1>登录信息</h1>");
out.println("<hr>");
out.println("<br>账号:" + uname);
out.println("<br><br>密码:" + pwd);
}
}
}
register.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>注册页面</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/register.css">
</head>
<body>
<div class="container">
<h1 class="text-primary text-center">学生注册</h1>
<hr>
<form method="post" action="rs.do" class="form-inline">
<table>
<tr>
<td><label for="srollno">学号:</label></td>
<td><input name="srollno" class="form-control" type="text" id="srollno" value="2017209999"></td>
</tr>
<tr>
<td><label for="spwd">密码:</label></td>
<td><input name="spwd" class="form-control" type="password" id="spwd" value="666666"></td>
</tr>
<tr>
<td><label for="sname">姓名:</label></td>
<td><input name="sname" class="form-control" type="text" id="sname" value="李凡凡"></td>
</tr>
<tr>
<td><label for="sgender">性别:</label></td>
<td>
<select name="sgender" id="sgender" class="form-control">
<option value="男">男</option>
<option value="女">女</option>
</select>
</td>
</tr>
<tr>
<td><label for="sbatch">班级:</label></td>
<td>
<select name="sbatch" id="sbatch" class="form-control">
<option value="17软件(Java)03">17软件(Java)03</option>
<option value="17软件(Java)04">17软件(Java)04</option>
<option value="17软件(Java)06">17软件(Java)06</option>
</select>
</td>
</tr>
<tr class="foot">
<td colspan="2" class="text-center">
<input type="submit" value="注册" class="btn btn-sm btn-primary">
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
package com.qdu.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/rs.do")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String srollno = req.getParameter("srollno");
String spwd = req.getParameter("spwd");
String sname = req.getParameter("sname");
String sgender = req.getParameter("sgender");
String sbatch = req.getParameter("sbatch");
resp.setContentType("text/html;charset=utf-8");
try (PrintWriter out = resp.getWriter()) {
out.println("<h1>注册信息</h1>");
out.println("<hr>");
out.println("<br>学号:"+srollno);
out.println("<br><br>密码:"+spwd);
out.println("<br><br>姓名:"+sname);
out.println("<br><br>性别:"+sgender);
out.println("<br><br>班级:"+sbatch);
}
}
}
EncodingFilter
package com.qdu.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* 创建一个过滤器,用于拦截包含中文参数的post请求,修改请求编码,然后放行请求去访问实际资源
* <br>创建过滤器的步骤
* <br>1. 实现Filter接口,创建过滤器类
* <br>2. 在web.xml中或使用@WebFilter注解注册过滤器才能使用过滤器
*
* @author NIIT
*/
//过滤器在程序启动的时候就会实例化,可以看下init()方法中的代码在程序启动的时候就会输出
public class EncodingFilter implements Filter {
//init()方法在过滤器实例化后被调用,该方法被调用说明过滤器被实例化了
//如果在过滤器拦截请求之前需要做一些初始工作,在此方法中编写代码
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init被调用了!!!......;.");
}
//过滤器应该执行的逻辑代码在此方法编写,也就是过滤器需要实现的功能
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//该方法接收三个参数
//1. 表示拦截的请求对象
//2. 表示拦截的响应对象
//3. 一个FilterChain对象,表示过滤器链,可用于操作过滤器链上的过滤器
//可以在控制台观察下面这行代码的输出判断过滤器的doFitler()方法什么时候被调用
System.out.println("doFitler被调用...............");
request.setCharacterEncoding("utf-8"); //修改请求编码
//FilterChain接口的doFilter()方法的调用导致过滤器链上的下一个过滤器被调用
//如果没有下一个过滤器,则导致过滤器链上终端的实际资被调用,也就是请求到达实际资源
chain.doFilter(request, response); //放行请求去访问资源
}
//destroy()方法在一个过滤器实例被摧毁前调用,用于释放资源
@Override
public void destroy() {
System.out.println("destroy被调用!!!........");
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.xsd">
<!--filter标记用于指定一个过滤器的名称、描述和类名-->
<filter>
<description>拦截包含中文参数的post请求,修正请求编码</description>
<filter-name>encodingFilter</filter-name>
<filter-class>com.qdu.filter.EncodingFilter</filter-class>
</filter>
<!--如果想拦截某种类型的请求,可以考虑请求路径具有相同的后缀(如*.do)或前缀(如/post/*)-->
<!--filter-mapping标记指定一个过滤器的映射,也就是过滤器过滤什么样的请求,也就是拦截什么样的请求-->
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<!--<url-pattern>/ls</url-pattern>-->
<!--<url-pattern>/rs</url-pattern>-->
<url-pattern>*.do</url-pattern>
<!--<url-pattern>/post/*</url-pattern>-->
</filter-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
</web-app>
login.css
@charset "utf-8";
#container{
width: 280px;
margin: 50px auto 0 auto;
background-color:#CC0;
}
table{
width:100%;
border-spacing: 10px;
}
table caption{
background-color:#C60;
padding: 10px 0 10px 0;
font-size: 30px;
font-weight: bold;
color: white;
}
input[type="text"],input[type="password"],select{
padding:5px 10px;
border: none;
outline:none;
border-radius: 5px;
}
input[type="submit"],a{
width: 70px;
height: 30px;
line-height: 30px;
background-color: darkcyan;
color: white;
text-align: center;
border:none;
border-radius: 5px;
}
a{
display: inline-block;
text-decoration: none;
}
input[type="submit"]:hover{
background-color: brown;
cursor: pointer;
}
a{
background-color: darkorange;
}
a:hover{
text-decoration: underline;
background-color: brown;
}
table tr.foot{
text-align: center;
}
register.css
@charset "utf-8";
#container{
width: 320px;
margin: 50px auto 0 auto;
background-color:#CC0;
}
table{
border-spacing: 20px;
width:270px;
margin: 30px auto;
}
table td{
padding: 6px;
}
select{
width: 196px!important;
}
.gender{
margin-left: 5px;
margin-right: 10px;
}
.gender:hover{
cursor: pointer;
text-decoration: underline;
}
C02_D16_UseFilter2
login.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>登录页面</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<br>
<br>
<div id="container">
<br>
<form method="post" action="ls">
<table>
<caption>用户登录</caption>
<tr>
<td>账户:</td>
<td><input name="username" type="text" value="anna"></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="password" type="password" value="123"></td>
</tr>
<tr class="foot">
<td colspan="2">
<input type="submit" value="登录">
<a href="#">注册</a>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
这里的登录和注册虽然都是按钮,但一个是提交按钮,一个是超链接。
LoginServlet
package com.qdu.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/ls")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String uname=request.getParameter("username");
String pwd=request.getParameter("password");
if(uname.equals("anna")&&pwd.equals("123")){
//通过请求对象可以获取关联的会话
HttpSession session=request.getSession();
//添加一项信息到会话对象中,表示登录状态,如果会话中有isLogin这个属性,则说明用户登录了
session.setAttribute("isLogin","Y");
response.sendRedirect("loginSuccess.jsp");
}else{
response.sendRedirect("loginFail.html");
}
}
}
loginSuccess.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>登录成功</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="background-color: darkkhaki;">
<h1>欢迎登录,您可以去下载资源了</h1>
<hr>
<ul style="line-height: 30px;">
<li><a href="resources/download.jsp">下载园地</a></li>
<li><a href="resources/forum.jsp">学习论坛</a></li>
<li><a href="resources/video.jsp">学习视频</a></li>
<li><a href="contact.html">联系我们</a></li>
</ul>
<a href="los">退出登录</a>
</body>
</html>
LogoutServlet
package com.qdu.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/los")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
response.sendRedirect("login.html");
}
}
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1 style="color: red;">登录失败,请<a href="javascript:history.back();">返回</a>重新登录!</h1>
</body>
</html>
LoginFilter
package com.qdu.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* 创建一个过滤器,拦截访问resources目录下所有资源的请求
* <br>拦截请求后判断用户是否已经登录,如果登录,放行请求访问实际资源
* <br>否则不放行,将用户重定向到warning.html
*
* @author NIIT
*/
public class LoginFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init..................");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("doFilter...............");
//getSession()方法是HttpServletRequest接口的方法,ServletRequest接口没有该方法
//但是实际发送的请求是Http请求,所以实际发送的请求是HttpServletRequest类型
//需要手动转换类型到HttpServletRequest类型
HttpServletRequest req=(HttpServletRequest)request;
//sendRedirect()方法是HttpServletResponse接口的,所以响应对象也要转换类型
HttpServletResponse resp=(HttpServletResponse)response;
//如果还没有会话对象,说明没登录,我们也不希望在过滤器中创建对象
//所以调用getSession(false)表示有会话返回会话对象,没有返回null
HttpSession session=req.getSession(false);
//如果会话不为null,并且会话中有isLogin这个属性(该属性不为null说明有该属性)d
if(null!=session&&null!=session.getAttribute("isLogin")){
chain.doFilter(request, response); //放行请求去访问资源
}else{
//else说明没有登录,则不调用FilterChain的doFilter()方法
//但是这里不能使用相对路径,所以需要获取程序的上下文路径,再追加上warning.html,使用该页面的完整路径
//该程序的上下文路径是http://localhost:8084/C02_D16_UseFilter2
String ctxPath=req.getContextPath()+"/"; //获取程序的上下文路径
//ctxPath+"warning.html形成的路径是http://localhost:8084/C02_D16_UseFilter2/warning.html
resp.sendRedirect(ctxPath+"warning.html"); //这里使用warning.html的完整路径
}
}
@Override
public void destroy() {
}
}
style.css
@charset "utf-8";
#container{
width: 280px;
margin: 50px auto 0 auto;
background-color:#CC0;
}
table{
width:100%;
border-spacing: 10px;
}
table caption{
background-color:#C60;
padding: 10px 0 10px 0;
font-size: 30px;
font-weight: bold;
color: white;
}
input[type="text"],input[type="password"],select{
padding:5px 10px;
border: none;
outline:none;
border-radius: 5px;
}
input[type="submit"],a{
width: 70px;
height: 30px;
line-height: 30px;
background-color: darkcyan;
color: white;
text-align: center;
border:none;
border-radius: 5px;
}
a{
display: inline-block;
text-decoration: none;
}
input[type="submit"]:hover{
background-color: brown;
cursor: pointer;
}
a{
background-color: darkorange;
}
a:hover{
text-decoration: underline;
background-color: brown;
}
table tr.foot{
text-align: center;
}
web.html
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.xsd">
<filter>
<description>拦截所有对resources目录下资源的访问请求,根据登录判断决定是否可以访问资源</description>
<filter-name>loginFilter</filter-name>
<filter-class>com.qdu.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/resources/*</url-pattern>
<!--
/rs 拦截对rs这个servlet的访问请求
/second.jsp 拦截对单个页面second.jsp的请求
*.do 拦截所有以.do结尾的请求,比较常见的后缀是*.do或*.action等
*.post 拦截所有以.post结尾的请求
/post/* 拦截所有以post前缀的请求
/resources/* 拦截所有以resources为前缀的请求
/resources/*.jsp 不合法-->
</filter-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
</web-app>
C02_D17_UseFilter3
LoginFilter
package com.tianmao.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* 创建一个过滤器,拦截访问resources目录下所有资源的请求
* <br>拦截请求后判断用户是否已经登录,如果登录,放行请求访问实际资源
* <br>否则不放行,将用户重定向到warning.html
*
* @author NIIT
*/
public class LoginFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init..................");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("doFilter...............");
//getSession()方法是HttpServletRequest接口的方法,ServletRequest接口没有该方法
//但是实际发送的请求是Http请求,所以实际发送的请求是HttpServletRequest类型
//需要手动转换类型到HttpServletRequest类型
HttpServletRequest req=(HttpServletRequest)request;
//sendRedirect()方法是HttpServletResponse接口的,所以响应对象也要转换类型
HttpServletResponse resp=(HttpServletResponse)response;
//如果还没有会话对象,说明没登录,我们也不希望在过滤器中创建对象
//所以调用getSession(false)表示有会话返回会话对象,没有返回null
HttpSession session=req.getSession(false);
//如果会话不为null,并且会话中有isLogin这个属性(该属性不为null说明有该属性)d
if(null!=session&&null!=session.getAttribute("isLogin")){
chain.doFilter(request, response); //放行请求去访问资源
}else{
//else说明没有登录,则不调用FilterChain的doFilter()方法
//但是这里不能使用相对路径,所以需要获取程序的上下文路径,再追加上warning.html,使用该页面的完整路径
//该程序的上下文路径是http://localhost:8084/C02_D16_UseFilter2
String ctxPath=req.getContextPath()+"/"; //获取程序的上下文路径
//ctxPath+"warning.html形成的路径是http://localhost:8084/C02_D16_UseFilter2/warning.html
resp.sendRedirect(ctxPath+"warning.html"); //这里使用warning.html的完整路径
}
}
@Override
public void destroy() {
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 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_3_1.xsd">
<filter>
<description>拦截包含中文参数的post请求,判断是否登录</description>
<filter-name>LoginFilter</filter-name>
<filter-class>com.tianmao.filter.LoginFilter</filter-class>
</filter>
<!--如果想拦截某种类型的请求,可以考虑请求路径具有相同的后缀(如*.do)或前缀(如/post/*)-->
<!--filter-mapping标记指定一个过滤器的映射,也就是过滤器过滤什么样的请求,也就是拦截什么样的请求-->
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<!--<url-pattern>/ls</url-pattern>-->
<!--<url-pattern>/rs</url-pattern>-->
<url-pattern>/cs</url-pattern>
<!--<url-pattern>/post/*</url-pattern>-->
</filter-mapping>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<!--<url-pattern>/ls</url-pattern>-->
<!--<url-pattern>/rs</url-pattern>-->
<url-pattern>/los</url-pattern>
<!--<url-pattern>/post/*</url-pattern>-->
</filter-mapping>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<!--<url-pattern>/ls</url-pattern>-->
<!--<url-pattern>/rs</url-pattern>-->
<url-pattern>/ps</url-pattern>
<!--<url-pattern>/post/*</url-pattern>-->
</filter-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>