Java Web随笔

一、Java Web概念

Java Web,是用Java技术来解决相关web互联网领域的技术总和。web包括:web服务器和web客户端两部分。JavaWeb 是基于请求和响应来开发的。

  • 请求:请求是指客户端给服务器发送数据,叫请求 Request。
  • 响应:响应是指服务器给客户端回传数据,叫响应 Response。
  • 关系:请求和响应是成对出现的,有请求就有响应,一次请求对应一次响应。

1.1 Tomcat Web服务器

Tomcat:由 Apache 组织提供的一种 Web 服务器,提供对 jsp 和 Servlet 的支持。它是一种轻量级的 javaWeb 容器(服务 器),也是当前应用最广的 JavaWeb 服务器(免费)。

  1. 安装:

    找到你需要用的 Tomcat 版本对应的 zip 压缩包,解压到需要安装的目录即可。

  2. 目录介绍:

    • bin:专门用来存放 Tomcat 服务器的可执行程序
    • conf:专门用来存放 Tocmat 服务器的配置文件 ,主要配置文件为server.xmlweb.xml
    • lib:专门用来存放 Tomcat 服务器的 jar 包
    • logs:专门用来存放 Tomcat 服务器运行时输出的日志信息
    • temp:专门用来存放 Tomcdat 运行时产生的临时数据
    • webapps:该路径用于自动部署Web应用,将Web应用复制在该路径下,Tomcat会将该应用自动部署在容器中
    • work:是 Tomcat 工作时的目录,用来存放 Tomcat 运行时 jsp 翻译为 Servlet 的源码,和 Session 钝化的目录

二、Servlet

2.1 基本概念

  1. Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
  2. Servlet 是 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
  3. Servlet 是 JavaEE 规范之一。规范就是接口。
  4. Servlet 就是一个接口,定义了java类被浏览器访问到,即被Tomcat所识别的规则,将来我们自定义一个类,实现Servlet接口,复写方法就自定义了一个Servlet服务端的处理小程序。

2.2 基本使用

  1. 创建一个Java EE项目

  2. 自定义一个类实现Servlet接口,并实现接口中的抽象方法

    public class MyServlet 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 {
    
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    
  3. 在web.xml中配置自定义的Servlet的访问路径或初始化的参数配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        
        <servlet>
            <servlet-name>myServlet</servlet-name>
            <servlet-class>com.veo.web.servlet.MyServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>myServlet</servlet-name>
            <!--定义自定义servlet的访问路径-->
            <url-pattern>/myServlet</url-pattern>
        </servlet-mapping>
    </web-app>
    

2.3 执行原理

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

2.4 生命周期

  1. 被创建:执行 Servlet构造器方法、执行init方法,只执行一次,默认情况下第一次被访问时,servlet被创建,也可以配置Servlet的创建时机:
    • 第一次被访问时创建:的值为负数,默认值为-1
    • 在服务器启动时创建:的值为0或正整数
    • Servlet的init方法只执行一次,说明Servlet在内存中只存在一个对象,servlet是单例的(可能有线程安全问题)
  2. 提供服务:执行service方法,执行多次,每次访问Servlet时,service方法都会被调用一次
  3. 被销毁:执行destroy方法,只执行一次,Servlet被销毁时执行,服务器关闭时,Servlet被销毁,只有服务器正常关闭时,才会执行destroy方法,destroy方法在Servlet被销毁之前执行,一般用于释放资源

2.5 体系结构

  • Servlet接口
    • GenericServlet抽象类:将Servlet接口中其他的方法做了默认空实现,只将service()方法作了抽象,将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
    • HttpServlet抽象类:对http协议的一种封装,简化操作
image-20210826161850956

2.6 ServletConfig和ServletContext类

2.6.1 ServletCongfig类

Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。 Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对象,是Servlet 程序的配置信息类,主要用于获取Servlet的配置信息。

  1. 可以获取 Servlet 程序的别名 servlet-name 的值
  2. 获取初始化参数 init-param
  3. 获取 ServletContext 对象

web.xml配置:

<!-- servlet 标签给 Tomcat 配置 Servlet 程序 -->
<servlet>
    <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) -->
    <servlet-name>HelloServlet</servlet-name>
    <!--servlet-class 是 Servlet 程序的全类名-->
    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
    <!--init-param 是初始化参数-->
    <init-param>
        <!--参数名-->
        <param-name>username</param-name>
        <!--参数值-->
        <param-value>root</param-value>
    </init-param>
    <!--init-param 是初始化参数-->
    <init-param>
        <!--参数名-->
        <param-name>url</param-name>
        <!--参数值-->
        <param-value>jdbc:mysql://localhost:3306/test</param-value>
    </init-param>
</servlet>	
<!--servlet-mapping 标签给 servlet 程序配置访问地址-->
<servlet-mapping>
<!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个 Servlet 程序使用-->
    <servlet-name>HelloServlet</servlet-name>	
    <!--
    url-pattern 标签配置访问地址 <br/>
    / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径 <br/>
    /hello 表示地址为:http://ip:port/工程路径/hello <br/>
    -->
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

Servlet中:

@Override
public void init(ServletConfig servletConfig) throws ServletException {
	super.init(servletConfig);
    System.out.println("2 init 初始化方法");
    // 1、可以获取 Servlet 程序的别名 servlet-name 的值
    System.out.println("HelloServlet 程序的别名是:" + servletConfig.getServletName());
    // 2、获取初始化参数 init-param
    System.out.println("初始化参数 username 的值是;" + servletConfig.getInitParameter("username"));
    System.out.println("初始化参数 url 的值是;" + servletConfig.getInitParameter("url"));
    // 3、获取 ServletContext 对象
    System.out.println(servletConfig.getServletContext());
}	
2.6.2 ServletContext类

定义:

  1. ServletContext 是一个接口,它表示 Servlet 上下文对象,代表整个Web应用。
  2. 一个 web 工程,只有一个 ServletContext 对象实例。
  3. ServletContext 对象是一个域对象。
  4. ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。

常用方法:

  • public String getInitParameter(String name):获取名称为name的系统范围内的初始化参数值,系统范围内的初始化参数可以在部署描述符中使用元素定义。
  • public void setAttribute(String name, Object object):设置名称为name的属性。
  • public Object getAttribute(String name):获取名称为name的属性。
  • public void removeAttribute(String name):移除名为name的属性。
  • public String getRealPath(String path):返回参数所代表目录的真实路径。
  • public void log(String message):记录一般日志信息。
  • public String getRealPath(String path):获取文件的真实(服务器)路径。

作用:

  1. 获取 web.xml 中配置的上下文参数 context-param
  2. 获取当前的工程路径,格式: /工程路径
  3. 获取工程部署后在服务器硬盘上的绝对路径
  4. 像 Map 一样存取数

web.xml配置

<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
    <param-name>username</param-name>	
    <param-value>context</param-value>
</context-param>			
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
    <param-name>password</param-name>
    <param-value>root</param-value>
</context-param>

ContextServlet1代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
    // 1、获取 web.xml 中配置的上下文参数 context-param
    ServletContext context = getServletConfig().getServletContext();
    String username = context.getInitParameter("username");
    System.out.println("context-param 参数 username 的值是:" + username);
    System.out.println("context-param 参数 password 的值是:" +
    context.getInitParameter("password"));
    
    // 2、获取当前的工程路径,格式: /工程路
    System.out.println( "当前工程路径:" + context.getContextPath() );
    
    // 3、获取工程部署后在服务器硬盘上的绝对路径
    /**
    * / 斜杠被服务器解析地址为:http://ip:port/工程名/ 映射到 IDEA 代码的 web 目录<br/>
    */
    System.out.println("工程部署的路径是:" + context.getRealPath("/"));
    System.out.println("工程下 css 目录的绝对路径是:" + context.getRealPath("/css"));
    System.out.println("工程下 imgs 目录 1.jpg 的绝对路径是:" + context.getRealPath("/imgs/1.jpg"));
    
    System.out.println(context);
    System.out.println("保存之前: Context1 获取 key1 的值是:"+ context.getAttribute("key1"));
    context.setAttribute("key1", "value1");
    System.out.println("Context1 中获取域数据 key1 的值是:"+ context.getAttribute("key1"));	
}	

三、Http协议

**概念:**Hyper Text Transfer Protocol超文本传输协议,定义了客户端和服务器端通信时,发送数据的格式。

特点:

  1. 基于TCP/IP的高级协议
  2. 默认端口号:80
  3. 基于请求/响应模型:一次请求对应一次响应
  4. 无状态:每次请求之前相互独立,不能交互数据

版本:

  • 1.0:每一次请求响应都会建立新的连接
  • 1.1:复用连接

3.1 请求消息数据格式

  1. 请求行:
    • 组成:请求方式、请求url、请求协议/版本,如:GET /login.html HTTP/1.1。
    • 请求方式:HTTP协议有7中请求方式,常用的有2种。
      • GET:1.请求参数在请求行中,在url后、2.请求的url长度有限值、3.不安全。
      • POST:1. 请求参数在请求体中、2.请求的url长度没有限值、3.相对安全。
  2. 请求头:
    • 格式:请求头名称:请求头值
    • 常见的请求头:
      • User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息,可以在服务器端获取该头的信息,解决浏览器的兼容性问题。
      • Referer:http://localhost/login.html:告诉服务器,我(当前请求)从哪里来作用:防盗链、统计工作。
      • Accept:表示客户端可以接收的数据类型。
      • Accpet-Languege::表示客户端可以接收的语言类型。
      • Host: 表示请求时的服务器 ip 和端口号。
  3. 请求空行:
    • 用于分割post请求的请求头和请求体。
  4. 请求体:
    • 封装post请求消息的请求参数的

请求体格式:

GET /login.html HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer:http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1

Username=zhangsan

3.2 响应体消息数据格式

  1. 响应行:
    • 组成:协议/版本 响应状态码 状态码描述,如:HTTP/1.1 200 OK
    • 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态状态码都是3位数字
      • 1XX: 服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1××多的状态码
      • 2XX:成功。代表:200
      • 3XX:重定向。代表:302(重定向),304(访问缓存)
      • 4XX:客户端错误。代表:404(请求路径没有对应的资源),405(请求方式对应的do××方法)
      • 5XX:服务器端错误。代表:500(服务器内部出现异常)
  2. 响应头:
    • 格式:头名称:值
    • 常见响应头:
      • Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
      • Content-Disposition:服务器告诉客户端以什么格式打开响应体数据值,1.in-line:默认值,在当前页面内打开,2.Attachment;filename=xxx:以附件形式打开响应体。文件下载
  3. 响应空行:
  4. 响应体:传输的数据

响应体数据格式:

HTTP/1.1 200 OK
date: Sun, 12 Jan 2021 15:28:01 GMT
content-type: text/css
content-encoding: gzip
etag: W/"5df1fc22-61ff"
last-modified: Thu, 12 Dec 2021 08:36:50 GMT
expires: Sun, 19 Jan 2021 05:56:05 GMT
age: 103038
accept-ranges: bytes
cache-control: max-age=2592000
vary: Accept-Encoding
ohc-response-time: 1 0 0 0 0 0
ohc-cache-hit: fzcm64 [4], yangzcmcache92 [4]
X-Firefox-Spdy: h2

<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  hello,response
  </body>
</html>

四、Request对象

Request和response对象的原理:

  1. request和response对象是由服务器创建的,我们来使用它们
  2. request对象是来获取请求消息,response对象是来设置响应消息
  3. 每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的 信息

继承体系:

  • ServletRequest接口
    • HttpServletRequest接口:继承ServletRequest接口
    • HttpServletRequestWrapper类:实现HttpServletRequest接口
image-20210826190546844

4.1 常用方法

获取请求消息:

  1. String getMethod():获取请求方式。
  2. String getContextPath():获取虚拟目录。
  3. String getServletPath():获取servlet路径。
  4. String getQueryString():获取get方式请求参数。
  5. String getRequestURI():获取统一资源标识符(小),URI从虚拟目录开始获取。
  6. StringBuffer getRequestURL():获取统一资源定位符(大),URL从协议开始获取。
  7. String getProtocal():获取协议及版本。
  8. String getRemoteAddr():获取客户机的IP地址。

获取请求头数据:

  1. String getHeader(String name):通过请求头名称获取请求头的值。
  2. Enumeration getHeaderNames():获取所有的请求头名称。

获取请求体数据:

  1. 请求体:只有post请求方式才有请求体,在请求体中封装了post请求的请求参数。
  2. BufferedReader getReader():获取字符输入流,只能操作字符数据。
  3. ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据。

获取请求参数:

  1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来
  2. String getParameter(String name):根据参数名称获取参数值。
  3. String[ ] getParameterValues(String name):根据参数名称获取参数值的数组。
  4. Enumeration getParameterNames():获取所有请求的参数名称。
  5. Map<String,String[ ]> getParameterMap():获取所有参数的map集合。

4.2 中文乱码解决

  • Get方式:tomcat8已经将get方式乱码问题解决了。
    • 获取进行字符串的转码:
    • String username = request.getParameter(“username”);
    • username = new String(username.getBytes(“iso-8859-1”), “UTF-8”);
  • Post方式:会乱码
    • 解决:在获取参数前,设置request的编码
    • request.setCharacterEncoding(“utf-8”);

4.3 请求转发

一种在服务器内部的资源跳转方式

实现:

  1. 通过request对象获取请求转发器对象:RequestDispatcher dis = request.getRequestDispatcher(String)
  2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request,ServletResponse response)

特点:

  • 浏览器地址栏路径不发生变化
  • 只能转发到当前服务器内部资源中
  • 转发是一次请求
  • 他们共享Request域中的数据
  • 不可以访问工程以外的资源

共享数据:

域对象:一个有作用范围的对象,可以在范围内共享数据

Request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据,常用方法如下:

  • void setAttribute(String name,Object obj):存储数据
  • object getAttribute(String name):通过键获取值
  • void removeAttribute(String name):通过键移除键值对
  • ServletContext getServletContext():获取ServletContext

五、Response对象

5.1 常用方法

主要设置响应的消息,常用方法如下:

  1. setStatus(int sc):设置状态码
  2. setHeader(String name,String value):设置响应头
  3. 设置响应体,先获取输出流,在调用输出流的方法将数据输出到客户端,获取输出流方法如下:
    • 字符输出流:PrintWriter getWriter()
    • 字节输出流:ServletOutputStream getOutputStream()
    • 注意字符数据乱码问题:
    • PrintWriter pw = response.getWriter();获取流的默认编码是ISO-8859-1
    • 设置该流的默认编码,告诉浏览器响应体使用的编码
    • response.setContentType(“text/html;charset=utf-8”);
5.2 重定向

资源跳转的一种方式,实现方式:

  1. 设置响应头方式

    //1.设置状态码为302
    response.setStatus(302);
    
    //2.设置响应头location
    response.setHeader("location","/responseDemo2");
    
  2. response.sendRedirect("/responseDemo2");

特点:

  • 地址栏发生变化
  • 重定向可以访问其他站点(服务器)的资源
  • 重定向是两次请求,不可以使用request对象来共享数据
5.3 转发和重定向特点小结
  1. 重定向的特点:redirect

    • 地址栏发生变化
    • 重定向可以访问其他站点(服务器)的资源
    • 重定向是两次请求,不可以使用request对象来共享数据
    • /代表当前Web站点的根目录
  2. 转发的特点:forward

  • 转发地址栏路径不变
  • 转发只能访问当前服务器下的资源
  • 转发是一次请求,可以使用request对象来共享数据
  • /代表相对于当前WEB应用程序的根目录

六、会话技术

**定义:**一次会话中包含多次请求和响应,当浏览器第一次给服务器资源发送请求,会话就建立了,直到有一方断开为止,在一次会话中可以在多次请求间共享数据。

方式:

  1. 客户端会话技术:Cookie
  2. 服务器端会话技术:Session
6.1 Cookie

定义:

  1. 客户端会话技术,将数据保存到客户端。
  2. Cookie 是服务器通知客户端保存键值对的一种技术。
  3. 客户端有了 Cookie 后,每次请求都发送给服务器。
  4. 每个 Cookie 的大小不能超过 4kb

Cookie的创建和使用:

  1. 服务器端创建Cookie :new Cookie(String name,String value);
  2. 发送Cookie对象:response.addCookie(Cookie cookie)
  3. 获取Cookie,拿到数据:Cookie[ ] request.getCookies()
Cookie cookie = new Cookie("key4", "value4");
//2 通知客户端保存 Cookie
response.addCookie(cookie);
//1 创建 Cookie 对象
Cookie cookie1 = new Cookie("key5", "value5");
//2 通知客户端保存 Cookie
response.addCookie(cookie1);
response.getWriter().write("Cookie 创建成功");

Cookie细节:

  1. 一次可不可以发送多个cookie?可以

    • 可以创建多个cookie对象,使用response调用多次addCookie方法发送cookie即可
  2. Cookie在浏览器中保存多长时间?

    • 默认情况下,当浏览器关闭后,Cookie数据被销毁
    • 持久化存储:setMaxAge(int seconds)
      • 正数:将cookie数据写到硬盘的文件中,持久化存储,cookie存活时间
      • 负数:默认值
      • 零:删除cookie信息
  3. Cookie能不能存中文?

  • 在tomcat8之前,cookie中不能直接存储中文数据,需要将中文数据转码,一般采用url编码(%E3)
  • 在tomcat8之后,cookie支持中文数据。特殊字符还是不支持,建议使用url编码存储,url解码解析
  1. Cookie共享问题?

    • 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?

      • 默认情况下cookie不能共享
      • SetPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
      • 如果要共享,则可以将path设置为 /
    • 不同的tomcat服务器间cookie共享问题?

      • SetDomain(String path):如果设置一级域名相同,那么多个服务器之间的cookie可以共享

      • SetDomain(”.baidu.com”),那么tieba.baidu.com和news.baidu.com中

        cookie可以共享

Cookie的特点和作用:

  • cookie存储数据在客户端浏览器
  • 浏览器对于单个cookie的大小有限制(4kb)以及对同一个域名下的总cookie数量也有限制(20个)

作用:

  • Cookie一般用于存在少量的不太敏感的数据在不登录的情况下,完成服务器对客户端的身份识别
6.2 Session

定义:

服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession。

具体实现与生命周期:

  1. 从一个客户打开浏览器并连接到服务器开始,一直到这个客户关闭浏览器为一个回话。
  2. 当客户第一次连接到服务器请求时会为这个客户分配一个session对象,并为这个对象分配一个id。
  3. session信息保存在容器中,sessionID保存在客户机的cookie中,所以 session的实现是依赖于cookie的。
  4. 当服务器发出回复内容的同时将这个id发往客户段,并写入到客户端的cookie中,这样下次再请求的时候,服务器就可以通过该id来识别不同的用户。

session的获取与使用:

  1. 获取:HttpSession session=request.getSession();
  2. 使用:
    • Object getAttribute(String name):取值
    • void setAttribute(String name,Object value):存值
    • void removeAttribute(String name):删除值

细节:

  1. 当客户端关闭后, 服务器不关闭,两次获取吗session是否为同一个?默认情况下,不是

    • 如果需要相同,则可以创建cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存

    • Cookie c=new Cookie("JSESSIONID",session.getId());
      c.setMaxAge(60*60);
      response.addCookie(c);
      
  2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?不是同一个,但是要确保数据不丢失

  • Session的钝化:在服务器正常关闭之前,将session对象系列化到硬盘上
  • Session的活化:在服务器启动后,将session文件转化为内存中的sesion对象
  1. Session什么时候被销毁?

    • a) 服务器关闭

    • Session对象调用invalidate()

    • Session默认失效时间30分钟,可以自定义时间

      • 
        <session-config>
        	<session-timgout>30</session-timeout>
        </session-config>
        

    Session特点:

    1. Session用于存储一次会话的多次请求的数据,存在服务器端
    2. Session可以存储任意类型,任意大小的数据

    Session与cookie的区别:

    • Session存储数据在服务器端,cookie在客户端
    • Session没有数据大小限制,cookie有
    • Session数据安全,cookie相对于不安全

七、Jsp

概念:

Java Server Pages:java服务器端页面,一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码,可以简化书写,jsp本质上就是一个Servlet。

7.1 Jsp的执行过程

Web容器处理JSP文件请求需要经过3个阶段:

  1. 翻译阶段:JSP文件会被Web容器中的JSP引擎转换成Java源码(存放在Tomcat目录下的work文件夹中)。
  2. 编译阶段:Java源码会被编译成可执行的字节码(存放在Tomcat目录下的work文件夹中)。
  3. 执行阶段:容器接受了客户端的请求后,执行编译成字节码的JSP文件;处理完请求后,容器把生成的HTML或XHTML页面(一定是HTML或XHTML页面)反馈给客户端进行显示 。
  4. 第一次请求之后,Web容器可以重用已经编译好的字节码文件,如果对JSP文件进行了修改,Web容器会重新对JSP文件进行翻译和编译。

7.2 Jsp页面构成

image-20210827154818314
7.2.1 Jsp脚本元素
  • <%代码%>:代码脚本,可以在 jsp 页面中,编写我们自己需要的功能(写的是 java 语句)。
    • 代码脚本翻译之后都在_jspService() 方法中,为局部变量。
    • 代码脚本由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用。
    • 还可以由多个代码脚本块组合完成一个完整的 java 语句。
    • 代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据。
  • <%!代码%>:声明脚本,可以给 jsp 翻译出来的 java 类定义属性和方法甚至是静态代码块,内部类等。
    • 定义的变量为类的成员变量,可以全局使用。
    • 定义的方法为成员方法,可以全局使用。
  • <%=代码%>:表达式脚本,定义的java代码,会输出到页面上。
    • 所有的表达式脚本都会被翻译到_jspService()方法中 。
    • 表达式脚本都会被翻译成为 out.print()输出到页面上 。
    • 由于表达式脚本翻译的内容都在_jspService()方法中,所以_jspService()方法中的对象都可以直接使用。
    • 表达式脚本中的表达式不能以分号结束。
7.2.2 Jsp页面注释
  1. html注释
    • <!-- 这是 html 注释 -->
    • html 注释会被翻译到 java 源代码中。在_jspService 方法里,以 out.writer 输出到客户。
  2. java注释
    • //:单行 java 注释
    • /**/: 多行 java 注释
    • java 注释会被翻译到 java 源代码中。
  3. Jsp 注释
    • <%-- 这是 jsp 注释 --%>
    • jsp 注释可以注掉,jsp 页面中所有代码,并且在查看页面源码时看不见注释的内容。
7.2.3 Jsp指令元素
image-20210827160657613
7.2.3.1 Page指令

用于设置JSP页面的属性和相关的功能。 page指令作用整个JSP页面,可以在JSP文档的任意地方定义,不过一般我们定义在JSP文件的顶端。

语法格式:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

常用属性值:

  • contentType:设置响应体的mime类型以及字符集,设置当前jsp页面的编码,同于response.setContentType()。
  • Import:导包。
  • ErrorPage:当前页面发生异常后,会自动跳转到指定的错误页面。
  • IsErrorPage:标识当前页面是否是错误页面。
    • True:是,可以使用内置对象exception
    • False:否,默认值,不可以使用内置对象exception
7.2.3.2 Include指令

在JSP编译时,插入一个包含文本或代码的文件,这个包含的过程是静态的,而包含的文件可以是JSP网页、HTML网页、文本文件,或是一段Java程序,为静态包含。

语法格式:

<%@ include file="list.jsp"%>

动作指令动态包含:

<jsp:include page="/include/footer.jsp">
    <jsp:param name="username" value="bbj"/>
    <jsp:param name="password" value="root"/>
</jsp:include>	

静态包含与动态包含的区别:

  1. <jsp:include>是动态包含,而<%@ include%>是静态包含。
  2. <jsp:include page=“file” flush=“true” />它总是会检查所含文件中的变化。
  3. 动态包含可以给被包含的页面传递参数,静态包含不可以。
  4. 动态包含的地址可以是变量,静态不可以为一个变量。
  5. 静态包含,会将包含的文件与文件一起编译为一个java文件,不能出现同名的变量名,动态包含,会分两次编译包含的文件,两个文件相互独立,可以有同名的变量名。
7.3.3.3 taglib指令

允许引入用户定义的标签,完成JSP的开发。

**语法格式:**prfix为自定义的前缀,uri为引用的地址。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
7.2.4 九大内置对象
变量名真实类型作用
pageContextPageContext当前页面共享数据 还可以获取其他八个内置对象
requestHttpServletRequest一次请求访问的多个资源(转发)
sessionHttpSession一次会话的多个请求
applicationServletContext所有用户间共享数据
responseHttpServletResponse响应对象
pageObject当前页面servlet的对象 this的引用
outJspWriter输出对象,数据输出到页面上
configServletConfigServlet的配置对象
exceptionThrowable异常对象

在JSP中从小到大分为以下四个作用域

  1. page作用域:它的有效范围只在当前jsp页面里。
  2. request作用域:它的有效范围是当前请求周期。
  3. session作用域:它的有效范围是当前会话。
  4. application作用域:它的有效范围是整个应用。

八、El表达式

Express Language:表达式语言,替换和简化Jsp页面中java代码的编码,能够自动转换类型, El得到某个数据时可以自动转换类型 。

格式: ${表达式}

jsp中默认支持el表达式,可以通过如下方式禁用el表达式:

  • 设置jsp中page指令中:isELIgnored=“true” 忽略当前jsp页面中所有el表达式
  • \${表达式}:忽略当前这个el表达式

使用:

  • 运算符:+ - * /(div) %(mod)
  • 比较运算法:> < >= <= == ``!=
  • 逻辑运算符:&&(and) ||(or) !(not)
  • 空运算法:empty
    • 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
    • ${empty list}:表示判断字符串、集合、数组对象是否为null,并且长度=0
    • ${not empty str}:表示判断字符串、集合、数组对象是否不为null,并且长度>0

取值:

El表达式只能从域对象中获取值,顺序为从小到大的域对象获取:

  1. pageScope --> pageContext
  2. RequestScope --> request
  3. sessionScope --> session
  4. applicationScope --> application(ServletContext)

获取:${requestScope.name}

${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止

获取对象、List集合、Map集合的值:

  • 对象:${域名称.键名.属性名},本质上会去调用对象的getter方法
  • List集合:${域名称.键名[索引]}
  • Map集合:${域名称.键名.key名称} 或 ${域名称.键名[“key名称”]}

隐式对象

el表达式中有11个隐式对象

pageContext:获取jsp其他八个内置对象

${pageContext.request.contextPath}:动态获取虚拟目录

九、JSTl标签

JavaServer Pages Tag Library :JSP标准标签库,是由Apache组织提供的开源的免费的jsp标签。

使用方式:

  1. 导入jstl相关的jar包
  2. 引入标签库:taglib指令:<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>,然后在页面中使用。

常用的标签库:

JSTL前缀名称URI范例
核心标签库chttp://java.sun.com/jsp/jstl/core<c:out>
I18N格式标签库fmthttp://java.sun.com/jsp/jstl/fmt<fmt:formatDate>
SQL标签库sqlhttp://java.sun.com/jsp/jstl/sql<sql:query>
XML标签库xmlhttp://java.sun.com/jsp/jstl/xml<xml:forBach>
函数标签库fnhttp://java.sun.com/jsp/jstl/functions<fn:split>

常用的核心标签库:

  1. If:相当于java代码的if语句
    • 属性:test 必须属性,接收boolean表达式
    • 如果表达式为true,则显示if标签体内容;如果表达式为false,则不显示标签体内容
    • 一般情况下,test属性值会结合el表达式一起使用
    • 注意:c:if标签没有else情况,想要else情况,则可以再定义一个c:if标签
  2. Choose:相当于java代码的switch语句
  • 使用choose标签取出数字,相当于switch声明
  • 使用when标签做数字判断,相当于case
  • otherwise标签做其他情况的声明,相当于default
  1. Foreach:相当于java代码的for语句
  • items:被迭代的集合对象
  • var:用来存放迭代得到的成员
  • begin:开始的位置
  • end:结束的位置
  • step:步长
  • varStatus:用来存放现在指到得相关成员信息
  1. formatDate:格式化标签,它允许页面对日期进行格式化操作
    • value:要格式化的对象
    • type:格式的类型
    • pattern:自定义格式化类型

使用案例:


  <c:if test="${page.currentPage > 1}">
        <li class="page-item">
          <a class="page-link" href="/findAllByPage?currentPage=${page.currentPage - 1}&pageSize=${page.pageSize}&bookid=${conditions.bookid[0]}&bookname=${conditions.bookname[0]}&bookauthor=${conditions.bookauthor[0]}&startNum=${conditions.startNum[0]}&endNum=${conditions.endNum[0]}&startPrice=${conditions.startPrice[0]}&endPrice=${conditions.endPrice[0]}" tabindex="-1" aria-disabled="true">上一页</a>
        </li>
      </c:if>

      <c:forEach var="p" begin="1" end="${page.totalPages}" varStatus="index">
        <c:choose>
          <c:when test="${page.currentPage == index.count}">
            <li class="page-item active" aria-current="page">
              <a class="page-link" href="/findAllByPage?currentPage=${index.count}&pageSize=${page.pageSize}&bookid=${conditions.bookid[0]}&bookname=${conditions.bookname[0]}&bookauthor=${conditions.bookauthor[0]}&startNum=${conditions.startNum[0]}&endNum=${conditions.endNum[0]}&startPrice=${conditions.startPrice[0]}&endPrice=${conditions.endPrice[0]}">${index.count}</a>
            </li>
          </c:when>
          <c:otherwise>
            <li class="page-item"><a class="page-link" href="/findAllByPage?currentPage=${index.count}&pageSize=${page.pageSize}&bookid=${conditions.bookid[0]}&bookname=${conditions.bookname[0]}&bookauthor=${conditions.bookauthor[0]}&startNum=${conditions.startNum[0]}&endNum=${conditions.endNum[0]}&startPrice=${conditions.startPrice[0]}&endPrice=${conditions.endPrice[0]}">${index.count}</a></li>
          </c:otherwise>
        </c:choose>
      </c:forEach>
      <c:if test="${page.currentPage < page.totalPages}">
        <li class="page-item">
          <a class="page-link" href="/findAllByPage?currentPage=${page.currentPage + 1}&pageSize=${page.pageSize}&bookid=${conditions.bookid[0]}&bookname=${conditions.bookname[0]}&bookauthor=${conditions.bookauthor[0]}&startNum=${conditions.startNum[0]}&endNum=${conditions.endNum[0]}&startPrice=${conditions.startPrice[0]}&endPrice=${conditions.endPrice[0]}">下一页</a>
        </li>
      </c:if>
      当前第${page.currentPage}页,共${page.totalPages}页,共${page.totalCount}条记录



          
          
<c:forEach varStatus="s" items="${page.list}" var="book">
    <tr>
      <td>${s.count}</td>
      <td>${book.bookname}</td>
      <td>${book.booknum}</td>
      <td>${book.bookprice}</td>
      <td>${book.bookauthor}</td>
      <td><fmt:formatDate value="${book.bookpublish}" pattern="yyyy-MM-dd"/></td>
      <td>${book.typename}</td>
      <td>
        <a href="/updateBookServlet?currentPage=${page.currentPage - 1}&pageSize=${page.pageSize}&id=${book.bookid}">修改</a>
        &nbsp;&nbsp;
        <a href="${book.bookid}">删除</a>
      </td>
    </tr>
  </c:forEach>

十、过滤器

过滤器是一个服务器端的组件,它可以截取用户端的请求与响应信息,并对这些信息进行过滤,当需要限制用户访问某些资源或者在处理请求时提前处理某些资源的时候,就可以使用过滤器完成。例如:实现URL级别的访问权限控制、过滤敏感词汇、统一POST方式请求编码等一些业务处理 。

image-20210827171741963

基本使用:

  1. 新建一个java类,实现Filter接口,有三个方法,分别如下

    • Init():这是过滤器的初始化方法,web容器创建过滤器实例后将调用这个方法,这个方法可以读取web.xml文件中过滤器的参数。
    • doFilter():这个方法完成实际的过滤操作,是过滤器的核心方法,当用户请求访问与过滤器关联的URL 匹配时,web容器将先调用过滤器的doFilter方法,FilterChain参数可以调用chain.doFilter方法,将请求传给下一个过滤器(或目标资源),或利用转发,重定向将请求转发到其他资源。
    • Destory():web容器在销毁过滤器实例前调用该方法,在这个方法中可以释放过滤器占有的资源(大多数情况用不到)
  2. 配置web.xml文件

    <filter>
        <filter-name>loginFilter</filter-name>
        <filter-class>com.db.util.myFilter</filter-class>
        <init-param>
            <param-name>msg</param-name>
            <param-value>FilterParamValue</param-value>
        </init-param>
    </filter> 
    <filter-mapping>
    	<filter-name>loginFilter</filter-name>
    	<url-pattern>/*</url-pattern>
    </filter-mapping>
    

过滤器生命周期:

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

拦截路径配置

  • 具体资源路径:/index.jsp 只有访问index.jsp资源时,过滤器才会被执行
  • 拦截目录:/user/* 访问/user下的所有资源时,过滤器都会被执行
  • 后缀名拦截:*.jsp 访问所有后缀名为jsp资源资源时,过滤器都会被执行
  • 拦截所有资源:/* 访问所有资源时,过滤器都会被执行

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

  • 注解配置,设置dispatcherTypes属性
  • Request:默认值。浏览器直接请求资源
  • Forward:转发访问资源
  • Include:包含访问资源
  • Error:错误跳转资源
  • Async:异步访问资源
  • Web.xml配置
  • 设置<dispatcher></dispatcher>标签即可

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

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

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

过滤器先后顺序

  • 注解配置:按照类型的字符串比较规则比较,值小的先执行
  • Web.xml配置:<filter-mapping>谁定义在上边,谁先执行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值