周总结
01_会话技术
- 概念
- 打开浏览器,访问服务器中资源,关闭浏览器;这个过程就是会话。
- 会话分类
- Cookie会话技术;浏览器会话技术
- Session会话技术;服务器会话技术
- 作用
- 解决ServletContext域对象、Request域对象存储数据所存在的问题
- ServletContext域对象、Request域对象存在的问题
- ServletContext域对象可以看到所有人的购物车
- Request域对象,发起结算时购物车是空的
02_Cookie的介绍
- 概念
- 网景公司发明。是浏览器的会话技术
- Cookie的流程
- 浏览器请求服务器,请求Demo01Servlet,创建一个Cookie对象,名称为cookie1
- 可以通过响应头Set-Cookie,携带cookie给浏览器进行保存
- 浏览器再次请求服务器,请求Demo02Servlet,获取cookie1对象
03_Cookie的基本使用
- 设置Cookie
- 方式一(不推荐)
response.addHeader(“set-cookie”,“msg=hellocoolie”);
- 方式一(不推荐)
- 方式二(推荐)
Cookie cookie = new Cookie(“msg”,“hellocookie”);
response.addCookie(cookie); - 获取Cookie
- 开发步骤
- 通过request对象获取所有的Cookie对象,存储到一个数组中
- 遍历该数组,匹配Cookie名称
- 如果匹配上,就知道了指定的Cookie对象
- 如果匹配不上,就没有指定的Cookie对象
- 代码实现
- 开发步骤
Cookie[] cookies = request.getCookies();
Cookie cookie = null;
for(Cookie sonCookie : cookies){
if("msg".equals(sonCookie.getName())){
cookie = sonCookie;
}
}
if(null != cookie){
System.out.println("name : "+msgCookie.getName() + " , value : "+ msgCookie.getValue());
}
04_Cookie的相关设置
- 持久化设置
- cookie的生命周期
- 默认是随着浏览器的关闭而销毁
- setMaxAge
- 设置cookie的存活时长,cookie就可以不随着会话的关闭而销毁!
- cookie的生命周期
- 路径设置
- 默认情况下,Cookie对象会随着任何一个请求携带到服务器
- setPath
- 设置Cookie的访问路径
Cookie cookie = new Cookie(“msg”,“helloworld”);
cookie.setPath("/day56/demo04");
response.addCookie(cookie); - cookie对象只有访问路径包含"/day56/demo04",才会跟随请求携带到服务器
- 设置Cookie的访问路径
05_Cookie案例之记录上一次访问时间
- 需求:
- 第一次访问,就直接打印当前时间
- 不是第一次访问,就打印上一次的访问时间
- 开发步骤
- 获取对应的Cookie对象
- 判断是否是第一次访问
- 如果是第一次访问
- 打印当前时间
- 将当前时间存储到Cookie中
- 如果不是第一次访问
- 打印上一次访问时间
- 将当前时间存储到Cookie中
- 代码实现
//判断是否是一次请求
Cookie[] cookies = request.getCookies();
Cookie cookie = null;//记录上一次的访问时间
if (cookies != null && cookies.length != 0 ) {
for (Cookie sonCookie : cookies) {
if ("lastTime".equals(sonCookie.getName())) {
cookie = sonCookie;
}
}
}
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
if (null == cookie) {
//第一次访问 ,打印当前时间,并将创建Cookie对象,存储当前时间
Date currentDate = new Date();
System.out.println("第一次访问,时间为" + format.format(currentDate));
cookie = new Cookie("lastTime",currentDate.getTime()+"");
} else {
//不是第一次访问,从cookie取出上一次的访问时间,并打印。获取当前时间,并存储cookie对象中
long lastDateMills = Long.parseLong(cookie.getValue());
Date lastDate = new Date(lastDateMills);
//获取到了上一次的访问时间
String lastTimeStr = format.format(lastDate);
System.out.println("上一次访问,时间为" + lastTimeStr);
//获取当前时间,并存储cookie对象中
Date currentDate = new Date();
// cookie.setValue(currentDate.getTime()+"");
cookie = new Cookie("lastTime",currentDate.getTime()+"");
}
response.addCookie(cookie);
06_Cookie案例之商品浏览记录
- 需求
- 浏览商品,将商品的浏览的记录起来,并显示!
- 开发步骤
- 获取history的Cookie对象
- 判断商品浏览记录是否为空
- 如果浏览记录没有
- 创建Cookie,并将当前的商品记录到Cookie中
- 如果浏览记录有
- 有当前的商品,不做任何处理
- 没有当前商品,就需要将当前的商品拼接到已有记录中
- 代码实现
- 页面代码
<a href="/day56/history?id=0">西游记</a><br>
<a href="/day56/history?id=1">红楼梦</a><br>
<a href="/day56/history?id=2">水浒传</a><br>
<a href="/day56/history?id=3">三国志</a><br>
- 商品浏览记录
String id = request.getParameter("id");
Cookie cookie = null;
Cookie[] cookies = request.getCookies();
if (null != cookies && 0 != cookies.length){
for (Cookie sonCookie : cookies) {
if ("history".equals(sonCookie.getName())) {
cookie = sonCookie;
}
}
}
if (null == cookie) {
//之前没有任何浏览记录 ,创建Cookie对象 ,并存储浏览记录(id)
cookie = new Cookie("history",id);
} else {
//之前有一些浏览记录
String historyStr = cookie.getValue();
if (!historyStr.contains(id)) {
//有一些记录,但是不包含当前浏览的商品;
//将浏览商品拼接到已有浏览记录中
//120
//1-2-0
historyStr += "-"+id;
cookie.setValue(historyStr);
} else {
//有一些记录,包含当前浏览的商品 ,不做任何处理
}
}
response.addCookie(cookie);
//上述代码,已经完成了商品浏览记录功能,剩下就是要显示商品浏览记录
response.sendRedirect(request.getContextPath()+ File.separator+"showHistory");
07_CookieUtils工具类
- 获取指定名称的Cookie对象
public static Cookie getCookie(Cookie[] cookies ,String cookieName){
if (null != cookies && 0 != cookies.length) {
for (Cookie sonCookie : cookies) {
if (cookieName.equals(sonCookie.getName())) {
return sonCookie;
}
}
}
return null;
}
08_Session基本使用
- Cookie之所以叫做浏览器会话,原因是Cookie的数据存储到浏览器!
- Session之所以叫做服务器会话,原因是Session的数据存储到服务器!
- 执行流程
- 第一次请求Demo01Servlet时,根据request.getSession方法, 新建一个session对象;
- 当第一次响应时,会将该session对象的id作为cookie头响应给浏览器保存
set-cookie:JSESSIONID=4741C65CC84788A204E87EB870196EB0 - 第二次请求Demo01Servlet时,根据request.getSession方法,请求中会有cookie头
Cookie:JSESSIONID=4741C65CC84788A204E87EB870196EB0 - 会根据该JSESSIONID去服务器中找有没有对应的session对象,如果有就直接用,没有就新建!!!
09_Session相关配置
- 生命周期
- session默认是有30分钟的存活时间,参考tomcat中的web.xml
<session-config>
<session-timeout>30</session-timeout>
</session-config>
- session和cookie是相关联的,cookie中存储了jsessionid,request.getSession方法会根据jsessionid去选择,到底是新建session对象,还是引用原来的session对象;如果,将浏览器关闭了,就意味着cookie中存储的jsessionid就会销毁,对应request.getSession就会新建一个session对象,但是原来的session对象还存在!
- session.invalidate方法,立马将对应的session对象销毁!后续就会新建session!
- 注意事项
- 关闭浏览器,session会怎么样?
- 销毁session,下一次的geSession怎么样?
- 总结
- session只有两种情况会销毁
- 调用了invalidate方法
- 过了30分钟
- session只有两种情况会销毁
01_session的基本使用
- setAttribute
- 往session域对象中存储数据
- getAttribute
- 从session域对象中获取数据
- removeAttribute
- 把session域对象中的数据移除
02_session案例之登录
- 登录功能
- UserDao
public class UserDaoImpl implements UserDao {
@Override
public User login(User inputUser) throws SQLException {
// ComboPooledDataSource就是连接池,连接池包含很多连接对象
// 连接池作用就是减少连接的创建次数!
// 第一个用户,登录,创建一个连接池,创建3个连接
// 第二个用户,登录,创建一个连接池,创建3个连接
// 应该只让连接池创建一次!!后面复用就OK了!!
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
User existUser = queryRunner.query(
"select * from tb_user where username = ? and password = ?",
new BeanHandler<User>(User.class),
inputUser.getUsername(),
inputUser.getPassword());
return existUser;
}
}
- LoginServlet
@WebServlet(name = "LoginServlet",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
private UserDao userDao = new UserDaoImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User inputUser = new User();
inputUser.setUsername(username);
inputUser.setPassword(password);
try {
User existUser = userDao.login(inputUser);
System.out.println(existUser);
//判断登录成功
if (null == existUser) {
//登录失败,请求转发,跳转到登录页面
request.getRequestDispatcher("/login.html").forward(request,response);
} else {
//登录成功,重定向,跳转到显示用户信息
//存储existUser
//request : 跳转到首页,使用了重定向,会有一个新的请求
//servletContext : 如果存储到ServletContext,就意味着所有人都可以拿到你的用户信息!
//cookie : 如果存储到cookie中,就是存储到浏览器 , 不安全! cookie中是无法存储中文及一些特殊符号!!
//session : 数据存储到服务器!!
request.getSession().setAttribute("existUser",existUser);
response.sendRedirect("/day57/showIndex");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
- 显示用户信息
- ShowIndexServlet
@WebServlet(name = "ShowIndexServlet" ,urlPatterns = "/showIndex")
public class ShowIndexServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
User existUser = (User) request.getSession().getAttribute("existUser");
if (null != existUser) {
//在登录状态
response.getWriter().write("欢迎回来,"+existUser.getUsername());
} else {
//不在登录状态
//方式一:提示下,未登录
// response.getWriter().write("您还没有登录,<a href='/day57/login.html'>请登录</a>");
//方式二:跳转到登录页面
response.sendRedirect("/day57/login.html");
//看需求,选择方式一还是方式二
//登录状态权限管理!!
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- 注意事项
- 第三方jar包,必须放到WEB-INF文件夹中
- 登录失败使用请求转发、登录成功使用重定向!
03_session案例之随机验证码
- 显示验证码
- 创建图片对象
- 画背景
- 画边框
- 画干扰线
- 产生四位随机数,存储到session
- 画四位随机数
- 将图片响应到浏览器
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 60;//定义图片宽度
int height = 32;//定义图片高度
//创建图片对象
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//创建画笔对象
Graphics g = image.getGraphics();
//设置背景颜色
g.setColor(new Color(0xDCDCDC));
g.fillRect(0, 0, width, height);//实心矩形
//设置边框
g.setColor(Color.black);
g.drawRect(0, 0, width - 1, height - 1);//空心矩形
Random rdm = new Random();
//画干扰椭圆
for (int i = 0; i < 50; i++) {
int x = rdm.nextInt(width);
int y = rdm.nextInt(height);
g.drawOval(x, y, 0, 0);
}
//产生随机字符串
String hash1 = Integer.toHexString(rdm.nextInt());
//生成四位随机验证码
String capstr = hash1.substring(0, 4);
//将产生的验证码存储到session域中,方便以后进行验证码校验!
request.getSession().setAttribute("existCode", capstr);
System.out.println(capstr);
g.setColor(new Color(0, 100, 0));
g.setFont(new Font("Candara", Font.BOLD, 24));
g.drawString(capstr, 8, 24);
g.dispose();
//将图片响应到浏览器
response.setContentType("image/jpeg");
OutputStream strm = response.getOutputStream();
ImageIO.write(image, "jpeg", strm);
strm.close();
}
//获取输入的验证码
String validateCode = request.getParameter("validateCode");
//将输入的验证码和产生的随机验证码进行校验
String existCode = (String) request.getSession().getAttribute("existCode");
if (validateCode.equals(existCode)) {
//校验通过,完成登录功能
} else {
//校验不通过,跳转到登录页面
}
04_自定义DbUtils之增删改
- 相同点
- 1,获取连接
- 4,执行sql语句
- 5,释放资源
- 不同点
- 2,sql语句
- 3,设置参数
- 代码实现
public static void update(String sql , Object... parameters){
Connection connection = null;
PreparedStatement statement = null;
try {
connection = JDBCUtils.getConnection();
statement = connection.prepareStatement(sql);
//设置参数值的时候,参照的是parameters的个数! 应该参照有多少个问号?
ParameterMetaData parameterMetaData = statement.getParameterMetaData();
for (int i = 0; i < parameterMetaData.getParameterCount(); i++) {
statement.setObject(i + 1,parameters[i]);
}
statement.executeUpdate();
} catch (Exception throwables) {
throwables.printStackTrace();
} finally {
JDBCUtils.release(connection, statement);
}
}
05_自定义DbUtils之查询
- 相同点
- 1,获取连接
- 5,释放资源
- 不同点
- 2,sql语句
- 3,设置参数
- 4,处理结果集
- 代码实现
- MyResultSetHandler接口
- 处理结果集,并得到想要的类型的数据
- MyResultSetHandler接口
public interface MyResultSetHandler<T> {
/**
* 处理结果集,并返回想要的类型的数据
* @param resultSet 结果集
* @return 要的类型的数据
* @throws Exception
*/
T handle(ResultSet resultSet) throws Exception;
}
- 通用query方法
public static<T> T query(String sql ,MyResultSetHandler<T> handler,Object... parameters ){
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = JDBCUtils.getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0; i < statement.getParameterMetaData().getParameterCount(); i++) {
statement.setObject(i+1 , parameters[i]);
}
resultSet = statement.executeQuery();
//处理结果集 , 返回结果
T t = handler.handle(resultSet);
return t;
} catch (Exception throwables) {
throwables.printStackTrace();
} finally {
JDBCUtils.release(connection,statement,resultSet);
}
return null;
}
- 测试代码
User existUser = MyDbUtils.query("select * from tb_user where id = ?",
new MyResultSetHandler<User>() {
@Override
public User handle(ResultSet resultSet) throws Exception {
User user = null;
while (resultSet.next()) {
Integer id = resultSet.getInt("id");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
user = new User(id, username, password);
}
return user;
}
}, 2);
System.out.println(existUser);
- 存在的问题
- 结果集的处理太麻烦,具体体现在处理结果集的具体实现上!!
- 解决思路
- 如果结果集处理之后返回的是单条记录,封装好一个MyBeanHandler
- 如果结果集处理之后返回的是多条记录,封装好一个MyBeanListHandler
01_自定义DbUtils之MyBeanHandler
- 概念
- 封装单条记录的结果集处理
- 开发步骤
- MyResultSetHandler接口上的泛型由MyBeanHandler的泛型确定
- 声明一个Class对象的引用
- 重写handle方法
- 代码实现
public class MyBeanHandler<T> implements MyResultSetHandler<T> {
private Class<T> clazz;//User类Class对象,也可以是Student类Class对象
public MyBeanHandler(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public T handle(ResultSet resultSet) throws Exception {
T t = clazz.newInstance();
//处理结果集
while (resultSet.next()){
//id属性值,username属性值,password属性值
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
//字段名称
String fieldName = field.getName();
//字段值
Object fieldValue = resultSet.getObject(fieldName);
//将字段值设置Class对象对应的java实体对象
//获取字段对应set方法
String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
Method method = clazz.getMethod(methodName, field.getType());
if (null != method) {
method.invoke(t,fieldValue);
}
}
}
return t;
}
}
02_自定义DbUtils之MyBeanListHandler
- 概念
- 封装多条记录的结果集处理
- 开发步骤
- MyResultSetHandler接口上的泛型由MyBeanListHandler的泛型确定
- 已经确定了返回的是集合,只是不确定集合中的元素的类型
- MyBeanListHandler只确定集合中元素的类型就可以了
- 声明一个Class对象的引用
- 重写handle方法
- MyResultSetHandler接口上的泛型由MyBeanListHandler的泛型确定
- 代码实现
public class MyBeanListHandler<T> implements MyResultSetHandler<List<T>> {
private Class<? extends T> clazz;//集合中元素的Class对象
public MyBeanListHandler(Class<? extends T> clazz) {
this.clazz = clazz;
}
@Override
public List<T> handle(ResultSet resultSet) throws Exception {
List<T> list = new ArrayList<>();
while (resultSet.next()) {
//循环一次,就是一条记录,就是一个对象
T t = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
Object fieldValue = resultSet.getObject(fieldName);
//获取set方法
String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
Method method = clazz.getMethod(methodName, field.getType());
if (null != method) {
method.invoke(t,fieldValue);
}
}
list.add(t);
}
return list;
}
}
03_过滤器的概念
- 概念
- 过滤器就是一个用于在请求之前处理资源的组件
- 生命周期
- 随着服务器启动而初始化
- 随着请求的发出而过滤
- 随着服务器关闭而销毁
- 执行流程
- 浏览器发起请求
- 服务器会根据这个请求,创建request对象及response对象
- 过滤器会持有request对象及response对象
- 只有当过滤器放行之后,request对象及response对象才会传给Serlvet
- 过滤器链
- 根据配置顺序,遵从"先过滤,后放行"的原则!
04_过滤器的基本使用
- 开发步骤
- 自定义类实现Filter接口
- 重写init、doFilter、destroy方法
- 在web.xml中配置过滤器
- 声明过滤器
- 过滤器配置过滤路径
- 代码实现
- 过滤器
public class Demo01Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//Demo01Filter过滤器的初始化
System.out.println("Demo01Filter初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//Demo01Filter过滤器处理请求
System.out.println("Demo01Filter放行之前");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Demo01Filter放行之后");
}
@Override
public void destroy() {
//Demo01Filter过滤器的销毁
System.out.println("Demo01Filter销毁");
}
}
web.xml
<!--声明Demo01Filter过滤器-->
<filter>
<filter-name>Demo01Filter</filter-name>
<filter-class>com.qfedu.filter.Demo01Filter</filter-class>
</filter>
<!--配置Demo01Filter的过滤路径-->
<filter-mapping>
<filter-name>Demo01Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
05_过滤器的相关配置
- 初始化参数
- Filter配置初始化参数
<filter>
<filter-name>Demo03Filter</filter-name>
<filter-class>com.qfedu.filter.Demo03Filter</filter-class>
<!--初始化参数-->
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>root123</param-value>
</init-param>
</filter>
Filter获取初始化参数
public class Demo03Filter implements Filter {
public void init(FilterConfig config) throws ServletException {
Enumeration<String> parameterNames = config.getInitParameterNames();
while (parameterNames.hasMoreElements()) {
//获取初始化参数名称
String parameterName = parameterNames.nextElement();
//获取初始化参数值
String parameterValue = config.getInitParameter(parameterName);
System.out.println("name : " + parameterName + " , value : " + parameterValue);
}
}
......
}
Filter的过滤路径
- 针对 ,以为Filter仅针对Demo01Servlet进行过滤
<filter-mapping>
<filter-name>Demo03Filter</filter-name>
<servlet-name>Demo01Servlet</servlet-name>
</filter-mapping>
针对
- 完全匹配:必须以"/"开头
<filter-mapping>
<filter-name>Demo03Filter</filter-name>
<url-pattern>/aa</url-pattern>
</filter-mapping>
-
- 过滤器只过滤访问路径目录匹配到“/aa/bb“的资源
- 后缀名匹配:必须以"*"开头,以后缀名结尾
<filter-mapping>
<filter-name>Demo03Filter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
01_过滤器应用之敏感词屏蔽
- 代码实现
@WebFilter(
filterName = "SensitiveWordsFilter" ,
urlPatterns = "/*",
initParams = {
@WebInitParam(name = "word1",value = "笨蛋"),
@WebInitParam(name = "word2" ,value = "老邱"),
@WebInitParam(name = "word3" ,value = "中邱"),
@WebInitParam(name = "word4",value = "小邱")
})
public class SensitiveWordsFilter implements Filter {
//敏感词
List<String> sensitiveWords = new ArrayList<>();
public void init(FilterConfig config) throws ServletException {
Enumeration<String> parameterNames = config.getInitParameterNames();
while (parameterNames.hasMoreElements()) {
String sensitiveWord = config.getInitParameter(parameterNames.nextElement());
sensitiveWords.add(sensitiveWord);
}
}
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("SensitiveWordsFilter doFilter");
HttpServletRequest request = (HttpServletRequest) req;
//增强request下的getParameter方法
HttpServletRequest requestPrxoy = (HttpServletRequest) Proxy.newProxyInstance(
request.getClass().getClassLoader(),
request.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强getParameter方法
Object returnValue = null;
String methodName = method.getName();
if ("getParameter".equals(methodName)) {
//returnValue就是getParameter方法的返回值,可能会存在敏感词
String returnValue1 = (String)method.invoke(request, args);
//开始处理敏感词
for (String sensitiveWord : sensitiveWords) {
if (returnValue1.contains(sensitiveWord)) {
//getParameter方法的返回值包含敏感词
returnValue1 = returnValue1.replace(sensitiveWord,"***");
}
}
return returnValue1;
} else {
returnValue = method.invoke(request, args);
}
return returnValue;
}
});
chain.doFilter(requestPrxoy, resp);
}
}
02_监听器的介绍
- 监听器概念
- 事件源:事件发生的源头
- 监听器:监听事件发生
- 绑定:将监听器绑定到事件源
- 事件:能够触发监听器的事
- Servlet监听器
- 事件源:request域对象、session域对象、ServletContext域对象
- 监听器:Servlet三种监听器
- 绑定:配置web.xml
- 事件:域对象发生改变
03_监听器的分类
- 一类监听器
- 监听域对象的创建、销毁
- 二类监听器
- 监听域对象中的属性变更(属性设置、属性替换、属性移除)
- 三类监听器
- 监听域对象的java对象的绑定
04_一类监听器的基本使用
- 一类监听器
- ServletRequestListener : 监听ServletRequest域对象的创建、销毁
- HttpSessionListener :监听HttpSession域对象的创建、销毁
- ServletContextListener : 监听ServletContext域对象的创建、销毁
- 开发步骤
- 自定义类实现一类监听器
- 重写监听器中的方法
- 配置web.xml
- 代码实现
- 监听器
public class MyListener01 implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//监听ServletContext域的初始化,随着服务器的启动
System.out.println("ServletContext初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//监听ServletContext域的销毁,随着服务器的关闭
System.out.println("ServletContext销毁");
}
}
web.xml(绑定)
<listener>
<listener-class>com.qfedu.listener.MyListener01</listener-class>
</listener>
-
- 事件源: ServletContext域对象
- 监听器:ServletContextListener
- 绑定: web.xml配置
- 事件 : ServletContext域对象发生了创建、发生了销毁
05_二类监听器的基本使用
- 分类
- ServletRequestAttributeListener
- 监听ServletRequest域对象中属性变更
- HttpSessionAttributeListener
- 监听HttpSession域对象中属性变更
- ServletContextAttributeListener
- 监听ServletContext域对象中属性变更
- ServletRequestAttributeListener
- 代码实现
- 监听器
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
//监听ServletContext域对象中属性添加
System.out.println("ServletContext added");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
//监听ServletContext域对象中属性值被替换
System.out.println("ServletContext replaced");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
//监听ServletContext域对象中属性值移除
System.out.println("ServletContext removed");
}
}
web.xml(绑定)
<listener>
<listener-class>com.qfedu.listener.MyServletContextAttributeListener</listener-class>
</listener>
03_三类监听器
- HttpSessionBindingListener
- 监听session域中的java对象的状态(绑定和解绑)
- 绑定:将java对象存储到session域对象
- 解绑:将java对象从session域对象移除
- 监听session域中的java对象的状态(绑定和解绑)
- 监听器组成
- 事件源:java对象
- 监听器:HttpSessionBindingListener
- 绑定:java对象实现HttpSessionBindingListener接口
- 事件:java对象在session中状态发生改变
- 代码实现
public class User implements HttpSessionBindingListener {
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("User绑定");
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("User解绑");
}
......
}
-
注意事项
- HttpSessionBindingListener监听不需要在web.xml配置
01_监听器的注解开发
- HttpSessionBindingListener监听不需要在web.xml配置
-
@WebListener
- 相当于在web.xml绑定了监听器
-
代码实现
@WebListener
public class MyServletContextLIstener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext创建");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext销毁");
}
}
02_javaWeb综合案例之用户列表
- 开发步骤
- 获取用户列表放到首页完成
- 登录状态才需要获取用户列表
- 获取用户列表放到首页完成
- 代码实现
- UserDao
@Override
public List<User> selectUserList() throws Exception {
return new QueryRunner(JDBCUtil.getDataSource())
.query("select * from tb_user",
new BeanListHandler<User>(User.class));
}
ShowIndexSerlvet
@WebServlet(name = "ShowIndexServlet" ,urlPatterns = "/showIndex")
public class ShowIndexServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User existUser = (User) request.getSession().getAttribute("existUser");
StringBuffer responseBody = new StringBuffer();
if (null != existUser) {
//已经在登录状态
responseBody.append("欢迎回来~ " + existUser.getUsername());
responseBody.append(" <a href='/day60/logout'>注销</a><br>");
//获取用户列表
UserDao userDao = new UserDaoImpl();
try {
List<User> userList = userDao.selectUserList();
System.out.println(userList);
responseBody.append("<table border='1px' cellspaceing='0px' cellpadding='10px' width='500px' height='200px'>");
responseBody.append("<tr>");
responseBody.append("<td>ID</td>");
responseBody.append("<td>账户</td>");
responseBody.append("<td>密码</td>");
responseBody.append("</tr>");
for (User user : userList) {
//遍历一个User对象,对应就应该有一个tr
responseBody.append("<tr>");
responseBody.append("<td>"+user.getId()+"</td>");
responseBody.append("<td>"+user.getUsername()+"</td>");
responseBody.append("<td>"+user.getPassword()+"</td>");
responseBody.append("</tr>");
}
responseBody.append("</table>");
} catch (Exception e) {
e.printStackTrace();
}
} else {
//不在登录状态
responseBody.append("您还没有登录,<a href='/day60/login.html'>请登录</a><br>");
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(responseBody.toString());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
03_javaWeb综合案例之删除用户
- 开发步骤
- 首页,给每一个记录后面添加一个删除按钮
- 用户列表不要显示当前登录用户
- 代码实现
- UserDao
@Override
public void deleteUserById(Integer id) throws Exception {
new QueryRunner(JDBCUtil.getDataSource())
.update("delete from tb_user where id = ?",
id);
}
ShowIndexServlet
responseBody.append("<table border='1px' cellspaceing='0px' cellpadding='10px' width='500px' height='200px'>");
responseBody.append("<tr>");
responseBody.append("<td>ID</td>");
responseBody.append("<td>账户</td>");
responseBody.append("<td>密码</td>");
responseBody.append("<td>操作</td>");
responseBody.append("</tr>");
for (User user : userList) {
if ( user.getId() != existUser.getId()) {
//遍历一个User对象,对应就应该有一个tr
responseBody.append("<tr>");
responseBody.append("<td>"+user.getId()+"</td>");
responseBody.append("<td>"+user.getUsername()+"</td>");
responseBody.append("<td>"+user.getPassword()+"</td>");
responseBody.append("<td><a href='/day60/deleteUser?id="+user.getId()+"'>删除</a></td>");
responseBody.append("</tr>");
}
}
responseBody.append("</table>");
DeleteUserServlet
@WebServlet(name = "DeleteUserServlet" ,urlPatterns = "/deleteUser")
public class DeleteUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String idStr = request.getParameter("id");
Integer id = Integer.parseInt(idStr);
UserDao userDao = new UserDaoImpl();
try {
userDao.deleteUserById(id);
} catch (Exception e) {
e.printStackTrace();
}
response.sendRedirect("/day60/showIndex");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
04_javaWeb综合案例之批量删除
- 开发流程
- 在首页需要给每一个记录新加多选框
- 当点击批量删除按钮之后,完成批量删除操作
- 代码实现
- UserDao
public void deleteUsersByIds(List<Integer> idList) throws Exception {
for (Integer id : idList) {
deleteUserById(id);
}
}
ShowIndexServlet
responseBody.append("<form action='/day60/deleteUsers' method='post'>");
responseBody.append("<table border='1px' cellspaceing='0px' cellpadding='10px' width='500px' height='200px'>");
responseBody.append("<tr>");
responseBody.append("<td></td>");
responseBody.append("<td>ID</td>");
responseBody.append("<td>账户</td>");
responseBody.append("<td>密码</td>");
responseBody.append("<td>操作</td>");
responseBody.append("</tr>");
for (User user : userList) {
if ( user.getId() != existUser.getId()) {
//遍历一个User对象,对应就应该有一个tr
responseBody.append("<tr>");
responseBody.append("<td><input name='ids' type='checkbox' value='"+user.getId()+"'></td>");
......
responseBody.append("</tr>");
}
}
responseBody.append("</table>");
responseBody.append("<button type='submit'>批量删除</button>");
responseBody.append("</form>");
05_javaWeb综合案例之添加用户
- 开发步骤
- 首页加入一个添加用户按钮
- 点击添加用户按钮进入到登录页面
- 代码实现
- UserDao
public void addUser(User inputUser) throws Exception {
new QueryRunner(JDBCUtil.getDataSource())
.update("insert into tb_user(username ,password) values(?,?)",
inputUser.getUsername(),
inputUser.getPassword());
}
ShowIndexServlet
//已经在登录状态
responseBody.append("欢迎回来~ " + existUser.getUsername());
responseBody.append(" <a href='/day60/logout'>注销</a><br>");
responseBody.append("<a href='/day60/add.html'>添加用户</a><br>");
AddUserServlet
@WebServlet(name = "AddUserServlet" ,urlPatterns = "/addUser")
public class AddUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User inputUser = new User();
inputUser.setUsername(username);
inputUser.setPassword(password);
//方式一:在添加之前,校验下用户名是否存在
//方式二:让username字段有唯一约束!
UserDao userDao = new UserDaoImpl();
try {
userDao.addUser(inputUser);
//添加成功,跳转到首页
response.sendRedirect("/day60/showIndex");
} catch (Exception e) {
e.printStackTrace();
//添加失败,跳转到添加用户页面
response.sendRedirect("/day60/add.html");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
06_javaWeb综合案例之修改用户
- 开发步骤
- 首页加入修改按钮
- 代码实现
- UserDao
@Override
public void updateUser(User user) throws Exception {
new QueryRunner(JDBCUtil.getDataSource())
.update("update tb_user set username = ? , password = ? where id = ?",
user.getUsername(),
user.getPassword(),
user.getId());
}
ShowIndexServlet
for (User user : userList) {
if ( user.getId() != existUser.getId()) {
//遍历一个User对象,对应就应该有一个tr
responseBody.append("<tr>");
responseBody.append("<td><input name='ids' type='checkbox' value='"+user.getId()+"'></td>");
responseBody.append("<td>"+user.getId()+"</td>");
responseBody.append("<td>"+user.getUsername()+"</td>");
responseBody.append("<td>"+user.getPassword()+"</td>");
responseBody.append("<td>" +
"<a href='/day60/deleteUser?id="+user.getId()+"'>删除</a> " +
"<a href='/day60/showUpdateUser?id="+user.getId()+"'>修改</a>"+
"</td>");
responseBody.append("</tr>");
}
}
显示修改用户页面
@WebServlet(name = "ShowUpdateUserServlet" , urlPatterns = "/showUpdateUser")
public class ShowUpdateUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer id = Integer.parseInt(request.getParameter("id"));
//根据id查询用户
UserDao userDao = new UserDaoImpl();
StringBuffer responseBody = new StringBuffer();
try {
User user = userDao.selectUserById(id);
System.out.println(user);
responseBody.append("<form action='/day60/updateUser' method='post'>");
responseBody.append("<input type='hidden' name='id' value='"+user.getId()+"'/>");
responseBody.append("账户:<input type='text' name='username' value='"+user.getUsername()+"'/><br>");
responseBody.append("密码:<input type='text' name='password' value='"+user.getPassword()+"'/><br>");
responseBody.append("<button type='submit'>修改</button>");
responseBody.append("</form>");
} catch (Exception e) {
e.printStackTrace();
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(responseBody.toString());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
修改用户
@WebServlet(name = "UpdateUserServlet" ,urlPatterns = "/updateUser")
public class UpdateUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer id = Integer.parseInt(request.getParameter("id"));
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username : " + username + ", password : " + password);
//要修改的内容:username、password
User user = new User(id,username,password);
UserDao userDao = new UserDaoImpl();
try {
userDao.updateUser(user);
//修改成功,跳转到首页
response.sendRedirect("/day60/showIndex");
} catch (Exception e) {
e.printStackTrace();
//修改失败,跳转到修改页面
response.sendRedirect("/day60/showUpdateUser?id="+id);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
上一篇: $_REQUEST、$_GET、$_POST,该怎么处理
下一篇: 求正则表达式写法解决方法