JavaWeb:三大组件servlet & Filter & Listener

当当当当~~~~欢迎大家阅读,今天我们学习JavaWeb中的三大组件(servlet)程序、(Filter)过滤器和(Listener)监听器

servlet程序

一:概念

运行在服务器端的小程序
其实Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。
将来我们自定义一个类,实现Servlet接口,复写方法。

二:快速入门

(一):创建JavaEE项目

(二):定义一个类,实现Servlet接口   

  public class ServletDemo1 implements Servlet{}

(三):实现接口中的抽象方法

@WebServlet("/demo")
public class ServletDemo implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet3.0来了......");

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

(四):配置Servlet:在web.xml中配置

  <!--配置Servlet -->
        <servlet>
            <servlet-name>demo1</servlet-name>
            <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>demo1</servlet-name>
            <url-pattern>/demo1</url-pattern>
        </servlet-mapping>

三:执行原理

1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。
3. 如果有,则在找到对应的<servlet-class>全类名
4. tomcat会将字节码文件加载进内存,并且创建其对象
5. 调用其方法

四:Servlet中的生命周期方法

(一):被创建:执行init方法,只执行一次

1:Servlet什么时候被创建?

(1):默认情况下,第一次被访问时,Servlet被创建
(2):可以配置执行Servlet的创建时机。

 <!--配置Servlet-->
    <servlet>
        <servlet-name>demo1</servlet-name>
        <servlet-class>servlet.ServletDemo1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>demo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
    </servlet-mapping>

    <!--配置Servlet-->
    <servlet>
        <servlet-name>demo2</servlet-name>
        <servlet-class>servlet.ServletDemo2</servlet-class>

        <!--指定Servlet的创建时机
         1.第一次被访问时创建
         <load-on-startup>的值为负数
         2.在服务器启动时创建
          <load-on-startup>的值为0或正整数-->
        <load-on-startup>5</load-on-startup>
    </servlet>

2:Servlet的init方法,只执行一次

说明一个Servlet在内存中只存在一个对象,Servlet是单例的
多个用户同时访问时,可能存在线程安全问题。
解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要修改值

(二):提供服务:执行service方法,执行多次

1:每次访问Servlet时,Service方法都会被调用一次

(三):被销毁:执行destroy方法,只执行一次

1:Servlet被销毁时执行。服务器关闭时,Servlet被销毁
2:只有服务器正常关闭时,才会执行destroy方法。
3:destroy方法在Servlet被销毁之前执行,一般用于释放资源

五:Servlet3.0

(一):好处

支持注解配置。可以不需要web.xml了。

(二):步骤

1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
2. 定义一个类,实现Servlet接口
3. 复写方法
4. 在类上使用@WebServlet注解,进行配置
@WebServlet("资源路径")

 六:Servlet的体系结构    

Servlet -- 接口
        |
GenericServlet -- 抽象类
        |
HttpServlet  -- 抽象类

(一):GenericServlet

将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可

public class ServletDemo2 extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("demo2......");

    }
}

(二):HttpServlet

对http协议的一种封装,简化操作
1. 定义类继承HttpServlet
2. 复写doGet/doPost方法

@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet......");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost......");
    }
}

七:Servlet相关配置

(一):urlpartten:Servlet访问路径

1:一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})

2:路径定义规则

(1):/xxx:路径匹配
(2):/xxx/xxx:多层路径,目录结构
(3):*.do:扩展名匹配

八:ServletContext对象

(一):概念

代表整个web应用,可以和程序的容器(服务器)来通信

(二):获取

@WebServlet("/servletContextDemo1")
public class ServletContextDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
        * ServletContext对象获取:
        * 1.通过request对象获取
        * request.getServletContext();
        * 2.通过HttpServlet获取
        * this.getServletContext();
        */
        //1.通过request对象获取
        ServletContext context1 = request.getServletContext();
        //2.通过HttpServlet获取
        ServletContext context2 = this.getServletContext();
        System.out.println(context1);
        System.out.println(context2);
        System.out.println(context1 == context2);//true


    }

(三):功能

1. 获取MIME类型

@WebServlet("/servletContextDemo2")
public class ServletContextDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
        获取MIME类型
        MIME类型:在互联网通信过程中定义的一种文件数据类型
		格式: 大类型/小类型   text/html		image/jpeg
        获取:String getMimeType(String file)
        */
        //1.通过HttpServlet对象获取
        ServletContext context = this.getServletContext();

        //2.定义文件名称
        String filename="a.jpg";//image/jpeg

        //3.获取MIME类型
        String mimeType = context.getMimeType(filename);
        System.out.println(mimeType);
    }

2. 域对象:共享数据

1. setAttribute(String name,Object value)
2. getAttribute(String name)
3. removeAttribute(String name)
 * ServletContext对象范围:所有用户所有请求的数据

3. 获取文件的真实(服务器)路径

@WebServlet("/servletContextDemo4")
public class ServletContextDemo5 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        /*
        1.获取MIME类型
        2.域对象:共享数据
        3.获取文件的真实(服务器)路径
        */

        //1.通过HttpServlet对象获取
        ServletContext context = this.getServletContext();

        //获取文件的服务器路径
        String realPath = context.getRealPath("/b.txt");//web目录下的资源访问
        File file=new File(realPath);

        String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
        System.out.println(c);

        String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
        System.out.println(a);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

(servlet)程序的讲解到这里就结束啦,接下来我们看(!Filter)过滤器~~~~

Filter:过滤器

一:概念

生活中的过滤器:净水器,空气净化器,土匪

web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。

二:过滤器的作用

一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤等...

三:快速入门

(一):步骤

1. 定义一个类,实现接口Filter
2. 复写方法
3. 配置拦截路径
        1. web.xml
         2. 注解

(二):代码

@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

四:过滤器细节

(一):web.xml配置    

    <filter>
        <filter-name>demo1</filter-name>
        <filter-class>filter.FilterDemo1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>demo1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

(二):过滤器执行流程

1. 执行过滤器
2. 执行放行后的资源
3. 回来执行过滤器放行代码下边的代码

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //对request对象请求消息增强
        System.out.println("filterDemo2执行了...");

        //放行
        chain.doFilter(req, resp);

        //对response对象的响应消息增强
        System.out.println("filterDemo2回来了...");
    }

(三):过滤器生命周期方法

1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
2. doFilter:每一次请求被拦截资源时,会执行。执行多次
3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源

@WebFilter("/*")
public class FilterDemo3 implements Filter {
    /*
     *@Description:在服务器启动后,会创建Filter对象,然后调用init方法
     *@param:config
     *@return:ServletException
     */
    public void init(FilterConfig config) throws ServletException {
        System.out.println("init...");

    }
    /*
    *@Description:每一次请求被拦截资源时,会执行
    *@param:req
    *@return:
    */
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("doFilter...");
        chain.doFilter(req, resp);
    }
    /*
    *@Description:在服务器关闭后,Filter对象被销毁,如果服务器是正常关闭,则会执行destroy方法
    *@param:
    *@return:
    */
    public void destroy() {
        System.out.println("destroy...");
    }
}

(四):过滤器配置详解

1:拦截路径配置

@WebFilter("/index.jsp") //1.具体资源路径:  /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
@WebFilter("/user/*")    //2.拦截目录:     /user/*访问/user下的所有资源时,过滤器都会被执行
@WebFilter("*.jsp")     //3. 后缀名拦截:   *.jsp	访问所有后缀名为jsp资源时,过滤器都会被执行
@WebFilter("/*")        //4. 拦截所有资源:  /*	访问所有资源时,过滤器都会被执行

2:拦截方式配置:资源被访问的方式

注解配置

设置dispatcherTypes属性
1. REQUEST:默认值。浏览器直接请求资源
2. FORWARD:转发访问资源
3. INCLUDE:包含访问资源
4. ERROR:错误跳转资源
5. ASYNC:异步访问资源

//浏览器直接请求资源时,该过滤器会被执行
@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
//只有转发访问index.jsp时,该过滤器才会被执行
@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
//浏览器直接请求资源,转发访问index.jsp时,该过滤器都会被执行
@WebFilter(value = "/*",dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})

web.xml配置

设置<dispatcher></dispatcher>标签即可

(五):过滤器链(配置多个过滤器)

1:执行顺序:如果有两个过滤器:过滤器1和过滤器2

1. 过滤器1
2. 过滤器2
3. 资源执行
4. 过滤器2
5. 过滤器1 

举例:doFilter...
           filterDemo6执行了...
           filterDemo7执行了...
           index.jsp...
           filterDem7回来了...
           filterDem6回来了...

2:过滤器先后顺序问题

1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
如: AFilter 和 BFilter,AFilter就先执行了。

2. web.xml配置: <filter-mapping>谁定义在上边,谁先执行

代理设计模式:增强对象的功能

 一:概念

1. 真实对象:被代理的对象
2. 代理对象:
3. 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的

二:实现方式

(一):静态代理:有一个类文件描述代理模式

(二):动态代理:在内存中形成代理类

1:实现步骤

1. 代理对象和真实对象实现相同的接口
2. 代理对象 = Proxy.newProxyInstance();
3. 使用代理对象调用方法。
4. 增强方法

举例:联想电脑的代理 

先创建一个真实对象,再在接口中声明代理对象和真实对象需要实现的方法,让代理对象和真实对象实现相同的接口

public class Lenovo implements SaleComputer {
    @Override
    public String sale(double money) {
        System.out.println("花了"+money+"元买了一台联想电脑...");
        return "联想电脑";
    }

    @Override
    public void show() {
        System.out.println("展示电脑...");
    }
}
public interface SaleComputer {
    public  String  sale(double money);

    public void show();
}

 2:增强方式

1. 增强参数列表
2. 增强返回值类型
3. 增强方法体执行逻辑

public class ProxyTest {

    public static void main(String[] args) {
        //1:创建真实对象
        Lenovo lenovo=new Lenovo();

        //2:动态代理增强Lenovo对象
        /*
        * 三个参数
        * 1:类加载器:真实对象.getClass().getClassLoader()
        * 2:接口数组:真实对象.getClass().getInterfaces()
        * 3:处理器:new InvocationHandler()
        */
        SaleComputer proxy_lenovo= (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
            /*
            * 代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
            * 参数:
            * 1:proxy:代理对象
            * 2:method:代理对象调用的方法,被封装为的对象
            * 3:args:代理对象调用方法时,传递的实际参数*/

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               /* System.out.println("该方法执行了...");
                System.out.println(method.getName());
                System.out.println(args[0]);*/


                //方式一:增强参数
                //判断是否时sale方法
                if(method.getName().equals("sale")){
                   //1.增强参数
                   double money= (double) args[0];
                   money=money*0.85;
                    System.out.println("专车接你...");
                   //使用真实对象调用该方法
                    String obj = (String) method.invoke(lenovo, money);
                    System.out.println("免费送货...");
                    //2.增强返回值
                    return obj+"_鼠标垫";
                }else{
                    Object obj = method.invoke(lenovo, args);
                    return obj;

                }
            }
        });
        //3:调用方法
       /* String computer = lenovo.sale(8000);
        System.out.println(computer);*/

        proxy_lenovo.show();
    }
}

​​​​​​​ 

(Filter)过滤器的讲解到这里就结束啦,接下来我们看(Listener)监听器~~~~

Listener:监听器

一: 概念

(一):事件监听机制

事件    :一件事情
事件源 :事件发生的地方
监听器 :一个对象
注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码

(二):ServletContextListener:监听ServletContext对象的创建和销毁

1:方法

void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法

2:步骤

1. 定义一个类,实现ServletContextListener接口
2. 复写方法
3. 配置

3:web.xml配置

   <!--配置监听器-->
   <listener>
      <listener-class>listener.ContextLoaderListener</listener-class>
   </listener>
   <!--指定初始化参数-->
   <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
   </context-param>

 4:监听器的代码实现

public class ContextLoaderListener implements ServletContextListener {
    /*
    * 监听ServletContext对象创建的,ServletContext对象服务器启动后自动创建
    * 在服务器启动后自动调用*/
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //加载资源文件
        //1.获取ServletContext对象
        ServletContext servletContext = servletContextEvent.getServletContext();

        //2.加载资源文件
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");

        //3.获取真实路径
        String realPath = servletContext.getRealPath(contextConfigLocation);

        //4.加载进内存
        try{
        FileInputStream fis=new FileInputStream(realPath);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("ServletContext对象被创建了...");
    }

    /*
    * 在服务器关闭后,ServletContext对象被销毁,当服务器正常关闭后该方法被调用*/
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext对象被销毁了...");
    }
}

以上就是Servlet & Filter & Listener的内容啦,希望我的文章对你有所帮助,如果有错误的地方还望大家批评指正,谢谢大家阅读! 
  

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值