0.Servlet : 属于一个接口,动态资源,如果浏览器想访问服务器中的动态资源,那么需要自定义类直接或者间接实现Servlet接口
1)自定义类实现Servlet接口===自定义类中要实现Servlet接口中的全部的抽象方法
2)自定义类继承GenericServlet====只需要重写ervice方法
3)自定义类继承HttpServlet===》需要重写doGet doPost方法 ******
1.request:处理浏览器向服务器发送请求的数据的(请求行 请求头 请求体)
2.request继承体系:
ServletRequest(父接口)==== HttpServletRequest(子接口) === RequestFacade(实现类,tomcat定义)
3.获取请求参数:
1)Map<String,String[]> getParameterMap();页面中所有的请求参数 name属性值或者key作为map集合的键,提交的数据作为map集合的值 username:张三
2)String[] getParameterValues(String name) 获取指定的name的值,是一个数组
3)String getParameter(String name)获取指定的name的值,一个值
4.处理请求乱码:
1)
URLEncoder.encode(字符串,编码表); 编码
URLDecoder.decode(字符串,编码表); 解码
2)String类
Byte[] 字符串.getBytes("编码表");编码
String s = new String(字节数组,编码表);解码
3)
只是解决请求体乱码的,即解决post
request.setCharacterEncoding(编码表);
5.请求转发:属于服务器内部跳转。地址不发生改变,只有一次请求一次响应,可以共享request数据
request.getRequestDispatcher("/loginServlet").forward(request,response); 只要通过浏览器访问必须加虚拟路径day03
补充:绝对路径:
1)http://localhost:8080/day03/loginServlet
2)/day03/loginServlet 省略三要素,必须加/
6.response:处理服务器响应数据(响应行 响应头 响应体)给浏览器
7.继承体系:
ServletResponse(父接口)==== HttpServletResponse(子接口) === ResponseFacade(实现类,tomcat定义)
8.响应行:状态码 200 404 500 302 304(从浏览器缓存中获取)
9.设置响应头:response.setHeader("content-type","text/html;charset=utf-8") MIME:文件在tomcat服务器中的类型
response.setContentType("text/html;charset=utf-8")//告知浏览器文件的MIME类型并解决响应乱码问题
10.响应体:
1)响应字符数据:response.getWriter().print();
2) 响应字节数据:response.getOutputStream()响应字节数据
11.重定向:实现服务器外部跳转,多次请求和响应,不能共享request数据,地址发生改变
1)
response.setStatus(302);
response.setHeader("location","/day03/loginServlet");必须加虚拟路径,因为属于服务器外部,经过浏览器再次向服务器发送请求
2)
response.sendRedirect("/day03/loginServlet");
1.会话技术:打开浏览器访问某个服务器开始,直到关闭一方,会话结束
2.会话跟踪:在会话过程中会有数据的产生,需要使用对象存储:cookie session
3.cookie:创建服务器创建存在浏览器客户端。
好处:减轻服务器压力
弊端:不安全
原理:设置响应头:set-cookie:key=value
请求头:Cookie:key=value
4.cookie使用:
1)创建cookie: new Cookie(name,value)
2)将cookie响应给浏览器:response.addCookie(cookie对象);
3)持久化cookie:cookie.setMaxAge(秒);
4)获取cookie:Cookie[] request.getCookies()
5.session:创建服务器端,存储在服务器中,默认存活时间:30min
6.session原理:
1)浏览器第一次访问服务器,执行代码:HttpSession session=request.getSession();创建session,给session容器一个唯一标识JSESSIONID,tomcat创建会话级别的cookie存储JSESSIONID,最后响应给浏览器,下次访问tomcat服务器的时候携带cookie,取出JSESSIONID,然后比较JSESSIONID进行查找session容器
7.session使用:
1)创建session:HttpSession session=request.getSession();
2)向session中存储数据:session.setAttribute(String name,Object value)
3)从session中获取数据:session.getAttribute(String name)这个参数name必须和setAttribute方法第一个参数一致
4)持久化session:持久化cookie
Cookie cookie = new Cookie("JSESSIONID",sessionid的值);
设置存活时间
cookie.setMaxAge(秒);
响应cookie给浏览器:response.addCookie(cookie对象);
web核心:
1)request : 浏览器向服务器发送的请求数据(请求行 头 体)都封装到request对象中,使用request对象调用方法获取数据
请求转发:服务器内部跳转。request.getRequestDispatcher("不带虚拟路径").forward(request,response);
2) response:服务器给浏览器响应数据(响应行 头 体),使用response对象调用方法就可以使用服务器响应数据给浏览器
重定向:实现服务器外部跳转。response.sendRedirect("带虚拟路径");经过浏览器
3)cookie:会话产生的数据使用cookie存储,存在浏览器端。记住用户名 密码 购物车
4)session:会话产生的数据使用session存储,存在服务器端。验证码
Filter&Listener
今日目标
1. filter(过滤器)
2. listener(监听器)
JavaWeb的三大组件
# 概念
1. 组件: 是一个系统的组成部件
2. javaweb组件 : javaweb项目的组成部件
1). servlet
2). filter
3). listener
组件 | 作用 | 实现接口 |
---|---|---|
Servlet | 小应用程序,在JavaWeb中主要做为控制器来使用 可以处理用户的请求并且做出响应 | javax.servlet.Servlet |
Filter | 过滤器,对用户发送的请求或响应进行集中处理,实现请求的拦截 | javax.servlet.Filter |
Listener | 监听器,在Web执行过程中,监听一些事件,当相应事件发生时, 进行处理 | javax.servlet.XxxListener 每个事件有一个接口 |
一 Filter概述
生活中的过滤器
净水器、空气净化器、地铁安检
web中的过滤器
当用户访问服务器资源时,过滤器将请求拦截下来,完成一些通用的操作
Filter的作用
- 拦截客户端对web资源的请求 (重要!)
- 拦截web资源对客户端的响应
应用场景
如:登录验证、统一编码处理、敏感字符过滤
二 Filter快速入门(掌握)
1.过滤器API介绍
Filter表示过滤器接口,我们想使用该接口必须自定义类实现接口并实现该接口中的所有抽象方法。
javax.Servlet.Filter接口下面的三个方法:
方法 | 说明 |
---|---|
void init(FilterConfig filterConfig) | 过滤器对象创建的时候调用的方法 |
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | 执行过滤的方法,每次访问被拦截的资源都会执行该方法 |
void destory() | 过滤器销毁的时候调用的方法 |
注意:doFilter第三个参数:FilterChain 表示过滤器链接口。
放行:使用FilterChain 对象调用FilterChain 中的方法:chain.doFilter(request,response);即可以让浏览器访问服务器资源
不放行,那么不写上述代码,即不让浏览器访问服务器资源
2.过滤器开发步骤
1.自定义过滤器类实现过滤器接口Filter
2.在自定义类中实现过滤器接口Filter中的所有抽象方法
3.在doFilter方法体中书写拦截资源的代码
方法说明:
Filter过滤器接口的:
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
参数:
request:表示请求对象,不满足http协议
response:表示响应对象,不满足http协议
chain:属于FilterChain的接口,表示过滤器链。
FilterChain接口中具有一个放行方法:
void doFilter(ServletRequest request, ServletResponse response)
如果放行,希望浏览器可以访问拦截的资源则执行该方法
如果不放行,不希望浏览器访问拦截的资源则不执行该方法
4.配置过滤器
5.访问被拦截的资源
3.代码实现
过滤器类:
package com.itheima.sh.b_filter_01;
import javax.servlet.*;
import java.io.IOException;
//1.自定义过滤器类实现过滤器接口Filter
public class MyFilter implements Filter{
//2.在自定义类中实现过滤器接口Filter中的所有抽象方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
//3.在doFilter方法体中书写拦截资源的代码
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("执行过滤器了...");
//不放行
/*
Filter过滤器接口的:
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
参数:
request:表示请求对象,不满足http协议
response:表示响应对象,不满足http协议
chain:属于FilterChain的接口,表示过滤器链。
FilterChain接口中具有一个放行方法:
void doFilter(ServletRequest request, ServletResponse response)
如果放行,希望浏览器可以访问拦截的资源则执行该方法
如果不放行,不希望浏览器访问拦截的资源则不执行该方法
*/
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
说明:
1.如果放行,希望浏览器可以访问拦截的资源则执行该方法:
filterChain.doFilter(servletRequest,servletResponse);
2.如果不放行,不希望浏览器访问拦截的资源则不执行该方法
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--配置过滤器-->
<!--表示关联的过滤器类-->
<filter>
<filter-name>myFilter</filter-name>
<!--过滤器类的全路径,底层获取这里使用反射技术调用无参构造方法创建过滤器类的对象-->
<filter-class>com.itheima.sh.b_filter_01.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<!--配置被拦截的资源-->
<url-pattern>/filter01.html</url-pattern>
</filter-mapping>
</web-app>
被拦截的页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>来拦截我啊</h1>
</body>
</html>
小结:
1.配置过滤器有两种方式:
1)xml版本:
<!--配置过滤器-->
<!--表示关联的过滤器类-->
<filter>
<filter-name>myFilter</filter-name>
<!--过滤器类的全路径,底层获取这里使用反射技术调用无参构造方法创建过滤器类的对象-->
<filter-class>com.itheima.sh.b_filter_01.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<!--配置被拦截的资源-->
<url-pattern>/filter01.html</url-pattern>
</filter-mapping>
2)注解版本配置
使用注解必须去掉xml版本。
3)流程
4.修改idea的过滤器模板
【1】修改模板:
【2】
public void doFilter(javax.servlet.ServletRequest req, javax.servlet.ServletResponse resp, javax.servlet.FilterChain chain) throws javax.servlet.ServletException, java.io.IOException {
javax.servlet.http.HttpServletRequest request = (javax.servlet.http.HttpServletRequest)req;
javax.servlet.http.HttpServletResponse response = (javax.servlet.http.HttpServletResponse)resp;
//your code....
chain.doFilter(request, response);
}
【3】创建Filter
【2】修改模板
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebFilter("/${Entity_Name}")
public class ${Class_Name} implements javax.servlet.Filter {
public void destroy() {
}
public void doFilter(javax.servlet.ServletRequest req, javax.servlet.ServletResponse resp, javax.servlet.FilterChain chain) throws javax.servlet.ServletException, java.io.IOException {
javax.servlet.http.HttpServletRequest request = (javax.servlet.http.HttpServletRequest)req;
javax.servlet.http.HttpServletResponse response = (javax.servlet.http.HttpServletResponse)resp;
chain.doFilter(request, response);
}
public void init(javax.servlet.FilterConfig config) throws javax.servlet.ServletException {
}
}
5.过滤器入门小结
1. 用户发送请求,请求Web资源(包括html,jsp,servlet等)
2. 如果Web资源的地址,是filter要拦截的地址,请求将先经过filter,并执行doFilter()
3. doFilter()方法中如果调用filterChain.doFilter(),则允许请求访问下一个Web资源。
4. 访问Web资源,响应回来会再次经过filter,执行过滤器中的代码,到达浏览器端。
三 使用细节
1 生命周期
生命周期:指的是一个对象从生(创建)到死(销毁)的一个过程
// 初始化方法
public void init(FilterConfig config);
// 执行拦截方法
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain);
// 销毁方法
public void destroy();
* 创建
服务器启动项目加载,创建filter对象,执行init方法(只执行一次)
* 运行(过滤拦截)
用户访问被拦截目标资源时,执行doFilter方法
* 销毁
服务器关闭时,销毁filter对象,执行destroy方法(只执行一次)
* 补充:
过滤器一定是优先于servlet创建的,后于Servlet销毁
复习:servlet默认是第一次访问的时候创建
package com.itheima01.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
Filter的生命周期方法
1. init
web服务器启动时,此方法运行,就运行一次(早于Servlet)
2. doFilter
当请求经过过滤器,此方法就会运行(每经过一次,就运行一次) (早于servlet的service方法)
3. destroy
tomcat关闭, 此方法运行一次 (晚于servlet的destroy)
*/
@WebFilter("/MyServlet2")
public class MyFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyFilter2 init");
}
//当请求经过过滤器,此方法就会运行(每经过一次,就运行一次)
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("MyFilter2 doFilter");
//请求放行 (相当于请求转发)
chain.doFilter(request,response);
}
@Override
public void destroy() {
System.out.println("MyFilter2 destroy");
}
}
package com.itheima01.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet(value = "/MyServlet2",loadOnStartup = 0)
public class MyServlet2 implements Servlet {
//默认第一次请求时执行,就执行一次
//通过loadOnStartup设置启动加载,tomcat启动时就会运行
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("MyServlet init");
}
//每次请求,运行一次
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("MyServlet service");
}
//tomcat关闭, 此方法运行一次
@Override
public void destroy() {
System.out.println("MyServlet destroy");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
}
小结:
1.过滤器是在tomcat启动的时候tomcat调用过滤器类中的无参构造方法创建对象,使用对象调用init方法,只会执行一次
2.当使用浏览器访问被过滤的资源的时候就会执行过滤器Filter中的doFilter方法,访问一次就会执行一次doFilter方法
3.当关闭tomcat服务器就会使用对象调用销毁方法destroy,只会执行一次
4.过滤器优先于访问的资源执行
2 拦截路径(重点)
在开发时,我们可以指定过滤器的拦截路径来定义拦截目标资源的范围
* 精准匹配
用户访问指定目标资源(/demo01.html)时,过滤器进行拦截
* 目录匹配
用户访问指定目录下(/user/*)所有资源时,过滤器进行拦截
* 后缀匹配
用户访问指定后缀名(*.html)的资源时,过滤器进行拦截,不能加/
* 匹配所有
用户访问该网站所有资源(/*)时,过滤器进行拦截 掌握
package com.itheima01.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//@WebFilter("/xx")
//@WebFilter({"/xx","/yy"})
@WebFilter("/xx") // 精准匹配
//@WebFilter("/user/*") // 目录匹配
//@WebFilter("*.do") // 后缀匹配
//@WebFilter("/*") // 匹配所有
public class MyFilter3 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("doFilter");
}
@Override
public void destroy() {
}
}
小结:
1.精确匹配:拦截哪个资源就书写哪个资源 /demo01.html /demo02Servlet 掌握
2.目录匹配:/xxx/* 拦截以xxx开始的所有资源
举例:/user/* 只要浏览器访问的资源路径以user开始都会执行该过滤器
3.后缀名匹配:*.xxx 拦截以xxx结尾的资源,这里不能加/ 。
举例:*.html:拦截所有以html结尾的资源
4.匹配所有路径:/* 掌握
3 过滤器链
在一次请求中,若我们请求匹配到了多个filter,通过请求就相当于把这些filter串起来了,形成了过滤器链。
问题:如果多个过滤器都对相同路径进行匹配,执行顺序该是什么?
Filter默认是按照字母顺序执行的,如果过滤器名字第一个字母相同,再看过滤器名字的第二个字母,以此类推。从而形成一个执行链条。
前提:多个过滤器过滤同一个资源,并且多个过滤器是在同一包下。
package com.itheima.sh.c_process_filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/apple")
public class AFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
System.out.println("AFilter....放行前");
chain.doFilter(request, response);
System.out.println("AFilter....放行后");
}
public void init(FilterConfig config) throws ServletException {
}
}
package com.itheima.sh.c_process_filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/apple")
public class BFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
System.out.println("BFilter....放行前");
chain.doFilter(request, response);
System.out.println("BFilter....放行后");
}
public void init(FilterConfig config) throws ServletException {
}
}
package com.itheima.sh.c_process_filter;
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 java.io.IOException;
@WebServlet("/apple")
public class AppleServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("AppleServlet....");
}
}
小结:
1.如果同一个包下,多个过滤器拦截同一个资源,那么按照过滤器类的名字字母升序来依次执行
AFilter ---- BFilter
2.执行完拦截资源后依次在按照相反顺序执行
3.如果是xml配置方式,那么按照从上往下配置的顺序执行
四 Filter案例(课下必须完成)
1、Filter统一解决全站乱码问题
8.0版本以上的tomcat为我们解决了get请求的乱码问题。我们需要自己处理post请求的乱码问题,因为我们的一个项目中可能有很多的请求。当然,我们可以在每一个Servlet中都对post的乱码进行处理。但是,Filter给我们提供了一个更加便捷的方式。我们自定义一个Filter类,拦截所有的请求,然后对这些请求进行post乱码处理即可。
【参考代码】:
1)页面:demo03.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/day15/demo01Servlet" method="post">
用户名: <input type="text" name="username">
<input type="submit">
</form>
</body>
</html>
2)后台 servlet代码:
RegisterServlet.java
package com.itheima.sh.c_filter_test_03;
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 java.io.IOException;
@WebServlet("/demo01Servlet")
public class Demo01Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决请求乱码
// request.setCharacterEncoding("utf-8");
//解决响应乱码
// response.setContentType("text/html;charset=utf-8");
//获取请求数据
String username = request.getParameter("username");
//输出
System.out.println("username = " + username);
//响应数据给浏览器
response.getWriter().print("姓名是:"+username);
}
}
说明:上述代码中我们需要处理post请求乱码和响应乱码,如果多个servlet,那么我们就会每个servlet中都会进行处理,这样代码会冗余,我们可以考虑使用过滤器来解决处理乱码问题。即将处理乱码的代码放到过滤器中来处理。
3)过滤器EncodingFilter中的代码:
package com.itheima.sh.c_filter_test_03;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
/*表示拦截当前项目中所有的资源路径
解决全站乱码问题
*/
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//解决请求乱码
request.setCharacterEncoding("utf-8");
//解决响应乱码
response.setContentType("text/html;charset=utf-8");
//your code....
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}
2、过滤器案例--登录权限校验
【需求】
- 登录之后:能够访问hack.html,然后下载黑客视频资源,成为NB黑客;
- 未登录:跳转到登录页面,并提示"请先登录";
- 我们对hack.html页面进行过滤,
详细描述:
1.页面:hack.html 访问这个页面要求必须先登录,不登录不能访问,使用过滤器书写代码让其跳转到登录页面login.html.
2.登录LoginServlet中获取用户名和密码,存放到User对象中,然后在session中。最后重定向到hack.html
3.使用一个过滤器对hack.html 进行拦截,先从session中获取用户信息,如果没有登录,获取的是null。跳转到登录页面。如果不为null,说明登录了,可以访问hack.html。
下载资源页面:hack.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>黑客。。</h1>
<a href="javascript:;">下载黑客资源</a>
</body>
</html>
页面login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/day15/loginServlet" method="post">
用户名:<input type="text" name="name"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
javabean,User类:
public class User {
private String name;
private String password;
public User(String name, String password) {
this.name = name;
this.password = password;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
LoginServlet代码:
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户名和密码
String name = request.getParameter("name");
String password = request.getParameter("password");
User user = new User(name,password);
System.out.println("user = " + user);
//将用户信息保存session中
request.getSession().setAttribute("user",user);
response.sendRedirect("/hack.html");
}
}
LoginFilter代码:
@WebFilter("/hack.html")
public class LoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//获取用户信息
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
//没有登陆
response.sendRedirect("/login.html");
return;
} else {
//放行。。
chain.doFilter(request, response);
}
}
public void init(FilterConfig config) throws ServletException {
}
}
补充:(了解,看下就行了)
package com.itheima.sh.e_filter_05;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//过滤的资源是hack.html页面
/*
说明:
1.过滤器默认拦截方式是来自于浏览器的请求,不拦截服务器内部的,转发属于服务器内部的,所以在执行代码:
request.getRequestDispatcher("/hack.html").forward(request,response);
并没有执行过滤器,如果想拦截服务器内部的跳转和浏览器的请求,需要进行配置
2.如果配置类拦截服务器的内部的,那么必须也得配置拦截来自于浏览器的请求,否则不会拦截浏览器的请求。
我们希望该过滤器即拦截服务器内部的,又拦截浏览器的请求,那么需要这样配置:
dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}
DispatcherType.FORWARD : 拦截请求转发(服务器内部)
DispatcherType.REQUEST:拦截浏览器的请求 (服务器外部的) 默认的
*/
@WebFilter(value = "/hack.html",dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})
public class Login2Filter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
/*
在当前过滤器中判断用户是否登录:
1.如果用户没有登录,直接访问hack.html页面,需要跳转到登录页面
2.登录,说明可以访问hack.html页面,放行
*/
//1.获取session中的实体类对象
// request.getSession().setAttribute("u",user);
User u = (User) request.getSession().getAttribute("u");
//2.判断u是否等于null
if(u == null){
//说明用户没有登录,直接访问hack.html页面,需要跳转到登录页面
response.sendRedirect("/login2.html");
}else{
//登录,说明可以访问hack.html页面,放行
//your code....
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}
五 Listener和ServletContext
补充:
1.ServletContext 表示上下文对象,属于接口,代表整个web项目,可以使用方法获取当前web项目的所有文件的MIME类型
2.之前学习能够共享数据的对象:
1)request: 只能在一次请求一次响应中进行数据的共享
2)session:只能在一次会话过程中,可以有多次请求和响应,
3)ServletContext:只要项目存在就可以共享数据,多次会话,多次请求和响应都可以共享数据:操作整个项目的配置文件
范围大小: ServletContext > session > request
1.0 ServletContext对象介绍
ServletContext对象:当tomcat服务器启动的时候,会为每个web项目创建一个唯一的ServletContext对象,该对象代表当前整个Web应用项目。该对象不仅封装了当前web应用的所有信息,而且实现了多个servlet的数据共享.在ServletContext中可以存放共享数据,ServletContext对象是真正的一个全局对象,凡是web容器中的Servlet都可以访问。
在每个项目中可以有多个Servlet程序,每个Servlet程序都是独立的。当前这个项目的配置信息,就必须使用描述这个项目的ServletContext对象获取。
方法名 | 描述 |
---|---|
setAttribute(String name,Object object) | 向ServletContext中存数据 |
getAttribute(String name) | 从ServletContext中取数据 |
removeAttribute(name) | 从ServletContext中移除数据 |
String getRealPath(String path) | 返回资源文件在服务器文件系统上的真实路径(文件的绝对路径) |
getMimeType(fileName) | 获取服务器中文件类型 |
ServletContext对象,tomcat为每一个web项目单独创建的一个上下文(知上知下贯穿全文)对象。有如下功能:
1.可以在多个servlet之间共享数据
存放:setAttribute()
获得:getAttribute()
删除:removeAttribute()
2.可以获得当前WEB项目中的指定资源(文件)
String path = getRealPath( String string);
需求1:如何获取上下文servletContext对象。
使用HttpServlet类的父类 GenericServlet 中的方法:getServletContext();
代码如下:
/*
获取上下文ServletContext对象:
使用HttpServlet类的父类 GenericServlet 中的方法:getServletContext();
*/
@WebServlet("/servletContextDemoServlet")
public class ServletContextDemoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext类的对象
ServletContext servletContext = getServletContext();
}
}
需求2:如何获取服务器中每个文件的路径。例如,在当前项目下的web文件夹下放一个1.jpg的图片,获取其真实路径(绝对路径)。
@WebServlet("/servletContextDemoServlet")
public class ServletContextDemoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
//如何获取服务器中每个文件的路径。
// 例如,在当前项目下的web文件夹下放一个1.jpg的图片,获取其真实路径(绝对路径)。
String realPath = servletContext.getRealPath("/1.jpg");
/*
输出结果:
realPath = F:\ideawork\jiuyeban2\heima60\heima03\out\artifacts\web_war_exploded\1.jpg
说明:我们的项目在发布的时候会被打成一个war包,这个war包下的class文件会被放在tomcat下被运行。
所以这里获取的真实路径是这个war包下的1.jpg所在的路径。
*/
System.out.println("realPath = " + realPath);
}
}
说明:
获取结果:
realPath = F:\ideawork\jiuyeban2\heima60\heima03\out\artifacts\web_war_exploded\1.jpg
说明:我们的项目在发布的时候会被打成一个war包,这个war包下的class文件会被放在tomcat下被运行。
所以这里获取的真实路径是这个war包下的1.jpg所在的路径。
如图:
需求3:获取当前项目下的1.jpg在服务器中的文件类型。
/*
需求3:获取当前项目下的1.jpg在服务器中的文件类型。
getMimeType("1.jpg");这里书写获取文件类型的文件名和后缀名即可
*/
String mimeType = servletContext.getMimeType("1.jpg");
System.out.println("mimeType = " + mimeType);//mimeType = image/jpeg
注意:对于方法 getMimeType("1.jpg");这里书写获取文件类型的文件名和后缀名即可
1.1 Listener概述
说明:
javaweb中的监听器是监听ServletContext HttpSession HttpServletRequest三个对象创建和销毁的,同时监听是哪个对象中数据的变化,就是监听属性的变化:setAttribute removeAttribute
# 监听
1. 设置监听器的人
2. 监听器
2. 监听器目标: 被监听的对象
3. 监听器工作: 被监听的对象执行某种行为,监听器就开始工作
# web里面
1. 雇佣人 : web程序开发者
2. 监听器例子A
1). 监听器A: ServletContextListener ****
2). 目标 : 监听ServletContext对象
3). 执行 : 监听ServletContext对象创建和销毁
3. 监听器例子B
1). 监听器A: HttpSessionListener
2). 目标 : HttpSession对象
3). 执行 : 监听HttpSession对象创建和销毁
4. 监听器例子C
1). 监听器A: HttpRequestListener
2). 目标 : HttpRequest对象
3). 执行 : 监听HttpRequest对象创建和销毁
5. 监听器例子D
1). 监听器A: ServletContextAttributeListener ****
2). 目标 : ServletContext对象
3). 执行 : 监听ServletContext对象增删改数据 (add,remove) 当我们向ServletContext对象中添加数据(setAttribute())和删除数据(removeAttribute())就会被ServletContextAttributeListener监听器监听
HttpSessionAttributeListener HttpRequestAttributeListener
生活中的监听器
我们很多商场有摄像头,监视着客户的一举一动。如果客户有违法行为,商场可以采取相应的措施。
javaweb中的监听器
在我们的java程序中,有时也需要监视某些事情,一旦被监视的对象发生相应的变化,我们应该采取相应的操作。
监听web三大域对象:HttpServletRequest、HttpSession、ServletContext (创建和销毁)
场景
历史访问次数、统计在线人数、系统启动时初始化配置信息
监听器的接口分类
事件源 | 监听器接口 | 时机 |
---|---|---|
ServletContext | ServletContextListener | 上下文域创建和销毁 |
ServletContext | ServletContextAttributeListener | 上下文域属性增删改的操作 |
**HttpSession ** | HttpSessionListener | 会话域创建和销毁 |
**HttpSession ** | HttpSessionAttributeListener | 会话域属性增删改的操作 |
HttpServletRequest | ServletRequestListener | 请求域创建和销毁 |
HttpServletRequest | ServletRequestAttributeListener | 请求域属性增删改的操作 |
1.2 Listener快速入门
监听器在web开发中使用的比较少,见的机会就更少了,今天我们使用ServletContextListenner来带领大家学习下监听器,因为这个监听器是监听器中使用率最高的一个,且监听器的使用方式都差不多。
我们使用这个监听器可以在项目启动和销毁的时候做一些事情,例如,在项目启动的时候加载配置文件。
步骤分析
1. 创建一个普通类,实现ServletContextListenner
2. 重写抽象方法
监听ServletContext创建
监听ServletContext销毁
3. 配置
web.xml
注解 掌握
① xml版本
package com.itheima04;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/*
设置监听器的人: 开发者
监听器 : MyListener
监听器目标 : ServletContext 对象
监听器的工作:
1). 当ServletContext 对象创建的时候就会执行contextInitialized方法
ServletContext是tomcat启动时就会创建 (早于Filter和Servlet)
2). 当ServletContext 对象销毁的时候就会执行contextDestroyed方法
ServletContext是tomcat关闭时销毁 (晚于Filter和Servlet)
这两个方法是事件驱动
*/
public class MyListener implements ServletContextListener {
//tomcat一启动,此方法就会运行
//运用场景: spring底层封装了一个ServletContextListener加载配置文件
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
}
}
<listener>
<listener-class>com.itheima08.MyServletContextListener</listener-class>
</listener>
② 注解版本
@WebListener
public class MyListener implements ServletContextListener {
//tomcat一启动,此方法就会运行
//运用场景: spring底层封装了一个ServletContextListener加载配置文件
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
}
}
1.3 案例:模拟spring框架
需求:可以在项目启动时读取配置文件。获取配置文件的名字。
步骤:
1.在web.xml进行配置文件的配置
2.创建自定义监听器类监听ServletContext的创建和销毁
3.在自定义监听器类中实现监听器的抽象方法
4.实现的方法体中读取web.xml文件中关于当前项目配置文件的信息
5.输出结果
package com.itheima.sh.h_listener_08;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
//2.创建自定义监听器类监听ServletContext的创建和销毁
//别忘记注册监听器
@WebListener
public class SpringContextListener implements ServletContextListener{
//3.在自定义监听器类中实现监听器的抽象方法
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//4.实现的方法体中读取web.xml文件中关于当前项目配置文件的信息
//4.1根据事件类对象servletContextEvent调用方法获取ServletContext上下文对象
ServletContext servletContext = servletContextEvent.getServletContext();
//4.2使用上下文对象调用方法获取web.xml配置文件中的数据
/*
<context-param>
<param-name>jdbc</param-name>
<param-value>jdbc.properties</param-value>
</context-param>
*/
String str = servletContext.getInitParameter("jdbc");
System.out.println("str = " + str);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("释放资源....销毁。。。。");
}
}
<!--配置当前项目的配置文件信息-->
<!--1.在web.xml进行配置文件的配置-->
<context-param>
<param-name>jdbc</param-name>
<param-value>jdbc.properties</param-value>
</context-param>
标签:Listener,Day08,void,request,javax,Filter,response,servlet,public
From: https://www.cnblogs.com/-turing/p/17207924.html