• javaweb应用程序概述


    1、HTTP(超文本传输协议),它是一种主流的B/S架构中应用的通信协议。具有以下特点:

    1.1、无状态:服务不会记录客户端每次提交的请求,服务器一旦响应客户端之后,就会结束本次的通信过程,客户端下一次的请求是一个新的连接,和上一次通信没有任何关系

    1.2、简单灵活:HTTP是基于请求和响应的模型

    支持客户端与服务端:

    1.3、支持主流的B/S以及C/S架构的通信。C/S架构可选的协议有多种,列如:TCP/IP、UDP、HTTP、等,而B/S架构通常只支持HTTP协议。

    2、服务器

    2.1、概念

    服务器同常由硬件和软件部分构成,对用户提供相应的服务

    硬件:包括相应的CPU、内存、磁盘、等等

    软件:包括操作系统、运行环境、服务端软件、数据库等等

    2.2、Web服务器

    web服务器是提供服务端程序运行的一个环境,它本身也是一个软件

    列如:将我们编写的html文件放到web容器服务器中,那么外界就可以通过浏览器来访问我们的HTML页面,

    常见的web服务器有Apache、Tomcat、Jetty、Nginx等等,而Tomcat、Jetty、这些web服务器更准确地来说是一个Servlet容器

     3. Web项⽬结构

    录,例
    如:
    myweb
    ch01
    通常存放静态资源⽂件(如: html等等)
    WEB-INF 这个⽬录是当前项⽬私有的⼀个⽂件夹,只能提供给项⽬内部访问,对于客户端来说是访问
    不到了,通常这个⽬录下存放的是Java源代码、编译后的字节码⽂件以及Servlet的核⼼配置⽂件web.xml
    src 存放Java源代码的⽬录
    classes 存放编译后的字节码⽂件
    llib lib⽬录存放当前项⽬所需要的jar⽂件
    jsp ⻚⾯ ⽤于存放JSP动态
    web.xml 项⽬的配置⽂件,⽤于配置Servlet的请求映射、过滤器、监听器等等信息。每⼀个web项⽬都对应⼀个web.xml配置⽂件

     

    4. Servlet基础

    4.1 什么是Servlet6

    ServletJavaEE中的标准组件之⼀,专⻔⽤于处理客
    户端的HTTP请求。并且它必须依赖于Servlet容器
    Tomcat就是⼀个标准的Servlet容器)才可以运⾏,
    ⽽不能脱离这个环境⽽单独执⾏。因为Servlet实例的
    创建和销毁都是由容器负责管理的,我们不能⾃⾏通过
    new关键去创建和使⽤它。

    4.2 编写⼀个简单的Servlet

    1.在任意地⽅创建⼀个myweb⽂件夹,这个⽂件夹相
    当于⼀个项⽬根⽬录
    2.在根⽬录下创建WEB-INF⼦⽬录
    3.WEB-INF⽬录下创建srcclasses⼦⽬录
    4.src⽬录下编写⼀个类,继承HttpServlet这个⽗类

    public class HelloServlet extends
    HttpServlet	{
    }
    

     2.重写⽗类的service⽅法,这个就是专⻔处理客户端请
    求的⽅法, web容器会为这个⽅法传⼊两个参数
    HttpServletRequestHttpServletResponse,并且这个
    ⽅法还需要抛出ServletExceptionIOException给容
    器捕获

    public class HelloServlet extends
    HttpServlet	{
    public void service(HttpServletRequest
    request,	 HttpServletResponse
    response)throws ServletException,	
    IOException{
    //设置响应类型及编码
    response.setContentType("text/html;charset
    =utf-8");
    //获取字符输出流输出html信息
    response.getWriter().println("
    <h1>Hello	Servlet</h1>")
    }
    }				
    

     5.编译Servlet,需要依赖servlet-api.jar⽂件,将它添加
    classpath

    javac    -cp    d:servlet-api.jar;
    HelloServlet.java
    

    6.将编译后的HelloServlet.class⽂件剪切到classes
    录中

    7.WEB-INF⽬录下创建并编辑web.xml⽂件,为
    servlet配置请求映射

    <?xml version="1.0"	encoding="utf-8"?>
    <!--	配置根节点	-->
    <web-app>
    <!--	配置servlet类	-->
    <servlet>
    <!--	指定servlet的别名	-->
    <servlet-name>hello</servlet-name>
    <!--	指定Servlet的完整类名-->
    <servlet-class>HelloServlet</servletclass>
    </servlet>
    <!--	配置请求映射-->
    <servlet-mapping>
    <!--	这⾥的servlet-name和上⾯的
    servlet-name要⼀⼀对应	-->
    <servlet-name>hello</servlet-name>
    <!--	配置请求映射的url,必须以“/”开头-->
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    </web-app>
    

     8.将项⽬部署都tomcatwebapps⽬录中,并执⾏bin
    录下的startup.bat启动容器

    9.打开浏览器,在地址栏输⼊http://localhost:8080/m
    yweb/hello访问Servlet

    4.3 Servlet的请求处理流程

    浏览器发起http的请求,这个请求⾸先会被servlet容器
    Tomcat)截获,然后容器会根据web.xml⽂件中配
    servlet的来找到相应的这个别名,然后再根据这个
    别名找到具体Servlet的类,然后容器会创建这个
    Servlet类的实例并调⽤service⽅法来处理这个请求。

    4.4 Servlet的⽣命周期

    所谓的⽣命周期,就是从Servlet的创建⼀直到它销毁
    的整个过程。并且它的这个⽣命周期都是由Servlet
    器(Tomcat)负责管理和维护的。(补充:在Tomcat
    中, Servlet是以单实例多线程的⽅式处理客户端请
    求)

    4.4.1 Servlet对象创建的过程

    当第⼀次请求某个Servlet的时候,容器会先查找之前
    有没有创建过这个Servlet的实例,如果没有则创建⼀
    个并缓存起来。后续相同的请求都由这个缓存的对象来
    处理。(注意:这⾥说的是第⼀次请求时创建。另外⼀
    种情况则是在容器启动的时候就创建Servlet的实例,

    4.4.2 ⽣命周期⽅法

    ⽅法名  描述
    init Servlet对象创建之后⽴即执⾏的初始化
    ⽅法,且只执⾏⼀次
    service 核⼼的请求处理⽅法,这个⽅法可以执⾏
    多次
    destroy 容器准备销毁Servlet实例之前执⾏这个⽅
    法,也是执⾏⼀次


    web.xml中为Servlet指定配置,这个配置的值是⼀个整型,数值越⼩,则初始化的优先级别越⾼)

    4.5 HTTP报⽂组成

    4.5.1 请求报⽂

    请求⾏:请求报⽂的第⼀⾏就是请求⾏。包括请求⽅
    法、请求URL地址、 HTTP协议版本。
    请求头:请求⾏之后的信息就是请求头,它是以名称:
    内容的格式体现。主要包括服务器主机地址及端⼝、
    连接状态、系统信息、编码、语⾔等等。
    请求体:请求头结束之后会有⼀个空⾏,空⾏之后就是
    请求体的内容。通常使⽤POST提交的数据信息会存放
    在请求体当中,然后传递给服务器。
    4.5.2 响应报⽂

    状态⾏:主要包括HTTP协议、响应状态码(例如:
    200表示OK,成功响应)。
    响应头:主要包括服务器信息、响应的类型及编码、内容的⻓度、响应的时间等。
    响应体:服务端可以将信息数据携带到响应体中,带回客户端。
    4.6 HTTP请求⽅法

    HTTP/1.1协议中,请求⽅法主要包括8个,下⾯列举
    常⽤的请求⽅法进⾏说明。

    ⽅法 说明
    GET 向服务器请求指定的资源,并返回响应主
    体。⼀般来说GET⽅法应该只⽤于数据的
    读取(类似于查询)
    POST 向指定的服务器提交数据(例如:表单数
    据的提交、⽂件上传等) ,并且提交的数据
    会放⼊请求体中(类似于新增)
    PUT 向服务器提交数据,但是和POST有所区
    别。如果服务器不存在此资源的时候,则
    执⾏新增,如果存在则执⾏修改(类似于
    修改)
    DELETE 根据uri的标识删除服务器上的某个资源
    (类似于删除)
    其他 ...


    备注: GETPOST区别:                

    1.GET主要⽤于获取数据, POST⽤于提交数据。
    2.GET请求所带的参数是放在请求⾏的url地址后⾯,⽽POST这是放在请求体中。
    3.通常浏览器会对GET请求的url⻓度有所限制,⽽POST提交的数据在请求体中,可以提交更多的内容。

    ⽅法 说明
    service 可以处理任何的请求类型
    doGet 处理对应的GET请求
    doPost 处理对应的POST请求
    doPut 处理对应的PUT请求
    doDelete 处理对应的DELETE请求
    其他 ...

    4.浏览器会对GET请求进⾏缓存

    说明:通过HttpServlet的源代码得知,默认的所有请求都会先经过service⽅法,然后service⽅法根据请求
    的⽅法类型判断来决定交给doGet或者是doPost⽅法来处理请求。如果⼦类重写了⽗类的service⽅法同时
    还重写了其他的doXxx的⽅法,那么只有service⽅法会处理请求,其他⽅法将失效。
    4.8 RequestResponse对象

    web容器调⽤某个ServletService⽅法时,会创建⼀个HttpServletRequestHttpServletRespinse对象
    作为参数传⼊到这个⽅法中,那么我们可以通过HttpServletRequest来获取相关的请求内容等,⽽响应客户端

    可以利⽤HttpServletResponse对象来完成。

     4.9 Servlet之间的通信

    4.9.1转发

    所谓转发就是在多个Servlet之间共享请求和响应对象,所有参与转发的过程的Servlet都可以获取同一个请求对象的信息。

    在servlet的API中,转发的操作有HttpServletRequest

    示例代码:

    package edu.nf.ch06.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletA extends HttpServlet{
    	
    	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    		System.out.println("请求经过ServletA,准备转发给ServletB...");
    		//获取页面提交的参数
    		String name = request.getParameter("userName");
    		System.out.println("ServletA获取请求参数:"+name);
    		
    		//可以使用请求作用域(requestScope)而外携带一些数据到ServletB
    		request.setAttribute("age", 35);
    		System.out.println("设置请求作用域:age = " + 35);
    		//转发由HttpServletRequest完成
    		//第一步先获取一个请求转发器RequestDispatcher
    		//获取请求转发器的同时要告诉转发器转发到哪里,转发给谁
    		//如果要转发给ServletB,那么就是对应ServletB的url-pattern
    		RequestDispatcher rd = request.getRequestDispatcher("servletB");
    		//调用转发器的forward方法执行转发,同时将request和response对象一并转发ServletB
    		rd.forward(request, response);
    		
    	}
    }
    
    package edu.nf.ch06.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletB extends HttpServlet{
    
    	@Override
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		System.out.println("请求到达ServletB,并接收了同一个请求和响应对象");
    		//这里在同一个请求中再次获取页面的参数
    		String name = request.getParameter("userName");
    		//从请求作用域中取出相应的值
    		Integer age = (Integer)request.getAttribute("age");
    		System.out.println("ServletB获取请求参数:"+name);
    		System.out.println("ServletB获取请求作用域的值:"+age);
    	}
    }
    

     

      <servlet>
      	<servlet-name>servletA</servlet-name>
      	<servlet-class>edu.nf.ch06.servlet.ServletA</servlet-class>
      </servlet>
      <servlet-mapping>
      	<servlet-name>servletA</servlet-name>
      	<url-pattern>/servletA</url-pattern>
      </servlet-mapping>
     
     <servlet>
      	<servlet-name>servletB</servlet-name>
      	<servlet-class>edu.nf.ch06.servlet.ServletB</servlet-class>
      </servlet>
      <servlet-mapping>
      	<servlet-name>servletB</servlet-name>
      	<url-pattern>/servletB</url-pattern>
      </servlet-mapping>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
     <a href="servletA?userName=wangl">测试转发</a><br/>
    </body>
    </html>
    

    转发的特点:

    1、url的地址栏是不会发生改变的

    2、转发的过程是在服务端自动完成的

    4.9.2 重定向

    重定向的机制和转发不同,一次重定向的过程中会有两次请求和两次响应,服务器在接受第一次请求后悔先做一次302响应(302表示重定向状态码)

    告诉客户端浏览器必须发起一个新的请求地址,服务端再次接受这个请求处理,最后再次响应到客户端。由于会产生不同的响应对象,因此并不同共享同一个请求的参数

    重定向是服务器通知浏览器去访问另一个地址,即再发出另一个请求。

    下面用一张图来简单描述下:

    重定向的特点:

    1、URL地址栏会发生改变

    2、重定向的操作是在客户端浏览器完成的

    示例代码:

    package edu.nf.ch06.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletC extends HttpServlet {
    
    	@Override
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		System.out.println("请求到达ServletC");
    		System.out.println("ServletC获取请求参数:"+request.getParameter("userName"));
    		//执行重定向
    		//方式一:设置302响应状态码,并在响应头中添加location属性指定重定向的地址
    		//response.setStatus(302);
    		//response.addHeader("location", "http://localhost:8080/ch06/servletD");
    		
    		//方式二:
    		response.sendRedirect("servletD");
    	}
    }
    
    package edu.nf.ch06.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletD extends HttpServlet{
    	@Override
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		System.out.println("重定向到ServletD");
    		System.out.println("ServletD获取请求参数:"+request.getParameter("userName"));
    	}
    }
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
     <a href="servletC?userName=wangl">测试重定向</a>
    </body>
    </html>
    

    4.10会话跟踪

    由于HTTP协议是无状态的,服务器并不会记录每一个客服端的状态,因此,如果想要实现服务器能记录客服端的状态的话,那么就需要会话跟踪技术

    4.1.1cookie

    cookie是客服端浏览器内部的一个文本文件,专门用于记录服务器发送过来的一些文本信息,那么再次请求的时候,都把这个cookie信息由提交回给

    相应的服务器,那么服务器就可以获取客服端保存的信息,达到会话跟踪的目的,使用cookie的机制是基于客户端浏览器来维护与服务端的状态跟踪

    cookie的生命周期:

    示例代码:

    默认cookie只会保存在浏览器进程的内存中,并不会写入cookie文件,如果关闭了浏览器,那么浏览器的进程也就会消失,那么对应的内存就会释放空间,

    因此cookie也就销毁。如果想要cookie写入文件,那么就必须设置cookie的生命时长,一旦设置了生命时长,那么就表示这个cookie会在文件中保留多长

    时间,到了这个时间之后,浏览器就会自动销毁这个cookie

    设置cookie:

    public class SetCookieServlet extends
    HttpServlet{
    protected void
    service(HttpServletRequest request,
    HttpServletResponse response)	throws
    ServletException,	IOException	{
    //创建⼀个Cookie的实例
    Cookie cookie = new
    Cookie("userId","10001");
    //将cookie对象设置到响应对象中
    response.addCookie(cookie);
    System.out.println("成功设置
    cookie");
    }
    }
    

    获取cookie

    public class GetCookieServlet extends
    HttpServlet{
    @Override
    protected void
    service(HttpServletRequest request,
    HttpServletResponse repsonse)	throws
    ServletException,	IOException	{
    //cookie是通过request对象来得到的
    //从请求中可以获取多个cookie对象
    Cookie[]	cookies =
    request.getCookies();
    for	(Cookie cookie	:	cookies)	{
    //判断cookie,只获取name为userId
    的cookie对象
    if("userId".equals(cookie.getName()))	{
    System.out.println(cookie.getValue());
    }
    }
    }
    }
    

    cookie保存中文 :

    在保存cookie的时候如果需要保存中⽂,那么中⽂信息
    需要经过编码后才可以写⼊cookie
    示例代码:
    编码使⽤URLEncoder

    String str = URLEncoder.encode("张三",
    "utf-8");
    Cookie cookie = new Cookie("userName",
    str);
    

     解码使⽤URLDecoder :

    String str =
    URLDecoder.decode(cookie.getValue(),"utf-8");
    System.out.println(str);
    

    设置cookie的存活时间:

    示例代码:

    //设置为0表示⽴即删除cookie
    cookie.setMaxAge(0);
    //设置为正数表示cookie在cookie⽂件的存活时间,
    单位:秒
    cookie.setMaxAge(5);
    //设置为-1表示cookie只保留在浏览器器的进程中,
    关闭浏览器之后会销毁cookie
    cookie.setMaxAge(-1);
    

    4.4.2 Session

    Session是基于服务端来保存用户的信息,这个是和cookie最大的区别。不同的客服端在请求的服务器的时候,服务器会为每一个客服端创建一个

    Session对象并保存在服务器端,Session对象是每一个客服端所独有的,相互之间不能访问。服务器为了区别不同的Session属于哪一个客户端,因此Session

    对象也有一个唯一标识,叫做SessionID.而这个SessionID是以cookie的机制保存在客户端浏览器。每次请求的时候,浏览器都会把这个SessionID带回服务端,服务端

    根据这个SessionID就可以找到对应的Session对象

    示例代码:

    public class SessionServlet extends
    HttpServlet{
    @Override
    protected void
    service(HttpServletRequest request,
    HttpServletResponse response)    throws
    ServletException,    IOException    {
    //HttpSession对象是在第⼀次调⽤
    request的getSession()⽅法时才会创建
    //注意: getSession()的⽅法会先判断之
    前是否为客户端创建了session实例,
    //如果创建了,则使⽤之前创建好的
    Session对象,没有则创建⼀个新的Session
    HttpSession session =
    request.getSession();
    //创建HttpSession的同时,会创建⼀个唯
    ⼀的标识SessionID
    //这个sessionId会保存在浏览器的cookie
    中,每次请求会带回这个id找到相应的session对象
    String sessionId = session.getId();
    System.out.println(sessionId);
    }
    }

    Session的生命周期:Session是保存在浏览器的cookie中,但是不会写入cookie文件中,这也就是表示当关闭浏览器之后,Sessionid就会销毁,Sessionid销毁之后,服务端

    的Session就没有如何作用了,但是,服务器并不会立刻销毁这个Session对象,至于什么时候销毁是由服务器自己决定的,除非我们手动调用了Session.invalidate()

    方法,服务器就会立刻销毁这个session实例

    例如:

    HttpSession session = request.getSession();
    //⽴即销毁session
    session.invalidate();

    2、Session默认也有存活时间,服务器创建session的时候,session设置默认的存活时间为30分钟,如果在30分钟之内,

    客户端没有发起任何请求到服务器来到服务器,那么服务器就会销毁这个Session对象,我们也可以设置Session的存活时间,

    可以为当前的Session设置,也可以为全局(服务端所有的Session)的Session设置

    设置当前的Session的超时(存活)时间:

    HttpSession session = request.getSession();
    //设置当前Session的存活时间,单位:秒
    session.setMaxInactiveInterval(3600);

    设置全局的Session存活时间:

    web.xml中进⾏设置 :

    <!--    设置全局Session的存活时间,单位:分钟    -->
    <session-config>
    <session-timeout>60</session-timeout>
    </session-config>

    Session的作用域:

    当我们需要一些数据信息出入Session的时候,就需要操作Session作用域(SessionScope),它和请求作用域类似,也有相应的setAttribute和getAttribute

    的方法,只不过Session作用域的范围要比请求作用域更宽,请求的作用域在一次请求响应之后,就会消失,(因为响应之后请求对象就会销毁)。而Session

    对象只要浏览器不关闭或者Session对象会一直驻留在服务器端,因此不管重新请求多少次还是转发和重定向,都可以重Session中获取之前保存的数据信息

    代码示例:

    User user = new User();
    user.setUid("1001");
    user.setUserName("wangl");
    HttpSession session = request.getSession();
    //将数据保存在会话作⽤域中
    session.setAttribute("user",    user);

    重回复作用域中取值:

    HttpSession session = request.getSession();
    //取值
    User user =
    (Object)session.getAttribute("user");


    URL的重写:

    浏览器是可以禁⽤cookie的,⼀旦禁⽤了cookie,那么SessionId将⽆法写⼊cookie的缓存中,这样就导致⽆
    法实现会话跟踪了,因此解决办法就是使⽤URL重写。URL重写的⽬的就是把SessionId在放在请求URL地址
    的后⾯提交回服务器(类似GET请求后⾯带上参数,⽽这个参数就是⼀个SessionId),服务器会解析这个
    URL的地址并得到SessionId

    代码示例:

    //重写请求的URL地址,这个地址后⾯会⾃动带上
    SessionId
    String url =
    response.encodeRedirectURL("getSession");
    //重定向URL
    response.sendRedirect(url);

    浏览器地址演示:

    http://localhost:8080/ch07/getSession;jsess
    ionid=6F1BA8C92D7E5D7CC479ED8DD30D3ED0

    4.11 Servlet上下文

    web容器在启动时会为每一个web应用创建唯一的上下文对象,这个对象就是Servlet上下文对象(ServletContext),这个上下文对象可以理解为是当前项目的一个共享内存空间,为项目中的所有Servlet提供一个共享的区域。

    常用API:

    getContextPath() 获取项目的相对路径
    getRealPath(String path) 获取项目的绝对路径
    getInitParameter(String name) 获取上下文的初始化参数(web.xml中配置的)
    setAttribute(String name, String value) 将数据放入上下文作用域
    getAttribute(String name) 从上下文作用域中去获取数据

     

     



    上下文作用域:

    上下文作用域是为当前项目所有Servlet提供的一个共享内存区域,可以将需要的数据信息保存在作用域中。这个作用域的的范围是最大的,只要容器没有停止,它就会一直存在。

    三种作用域:

    结合前面所学的作用域,那么一共有三个,分别是:请求作用域,会话作用域,上下文作用域。

    范围从小到大来划分:

    请求作用域>会话作用域>上下文作用域

    4.12 过滤器

    过滤器可以在请求到达servlet之前和servlet响应客户端之前进行拦截,相当于一个拦截器

    主要用于进行一些请求和响应的预处理操作,通常用的场景有限制权限的控制、统一字符编码

    4.12.1编写过滤器

    要实现一个过滤器必须要实现一个Filter接口,只有实现了这个接口的类才称之为过滤器

    示例代码:

    public class DemoFilter implements Filter {
        ...
    }
    web.xml配置过滤器:
    <filter>
          <filter-name>demoFilter</filter-name>
          <filter-class>edu.nf.ch09.filter.DemoFilter</filter-class>
          <!-- 初始化参数 -->
          <init-param>
              <param-name>param</param-name>
              <param-value>hello</param-value>
          </init-param>
      </filter>
      <filter-mapping>
          <filter-name>demoFilter</filter-name>
          <!-- 什么请求可以经过此过滤器,/*表示所有请求 -->
          <url-pattern>/*</url-pattern>
      </filter-mapping>

     4.12.2过滤器的生命周期

    与servlet类似,Filter同样也是容器负责创建和销毁,与servlet的区别在于,容器会在启动的时候最先创建所有

    的顾虑器,并执行init方法进行初始化

    生命周期的方法:

    方法说明
    init 初始化方法,容器启动时执行一次
    doFilter 请求过滤方法,决定请求是否放行
    destroy 容器销毁过滤器之前执行的方法
     
     
     
     
     
     
     
     
     


     
     
     
    实例代码:
    public class DemoFilter implements Filter{
        @Override
        public void destroy() {
            
            System.out.println("准备销毁DemoFilter");
        }
     @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //FilterChain表示一个过滤链对象,因为过滤器可能会存在多个 //同时这个对象将决定是否放行当前请求, //放行的话则请求会继续到达下一个过滤器或者servlet中 System.out.println("请求经过DemoFileer..放行"); chain.doFilter(request, response); System.out.println("响应前经过DemoFilter..."); } @Override public void init(FilterConfig config) throws ServletException { String name = config.getInitParameter("param"); System.out.println("初始化DemoFilter,获取初始化参数:"+name); } }

    4.12.3 过滤链

    在一个web项目中可能存在多个过滤器,当有多个过滤器存在的时候就会形成一个过滤链。请求会按照过滤器链的顺序一直传递下去,最终到达某个Servlet来处理请求。(注意:过滤链的顺序是按照web.xml中的先后配置顺序决定的)

    配置示例:

    <!-- 按先后顺序配置 -->
    <!-- 配置第一个过滤器 -->
    <filter>
        <filter-name>firstFilter</filter-name>
        <filter-class>edu.nf.ch09.filter.FirstFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>firstFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- 配置第二个过滤器-->
    <filter>
        <filter-name>secondFilter</filter-name>
        <filter-class>edu.nf.ch09.filter.SecondFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>secondFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
     

    4.13 监听器

    监听器用于监听对象的上的事件发生,在Servlet中监听器主要监听请求对象、会话对象、上下文对象以及监听这些对象的作用域操作。JavaEE为我们提供了一系列的监听器接口,开发时按需实现相应的接口即可。

    4.13.1 监听作作用域对象的创建与销毁

    监听器说明
    ServletRequestListener 监听请求对象的创建和销毁
    HttpSesisonListener 监听会话对象的创建和销毁
    ServletContextListener 监听Servlet上下文对象的创建和销毁
     
     
     
     
     
     
     
     

     

    1.请求对象监听器

    public class DemoRequestListener implements ServletRequestListener{
    
        /**
         * 当请求对象销毁后容器执行此方法
         * 销毁方法中同样也有一个ServletRequestEvent事件对象
         */
        @Override
        public void requestDestroyed(ServletRequestEvent event) {
            //通过这个事件对象就可以获取当前的请求对象
            HttpServletRequest request = (HttpServletRequest)event.getServletRequest();
            System.out.println("销毁请求对象..."+request);
        }
    /**
         * 当请求对象创建之后容器调用此方法
         * ServletRequestEvent这个参数就是一个事件对象
         */
        @Override
        public void requestInitialized(ServletRequestEvent event) {
            //通过这个事件对象就可以获取当前的请求对象
            HttpServletRequest request = (HttpServletRequest)event.getServletRequest();
            System.out.println("初始化了请求对象..."+request);
        }
    }
     
    web.xml配置
    <!-- 配置监听器 -->
      <listener>
        <!-- 指定监听器的完整类名 -->
      <listener-class>edu.nf.ch10.listener.DemoRequestListener</listener-class>
      </listener>
     
    2、会话监听器
    public class DemoSessionListener implements HttpSessionListener{
    
        /**
         * 监听HttpSession对象的创建
         * HttpSessionEvent参数是一个事件对象
         * 通过它可以获得当前的HttpSession
         */
        @Override
        public void sessionCreated(HttpSessionEvent event) {
            HttpSession session = event.getSession();
    System.out.println("创建了Session对象"+session);
        }
    
        /**
         * 监听HttpSession对象的销毁
         */
        @Override
        public void sessionDestroyed(HttpSessionEvent event) {
            HttpSession session = event.getSession();
            System.out.println("销毁了Session对象"+session);
        }
    }

    注意:当第一次调用了request.getSesison()方法创建Session时,监听器才会起作用。

    web.xml配置

    <listener>
        <!-- 指定监听器的完整类名 -->
          <listener-class>edu.nf.ch10.listener.DemoSessionListener</listener-class>
      </listener>
    3.Servlet上下文监听器
    public class DemoContextListener implements ServletContextListener{
    
        /**
         * 监听ServletContext的销毁
         */
        @Override
        public void contextDestroyed(ServletContextEvent event) {
            //通过事件对象获取ServletContext
            ServletContext sc = event.getServletContext();
            System.out.println("销毁了ServletContext对象..."+sc);
    }
    
        /**
         * 监听SerlvetContext的创建
         */
        @Override
        public void contextInitialized(ServletContextEvent event) {
            //通过事件对象获取ServletContext
            ServletContext sc = event.getServletContext();
            System.out.println("创建了ServletContext对象..."+sc);
        }
    }
    配置web.xml
    <listener>
        <!-- 指定监听器的完整类名 -->
          <listener-class>edu.nf.ch10.listener.DemoContextListener</listener-class>
      </listener>

     4.13.2 监听作用域的操作

    监听器说明
    ServletRequestAttributeListener 监听请求作用域的操作
    HttpSessionAttributeListener 监听会话作用域的操作
    ServletContextAttributeListener 监听Servlet上下文作用域的操作

     

    示例代码:这里以HttpSessionAttributeListener说明,其他作用于监听器用法相似。

    public class DemoSessionAttributeListener implements HttpSessionAttributeListener{
    
        /**
         * 当有数据添加到会话作用域时,执行此方法
         */
        @Override
        public void attributeAdded(HttpSessionBindingEvent event) {
            //获取存入作用域的键和值
            System.out.println("存入会话作用域..."+event.getName() + " : " + event.getValue());
            
        }
    
        /**
         * 当从会话作用域移除数据时,执行此方法
         */
        @Override
        public void attributeRemoved(HttpSessionBindingEvent event) {
            System.out.println("移除会话作用域..."+event.getName() + " : " + event.getValue());
            
        }
    
        /**
         * 当替换了会话作用域中的某个数据时,执行此方法
         */
        @Override
        public void attributeReplaced(HttpSessionBindingEvent event) {
            HttpSession session = event.getSession();
            //从session中获取的是替换之后的值
            System.out.println("替换的值: "+session.getAttribute("userName").toString());
            //注意:这里event.getValue()获取到的是替换之前的值
            System.out.println("替换会话作用域..."+event.getName() + " : " + event.getValue());
        }
    }

     web.xml 配置

    <listener>
        <!-- 指定监听器的完整类名 -->
          <listener-class>edu.nf.ch10.listener.DemoSessionAttributeListener</listener-class>
      </listener>

    4.14 注解配置

    Servlet3.0开始提供了一系列的注解来配置Servlet、Fiilter、Listener等等。这种方式可以极大的简化在开发中大量的xml的配置。

    从这个版本开始,web.xml可以不再需要,使用相关的注解同样可以完成相应的配置。完全配置,

    注解说明
    @WebServlet 这个注解标识在类上,用于配置Servlet。例如:@WebServlet(name="hello", urlPatterns="/hello") 也可简化配置@WebServlet("/hello")
    @WebFilter 这个注解标识在类上,用于配置Filter。例如:@WebFilter(filterName="encode",urlPatterns="/") 也可简化配置@WebFilter("/"),
    @WebListener 这个注解标识在类上,用于配置监听器
     
     
     
     
     
     
     
     
     
     
     
     

    5. JSP基础

    5.1 简介

    JSP全名为java Server Pages,中文名叫java服务器页面,是一种动态页面技术,而HTML是属于静态页面。JSP

    可以在HTML中嵌入java脚本代码,因为JSP本质上还是一个Servlet,因此JSP也必须依赖于web容器才能运行

    JSP的出现并不是为了去掉Servlet,而是简化了Servlet的工作,将Servlet中繁琐的视图呈现代码脱离出来,交给

    JSP来完成,让Servlet专注于请求的处理,所有在开发中通常将jsp和Servlet结合一起使用

    5.2JSP引擎

    由于JSP本质上就是一个Servlet,那么JSP文件转义成一个Servlet的java源文件,然后通过javac将这个源文件编译成class

    字节码文件并装载到JVM中执行,JSP引擎的核心类是JSPServlet,位于Jasper.jar文件张总,并且在Tomcat的web

    .xml中也默认就配置好了这个类(JSPServlet也是一个servlet,因此凡是以“.jsp”结尾的请求都会先经过JSPServlet

    ,那么这个引擎就可以开始工作了。通常引擎转义和编译后的文件放在容器的work工作目录中)

    注意:如果第一次访问jsp文件的时候,由于work目录中并不存在源文件和字节码文件,jsp引擎就必须完成这两个工作,

    因此,有可能在第一次访问jsp时会比较缓慢,当字节码编译出来加载后,第二次访问时的速度就会很快了

    5.3JSP的三大元素

    语法:<%@  %>

    指令说明
    page指令 用于设置JSP页面的相关信息以及编码
    include指令 用于静态包含其他的JSP页面代码,所谓静态包含,就是在编译期,将另外的JSP页面的代码合并到当前的JSP中,最终只会产生一个Java源文件
    taglib指令 这个指令用于引入标签库
     
     
     
     
     
     
     
     
     

    5.3.2 动作元素

    语法:jsp:xxx

    动作说明
    include 动态包含其他JSP页面的内容,所谓的动态包含是指在编译期将不同的JSP文件转义成不同的Java源文件,然后在运行时才将目标内容包含到当前的JSP页面中
    forward 相当于Servlet中的转发,转发到其他的JSP页面或者Servlet
    param 用于传递参数,通常结合其他的动作一起使用,例如转发时需要提交一些而外的参数
    useBean 用于在JSP页面中使用JavaBean对象,通常结合setProperty和getProperty来使用,完成bean对象的赋值和取值操作
     
     
     
     
     
     
     
     





    5.3.3 脚本元素          

    脚本元素主要就是在JSP中嵌入Java脚本代码,包括声明、表达式、Java脚本

    声明语法:<%! %>

    表达式: <%= %>

    Java脚本: <% %>

    代码实例:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
       <%-- 声明变量和方法,这里声明的变量a是实例变量 --%>
       <%!
              int a = 10;
               public void say(){
                   System.out.println("hello");
            }
           %>
           
           <%-- 表达式,注意:表达式后面是不允许有;号结束的 --%>
           3 + 1 = <%=3+1%><br/>
           
           <%-- Java脚本,脚本代码最终会生成在servlet中的service方法中作为代码片段 --%>
           <table border="1">
               <tr>
                 <th>Name</th>
                  <th>Age</th>
               </tr>
               <% for(int i=0;i<5;i++){%>
                 <tr>
                     <td>user<%=i%></td>
                     <td><%=10+i%></td>
                 </tr>
               <%}%>
           </table>
    </body>
    </html>
     

    5.4 JSP内置对象

    内置对象,是在容器运行时将创建好的9个对象内嵌在JSP中,在JSP里可以直接拿来使用的对象

    对象说明
    out 字符流输出对象
    config 等同于Servlet中的ServletConfig
    page 表示当前JSP页面
    request 等同于Servlet中的HttpServletRequest
    response 等同于Servlet中的HttpServletResponse
    session 等同于Servlet中的HttpSession
    application 等同于Servlet中的ServletContext
    pageContext 表示当前JSP页面的上下文对象
    exception 表示当前JSP中的异常对象
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
      <%-- 常用内置对象 --%>
      <%
           //使用request,API使用同HttpServletRequest一样
         request.getParameter("userName");
         request.setAttribute("user", "user1");
         request.getAttribute("user");
         
         //使用session,API使用等同于HttpSession
      session.setAttribute("user", "user2");
         session.getAttribute("user");
         session.getId();
         
         //使用response
         //response.sendRedirect("demo.jsp");
         
         //out对象,等同于字符输出流对象,在JSP页面输出相关内容
         out.println("hello world");
         //这个是输出在控制中
         System.out.println("hello");
      //使用application,等同于ServletContext
         application.setAttribute("userName", "user3");
         
         //pageContext使用
         //从pageContext中获取相关的其他对象
         HttpServletRequest req = (HttpServletRequest)pageContext.getRequest();
         HttpServletResponse res = (HttpServletResponse)pageContext.getResponse();
         HttpSession ses = pageContext.getSession();
         ServletConfig conf = pageContext.getServletConfig();
         ServletContext sc = pageContext.getServletContext();
         //也可以通过pageContext来统一设置不同的作用域
        //第三个参数表示要放入到哪个作用域,是一个int类型的参数
         //1代表page作用域(当前页面有效)
         //2代表请求作用域
         //3代表会话作用域
         //4代表上下文作用域
         pageContext.setAttribute("userName", "zhangsan", 2);
         //也可以指定中哪个作用域取出相应的值
         String name = (String)pageContext.getAttribute("userName", 2);
         out.println(name);
      %>
    </body>
    </html>

    5.5 EL表达式

    EL(Expression Language),全称叫做表达式语言,是JSP2.0推出的一种技术。主要简化了在JSP中使用Java脚本表达式。EL表达式的特点在于使用简单,支持四则运算、逻辑运算等,并且还可以对Servlet API中的对象进行数据访问。EL的语法: ${expression}

    运算:

    示例结果
    ${1+1} 2
    ${2*2} 4
    ${1==1} true
    ${2>5} false
    其他 ...

     



    数据访问:

    1.使用“.”来访问

    示例说明
    ${param.参数名} 获取请求参数的值,相当于使用request.getParameter()方法
    ${requestScope.xxx} 从请求作用域中访问数据
    ${sessionScope.xxx} 从会话作用域中访问数据
    ${applicationScope.xxx} 从上下文作用域中访问数据
    ${xxx} 不指定作用域范围时,默认按照作用域范围从小到大的顺序自动查找
    其他 ...
     
     







    2.使用"[]"来访问
    示例说明
    ${requestScope[“userName”]} 从请求作用域中取值
    ${sessionScope[“userName”]} 从会话作用域取值
    其他... 同上
     
     
     
     
     
     
     
     
     
     


    注意:通常使用"[]"来访问数据的时候,主要是访问一些特殊的名称,例如:request.setAttribute("user.userName")

    这种方式如果使用${requestScope.user.userName}是访问不到的,应该改为

    ${requestScope["user.userName"]}来访问

    5.6 JSTL核心标签库

    JSTL是JSP中的标准标签库,主要用于取代JSP中大量的Java脚本代码,让页面看起来更趋向于HTML。使用也很简单,通常结合EL表达式一起使用

    示例:

    核心标签库(core)说明
    c:out 输出标签
    c:set 声明某个变量并存入指定的作用域
    c:redirect 重定向标签
    c:if 条件判断
    c:forEach 循环标签
    其他 ...
     
     
     
     
     
     
     
     
     
     
     





    备注:其他标签库请参阅相关官方文档
     
     
     
     
     
     

     5.3.

  • 相关阅读:
    【简报】一款使用静态图片生成动画的jQuery插件:JZoopraxiscope
    使用jQuery timelinr和animate.css创建超酷的CSS动画时间轴特效
    超酷信息图分享:你属于哪类geek?
    数据库操作优化
    android R.java aapt
    xml sax 解析 & 符号
    sql server2000 完全卸载
    cmd 命令总结
    手动打包 解释
    bat 执行 java jar包
  • 原文地址:https://www.cnblogs.com/ywbmaster/p/9247033.html
Copyright © 2020-2023  润新知