JavaWeb


笔记可参考链接:https://www.yuque.com/csy/ykokl4/gg7vty

互联网通信

一、关于系统架构

C/S结构

优点:
1.速度快,体验好,界面炫酷(大量的数据都是集成在客户端软件当中,所以服务器只需要传送很少的数据量)
2.服务器压力小(大量的数据都是集成在客户端软件当中,所以服务器只需要传送很少的数据量)
3.安全(大量的数据都是集成在客户端软件当中,数据在多个客户端上有缓存)

缺点:
升级维护比较差劲(每一个客户端都需要升级)

B/S架构

优点:
升级维护方便,成本比较低。(只需要升级服务器端即可。)
不需要安装特定的客户端软件,只需要打开浏览器,输入网址即可。
缺点:
速度慢(因为所有的数据都是在服务器上,用户发送的每一个请求都是需要服务器全身心的响应数据)
不安全

二、 B/S结构的系统通信原理

2.1域名

https://www.baidu.com/(网站),www.baidu.com 是一个域名
在浏览器地址栏上输入域名,回车之后,域名解析器会将域名解析出来一个具体的IP地址端口号等。
解析结果也许是:http://110.242.68.3:80/index.html

IP地址: 一台主机的身份证号
端口号: 一个软件

2.2一个WEB系统的通信原理?

● 第一步:用户输入网址(URL)
● 域名解析器进行域名解析:110.242.68.3:80/index.html
● 浏览器软件在网络中搜索并找到110.242.68.3这一台主机
● 该台主机定位到80端口对应的服务器软件
● 80端口对应的服务器软件得知浏览器想要的资源名是:index.html
● 服务器软件找到index.html文件,并且将index.html文件中的内容直接输出响应到浏览器上。
● 浏览器接收并执行到来自服务器的代码(HTML CSS JS)
请添加图片描述
在这里插入图片描述

在这里插入图片描述

2.3模拟Servlet的本质

● 充当SUN公司的角色,制定Servlet规范
○ javax.servlet.Servlet接口

● 充当Webapp的开发者
○ BankServlet implements Servlet
○ UserListServlet implements Servlet
○ UserLoginServlet implements Servlet

● 充当Tomcat服务器的开发者

package javax.servlet;
/*
    我们现在充当的角色是SUN公司,
    SUN公司把Servlet接口/规范制定出来了
 */
public interface Servlet {

    //一个专门提供服务的方法.
    void service();
}
package com.bjpowernode.servlet;

import javax.servlet.Servlet;
public class BankServlet implements Servlet {

    @Override
    public void service() {
        System.out.println("BankServlet is servce...");
    }
}
package com.bjpowernode.servlet;

import javax.servlet.Servlet;
public class UserListServlet implements Servlet {

    @Override
    public void service() {
        System.out.println("UserListServlet is servce...");
    }
}

package com.bjpowernode.servlet;

import javax.servlet.Servlet;
public class UserLoginServlet  implements Servlet {

    @Override
    public void service() {
        System.out.println("UserLoginServlet is servce...");
    }
}

package org.apache;


import java.util.Scanner;
import java.util.Properties;
import java.io.FileReader;
import javax.servlet.Servlet;

// 充当Tomcat服务器的开发者
public class Tomcat{
    public static void main(String[] args) throws Exception{
        System.out.println("Tomcat服务器启动成功,开始接收用户的访问。");

        // 简单的使用Scanner来模拟一下用户的请求
        // 用户访问服务器是通过浏览器上的“请求路径”
        // 也就是说用户请求路径不同,后台执行的Servlet不同。
		/*
			/userList    UserListServlet
			/login		 UserLoginServlet
			/bank		 BankServlet
			......
		*/
        System.out.print("请输入您的访问路径:");
        Scanner s = new Scanner(System.in);

        // 用户的请求路径  /bbbb
        String key = s.nextLine(); // Tomcat服务器已经获取到了用户的请求路径了。

        // Tomcat服务器应该通过用户的请求路径找对应的XXXServlet
        // 请求路径和XXXServlet之间的关系应该由谁指定呢?
        // 对于Tomcat服务器来说需要解析配置文件

        /*    ResourceBundle bundle = ResourceBundle.getBundle("web.properties");
                String className=bundle.getString(提示key:"key");    */



        FileReader reader = new FileReader("web.properties");
        Properties pro = new Properties();
        pro.load(reader);
        reader.close();

        // 通过key获取value
        String className = pro.getProperty(key);
        // 通过反射机制创建对象
        Class clazz = Class.forName(className);
        Object obj = clazz.newInstance(); // obj的类型对于Tomcat服务器开发人员来说不知道。

        // 但是Tomcat服务器的开发者知道,你写的XXXXServlet一定实现了Servlet接口
        Servlet servlet = (Servlet)obj;
        servlet.service();

    }
}

注意:
这个配置文件的文件名不能乱来。固定的。
这个配置文件的存放路径不能乱来。固定的。
servlet规范中规定了:
一个合格的webapp应该是一个怎样的目录结构。
一个合格的webapp应该有一个怎样的配置文件。
一个合格的webapp配置文件路径放在哪里。
一个合格的webapp中java程序放在哪里。
这些都是Servlet规范中规定的。
Tomcat服务器要遵循Servlet规范。JavaWEB程序员也要遵循这个Servlet规范。这样Tomcat服务器和webapp才能解耦合。

2.4开发一个带有Servlet(Java小程序)的webapp(重点)

在这里插入图片描述

第一步:在webapps下建立文件夹

webapproot
|------WEB-INF
|------classes(存放字节码)
|------lib(第三方jar包)
|------web.xml(注册Servlet)
|------前端内容
注意:
1.webapproot()为你的项目名字
2.classes存放的是Java程序编译之后的class文件
3.web.xml内容为

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                      https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
  version="5.0"
  metadata-complete="true">

	<!--servlet描述信息-->
	<!--任何一个servlet都对应一个servlet-mapping -->
	<servlet>
		<servlet-name>HelloServlet</servlet-name>
		<!--这个位置必须是带有包名的全限定类名-->
		<servlet-class>com.bjpowernode.servlet.HelloServlet</servlet-class>
	</servlet>

	<!--servlet映射信息-->
	<servlet-mapping>
		<!--这个也是随便的,不过这里写的内容要和上面的一样。-->
		<servlet-name>HelloServlet</servlet-name>
		<!--这里需要一个路径-->
		<!--这个路径唯一的要求是必须以 / 开始-->
		<!--当前这个路径可以随便写-->
		<url-pattern>/HelloServlet.index</url-pattern>
	</servlet-mapping>
	
</web-app>

第三步:编写并编译一个java程序(必须实现Servlet接口)

java源代码你愿意在哪里就在哪里,位置无所谓,你只需要将java源代码编译之后的class文件放到classes目录下即可。

package com.bjpowernode.servlet;

import jakarta.servlet.Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.ServletConfig;
import java.io.IOException;
import java.io.PrintWriter;


public class HelloServlet implements Servlet{

	// 5个方法
	public void init(ServletConfig config) throws ServletException{
	
	}

	public void service(ServletRequest request,ServletResponse response)
		throws ServletException , IOException{

		// 向控制台打印输出
		System.out.println("My First Servlet, Hello Servlet");

		// 设置响应的内容类型是普通文本或html代码
		// 需要在获取流对象之前设置,有效。
		response.setContentType("text/html");

		// 怎么将一个信息直接输出到浏览器上?
		// 需要使用ServletResponse接口:response
		// response表示响应:从服务器向浏览器发送数据叫做响应。
		PrintWriter out = response.getWriter();
		
		out.print("Hello Servlet, You are my first servlet!");

		// 浏览器是能够识别html代码的,那我们是不是应该输出一段HTML代码呢?
		out.print("<h1>hello servlet,你好Servlet</h1>");

		// 这是一个输出流,负责输出字符串到浏览器
		// 这个输出流不需要我们刷新,也不需要我们关闭,这些都由Tomcat来维护。
		/*
		out.flush();
		out.close();
		*/
	}

	public void destroy(){
	
	}

	public String getServletInfo(){
		return "";
	}

	public ServletConfig getServletConfig(){
		return null;
	}
}

将以上编译之后的HelloServlet.class文件拷贝到WEB-INF\classes目录下。

第四步:在浏览器输入网址

启动tomcat服务器: startup.bat
关闭tomcat服务器:stop.bat
在这里插入图片描述

2.5使用集成工具IDEA开发一个带有Servlet(java小程序)的web

第一步:基础搭建
1.创建一个新工程
2.创建一个新模块
2.1模块右击---->Add Framework Support…(添加框架支持)------>选择Web Application
(一个符合Servlet规范的webpp目录结构。)

第二步:编写Servlet
1.编写Servlet
1.1这个时候发现Servlet.class文件没有。怎么办?
File --> Project Structrue --> Modules---->Dependeencies—>添加Library或者JAR
2.实现jakarta.servlet.Servlet接口中的5个方法。
3.在Servlet当中的service方法中编写业务代码(我们这里连接数据库了。)
4.在WEB-INF目录下新建了一个子目录:lib 并且将连接数据库的驱动jar包放到lib目录下。

package com.javaweb.servlet;

import jakarta.servlet.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.*;

public class StudentServlet implements Servlet {


    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

    @Override
    public void service(ServletRequest Request, ServletResponse Response) throws ServletException, IOException {
        //设置响应的内容类型
        Response.setContentType("text/html");
        PrintWriter out=Response.getWriter();
        //连接数据库(JDBC)
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet res=null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            String url="jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
            String username="root";
            String password="123456";

            conn=DriverManager.getConnection(url,username,password);
            String sql="select id,name from users";

            ps=conn.prepareStatement(sql);

            res=ps.executeQuery();
            while(res.next()){
                int id=res.getInt("id");
                String name=res.getString("name");
                out.print(id+","+name+"<br>");
                System.out.println("11111");
            }

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally {
            if(res!=null){
                try {
                    res.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(ps!=null){
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

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

    @Override
    public void destroy() {

    }
}

第三步:在web.xml文件中完成StudentServlet类的注册

<?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>studentServlet</servlet-name>
        <servlet-class>com.javaweb.servlet.StudentServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>studentServlet</servlet-name>
        <url-pattern>/servlet/student</url-pattern>
    </servlet-mapping>
</web-app>

第四步:给一个html页面,在HTML页面中编写一个超链接

  • student.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>student page</title>
</head>
<body>
    <!--这里的项目名是 /xmm,无法动态获取,先写死-->
    <a href="/xmm/servlet/student">student list</a>
</body>
</html>

第五步:让IDEA工具去关联Tomcat服务器。
1.Add Configuration
2.左上角加号,点击Tomcat Server --> local
3.Deployment(点击这个用来部署webapp),继续点击加号,部署即可。修改 Application context为:/xmm

第六步:启动tom服务器,浏览器输入地址
打开浏览器,在浏览器地址栏上输入:http://localhost:8080/xmm/student.html

注意:前端发送请求要加项目名

三、servlet对象的生命周期

3.1 servlet生命周期

在这里插入图片描述

在这里插入图片描述
研究:默认情况下,服务器在启动的时候Servlet对象并不会被实例化。
这个设计是合理的。用户没有发送请求之前,如果提前创建出来所有的Servlet对象,必然是耗费内存的,并且创建出来的Servlet如果一直没有用户访问,显然这个Servlet对象是一个废物,没必要先创建。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 Servlet适配器

GenericServlet
在这里插入图片描述

package com.javaweb.servlet;

import jakarta.servlet.*;

import java.io.IOException;

/**
 * 编写一个标准通用的Servlet,起名: GenericServlet
 * 以后所有的Servlet类都不要直接实现Servlet接口了。
 * 以后所有的Servlet类都要继承GenericServlet类。
 * GenericServlet就是一个适配器
 */
public abstract class GenericServlet implements Servlet {
    //成员变量
    private ServletConfig config;

    /**
     *init方法中的ServletConfig对象是小猫咪创建好的。
     * 这个ServletConfig对象目前在init方法的参数上,属于局部变量。
     * 那么ServletConfig对象肯定以后要在service方法中使用,怎么才能保iServletConfig对象(在iservice方法中能够使用呢?
     */
    @Override
    public final void init(ServletConfig config) throws ServletException {
        this.config=config;
        //调用init()方法
        init();
    }

    /**
     * 这个init方法是供子类重写的。
     */
    public void init(){

    }

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

    /**
     * 抽象方法,这个方法最常用,所有子类必须实现service方法
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException;

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

    @Override
    public void destroy() {

    }
}


package com.javaweb.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import java.io.IOException;

public class LoginServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("正在登陆中....");
    }
}

3.3 ServletConfig

package com.javaweb.servlet;

import jakarta.servlet.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

/**
 *ServletConfig
 *  1. ServletConfig是什么?
 *      jakarta.servlet.ServletConfig
 *      显然ServletConfig Servlet规范中的一员。
 *      ServletConfig是一个接口。(jakarta.servlet.Servlet是一个接口)
 *  2.谁去实现了这个接口呢?
 *      public class org.apache.catalina.core.StandardWrapperFacade implements ServletConfig{}
 *      结论:Tomcat服务器实现了ServletConfig接口
 *      思考:如果把Tomcat服务器换成jetty服务器,输出ServletConfig对象的时候,还是这个结果吗?
 *           不一定一样,包名类名可能和Tomcat不一样。但是他们都实现了ServletConfig这个规范。
 *  3,一个Servlet对象中有一个ServletConfig对象。(Servlet 和iServletConfig对象是一对一。>
 *      100个Servlet,就应该有100个ServletConfig对象。
 *  4. ServletConfig对象是谁创建的?在什么时候创建的?
 *      Tomcat服务器(WEB服务器)创建了ServletConfig对象。
 *      在创建Servlet对象的时候,同时创建lServletConfig对象。
 *  5. ServletConfig接口到底是干啥的?有什么用呢?
 *      Config是哪个单词的缩写?
 *          configuration
 *      ServletConfig对象被翻译为:Servlet对象的配置信息对象。
 *  6. ServletConfig对象中到底包装了什么信息呢?
 *      <servlet>
 *         <servlet-name>configTest</servlet-name>
 *         <servlet-class>com.javaweb.servlet.ConfigTestServlet</servlet-class>
 *     </servlet>
 *     ServletConfig对象中包装的信息是:
 *     web .xml文件中<servlet></servlet>标签的配置信息。
 *
 *     Tomcat小猫咪解析web.xml文件,将web.xml文件中<servlet></servlet>标签中的配置信息自动包装到ServletConfig 对象中 。
 *  7. ServletConfig有哪些方法?
 *      getServletConfig()
 *      getInitParameterNames()
 *      getInitParameter(java.lang.string name)
 *      第1个方法:
 *          public String getInitParameter(String name);
 *      第2个方法:
 *          public Enumeration<String> getInitParameterNames();
 *      第3个方法:
 *          public ServletContext getServletContext();
 *      第4个方法;
 *          public String getServletName()
 *      以上的4个方法,在自己编写的Servlet类当中也可以使用this 去调用。(这个Servlet继承了GenericServlet)
 */

public class ConfigTestServlet extends GenericServlet {
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out=response.getWriter();

        //获取ServletConfig对象
        ServletConfig config=this.getServletConfig();
        //输出该对象
        //org.apache.catalina.core.StandardWrapperFacade@640259a9
        out.print("ServletConfig对象: "+config);
        out.print("<br>");

        //获取<servlet-name></servlet-name>
        String servletName = config.getServletName();
        out.print("<servlet-name>"+servletName+"</servlet-name>");
        out.print("<br>");

        //通过ServletConfig对象的两个方法,可以获取到web.xml文件中的初始化参数配置信息。
        //java.util.Enumeration<java.lang.string>getInitParameterNames()

        //获取所有的初始化参数的name
        Enumeration<String> initParameterNames = config.getInitParameterNames();
        while (initParameterNames.hasMoreElements()){
            String parameterName = initParameterNames.nextElement();
            String parameterValue = config.getInitParameter(parameterName);
            out.print(parameterName+"="+ parameterValue);
            out.print("<br>");
        }


        //获取所有的初始化参数的值 value
        /*//java.lang.String getInitParameter(java.lang.string name)
        String driver = config.getInitParameter("driver");
        out.print(driver);*/

        //实际上获取一个Servlet对象的初始化参数,可以不用获取ServletConfig对象。直接通过this也可以。
        Enumeration<String> names = this.getInitParameterNames();
        while (names.hasMoreElements()){
            String name = names.nextElement();
            String value = this.getInitParameter(name);
            System.out.println(name + "=" + value);
        }

        //怎么获取ServletContext对象呢?
        //通过ServletConfig对象获取ServletContext对象。
        ServletContext application = config.getServletContext();
        out.print("<br>"+application);

        //第二种方式:通过this也可以获取ServletContext对象。
        ServletContext application2 = this.getServletContext();
        out.print("<br>"+application2);

    }
}

<?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>configTest</servlet-name>
        <servlet-class>com.javaweb.servlet.ConfigTestServlet</servlet-class>
        <!--这里是可以配置一个Servlet对象的初始化信息的。-->
        <init-param>
            <param-name>driver</param-name>
            <param-value>com.mysql.cj.jdbc.Driver</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>cjdbc:mysql://localhost:3306/jdbcStudy</param-value>
        </init-param>
        <init-param>
            <param-name>user</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>123456</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>configTest</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>configTest2</servlet-name>
        <servlet-class>com.javaweb.servlet.ConfigTestServlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>configTest2</servlet-name>
        <url-pattern>/test2</url-pattern>
    </servlet-mapping>

</web-app>

3.4 ServletContext

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
缓存机制:

在这里插入图片描述
在这里插入图片描述

四.Http协议

HTTP协议:是W3C制定的一种超文本传输协议。(通信协议:发送消息的模板提前被制定好。)

HTTP协议包括:

  • 请求协议
    浏览器 向 WEB服务器发送数据的时候,这个发送的数据需要遵循一套标准,这套标准中规定了发送的数据具体格式。
  • 响应协议
    WEB服务器 向 浏览器发送数据的时候,这个发送的数据需要遵循一套标准,这套标准中规定了发送的数据具体格式。

1.HTTP的请求协议(B --> S)

详细参考链接:https://www.yuque.com/csy/ykokl4/uufokl#TaTl9

○ HTTP的请求协议包括:4部分

  • 请求行
  • 请求头
  • 空白行
  • 请求体

○ HTTP请求协议的具体报文:GET请求

  • 请求行
  • 请求头
  • 空白行
  • 请求体

2.HTTP的响应协议(S --> B)

3.GET和POST有什么区别?

到目前为止,只有一种情况可以发送POST请求:使用form表单,并且form标签中的method属性值为:method=“post”。在这里插入图片描述

五.HttpServlet

在这里插入图片描述
● 我们编写的HelloServlet直接继承HttpServlet,直接重写HttpServlet类中的service()方法行吗?
○ 可以,只不过你享受不到405错误。享受不到HTTP协议专属的东西。
● 到今天我们终于得到了最终的一个Servlet类的开发步骤:
○ 第一步:编写一个Servlet类,直接继承HttpServlet
○ 第二步:重写doGet方法或者重写doPost方法,到底重写谁,javaweb程序员说了算。
○ 第三步:将Servlet类配置到web.xml文件当中。
○ 第四步:准备前端的页面(form表单),form表单中指定请求路径即可。

欢迎资源文件

● 动态资源:Servlet类。
○ 步骤:
■ 第一步:写一个Servlet

public class WelcomeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.print("<h1>welcome come!!</h1>");
    }
}

第二步:在web.xml文件中配置servlet

<servlet>
        <servlet-name>welcomeServlet</servlet-name>
        <servlet-class>com.javaweb.servlet.WelcomeServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>welcomeServlet</servlet-name>
        <url-pattern>/aaa</url-pattern>
    </servlet-mapping>

第三步:在web.xml文件中配置欢迎页

 <!-- 配置欢迎页-->
    <welcome-file-list>
        <welcome-file>aaa</welcome-file>
    </welcome-file-list>

关于WEB-INF目录

● 在WEB-INF目录下新建了一个文件:welcome.html
● 打开浏览器访问:http://localhost:8080/servlet07/WEB-INF/welcome.html 出现了404错误。
● 注意:放在WEB-INF目录下的资源是受保护的。在浏览器上不能够通过路径直接访问。所以像HTML、CSS、JS、image等静态资源一定要放到WEB-INF目录之外。

六.HttpServletRequest接口详解

● HttpServletRequest是一个接口,全限定名称:jakarta.servlet.http.HttpServletRequest
● HttpServletRequest对象中都有什么信息?都包装了什么信息?

○ HttpServletRequest对象是Tomcat服务器负责创建的。这个对象中封装了什么信息?封装了HTTP的请求协议。
○ 实际上是用户发送请求的时候,遵循了HTTP协议,发送的是HTTP的请求协议,Tomcat服务器将HTTP协议中的信息以及数据全部解析出来,然后Tomcat服务器把这些信息封装到HttpServletRequest对象当中,传给了我们javaweb程序员。
○ javaweb程序员面向HttpServletRequest接口编程,调用方法就可以获取到请求的信息了。

● request和response对象的生命周期?
○ request对象和response对象,一个是请求对象,一个是响应对象。这两个对象只在当前请求中有效。
○ 一次请求对应一个request。
○ 两次请求则对应两个request。

6.1 常用方法

获取用户提交的数据

怎么获取前端浏览器用户提交的数据?

Map<String,String[]> getParameterMap() 这个是获取Map
Enumeration<String> getParameterNames() 这个是获取Map集合中所有的key
String[] getParameterValues(String name) 根据key获取Map集合的value
String getParameter(String name)  获取value这个一维数组当中的第一个元素。这个方法最常用。
// 以上的4个方法,和获取用户提交的数据有关系。
Map<String,String>
    key存储String
    value存储String
    这种想法对吗?不对。
    如果采用以上的数据结构存储会发现key重复的时候value覆盖。
    key         value
    ---------------------
    username    abc
    userpwd     111
    aihao       s
    aihao       d
    aihao       tt
    这样是不行的,因为map的key不能重复。
Map<String, String[]>
    key存储String
    value存储String[]
    key				value
    -------------------------------
    username		{"abc"}
    userpwd			{"111"}
    aihao			{"s","d","tt"}

注意:前端表单提交数据的时候,假设提交了120这样的“数字”,其实是以字符串"120"的方式提交的,所以服务器端获取到的一定是一个字符串的"120",而不是一个数字。(前端永远提交的是字符串,后端获取的也永远是字符串。)

四个方法的使用

package com.javaweb.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class RequestTestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.print(request);
        out.print("<br>");
        out.print("RequestTestServlet test....");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        /*4.获取参数Map集合*/
        Map<String, String[]> parameterMap = request.getParameterMap();
        // 遍历Map集合(获取Map集合中所有的key,遍历)
        Set<String> keys = parameterMap.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()){
            String key = it.next();
            System.out.print(key+"=");
            String[] values = parameterMap.get(key);
            for (String value:values) {
                System.out.print(value+",");
            }
            System.out.println();
        }

        /*3.直接通过getParameterNames()这个方法,可以直接获取这个Map集合的所有key*/
        Enumeration<String> names = request.getParameterNames();
        while(names.hasMoreElements()){
            String name = names.nextElement();
            System.out.println(name);
        }

        /*2.既然是checkbox,调用方法:request.getParameterValues("interest")*/
        String[] usernames = request.getParameterValues("username");
        String[] userpwds = request.getParameterValues("userpwd");
        String[] aihaos = request.getParameterValues("aihao");
        for (String username:usernames) {
            System.out.println(username);
        }
        for (String userpwd:userpwds) {
            System.out.println(userpwd);
        }
        for (String aihao:aihaos) {
            System.out.println(aihao);
        }

        /*1.最常用的方式
         通过name获取value这个一维数组的第一个元素
        String getParameter(String name)*/

        String username = request.getParameter("username");
        String userpwd = request.getParameter("userpwd");
        System.out.println(username);
        System.out.println(userpwd);
        
    }
}

请求域对象request

在这里插入图片描述
请求域”对象要比“应用域”对象范围小很多。生命周期短很多。请求域只在一次请求内有效。
一个请求对象request对应一个请求域对象。一次请求结束之后,这个请求域就销毁了。

请求域对象也有这三个方法:

// 存(怎么向request请求域中存数据)
public void setAttribute(String name, Object value); // map.put(k, v)
// 取(怎么从request请求域中取数据)
public Object getAttribute(String name); // Object v = map.get(k)
// 删(怎么删除request请求域中的数据)
public void removeAttribute(String name); // map.remove(k)

● 请求域和应用域的选用原则?
尽量使用小的域对象,因为小的域对象占用的资源较少。

两个Servlet怎么共享数据?
● 将数据放到ServletContext应用域当中,当然是可以的,但是应用域范围太大,占用资源太多。不建议使用。
● 可以将数据放到request域当中,然后AServlet转发到BServlet,保证AServlet和BServlet在同一次请求当中,这样就可以做到两个Servlet,或者多个Servlet共享同一份数据。

请求转发
1.原理: 是由WEB服务器来控制的。A资源跳转到B资源,这个跳转动作是Tomcat服务器内部完成的。

	// 第一步:获取请求转发器对象
	RequestDispatcher dispatcher = request.getRequestDispatcher("/b");
	// 第二步:调用转发器的forward方法完成跳转/转发
	dispatcher.forward(request,response);
            
	// 第一步和第二步代码可以联合在一起。
	 request.getRequestDispatcher("/b").forward(request,response);
	
//注意:转发的时候是一次请求,会将当前的request和response对象传递给下一个servlet.
         

● 转发的下一个资源必须是一个Servlet吗?

  • 不一定,只要是Tomcat服务器当中的合法资源,都是可以转发的。例如:html…
  • 注意:转发的时候,路径的写法要注意,转发的路径以“/”开始,不加项目名

关于request对象中两个非常容易混淆的方法:

    // uri?username=zhangsan&userpwd=123&sex=1
    String username = request.getParameter("username");

    // 之前一定是执行过:request.setAttribute("name", new Object())
    Object obj = request.getAttribute("name");

    // 以上两个方法的区别是什么?
    // 第一个方法:获取的是用户在浏览器上提交的数据。
    // 第二个方法:获取的是请求域当中绑定的数据。

HttpServletRequest接口的其他常用方法:

	// 获取客户端的IP地址
	String remoteAddr = request.getRemoteAddr();
	
	// get请求在请求行上提交数据。
	// post请求在请求体中提交数据。
	// 设置请求体的字符集。(显然这个方法是处理POST请求的乱码问题。这种方式并不能解决get请求的乱码问题。)
	// Tomcat10之后,request请求体当中的字符集默认就是UTF-8,不需要设置字符集,不会出现乱码问题。
	// Tomcat9前(包括9在内),如果前端请求体提交的是中文,后端获取之后出现乱码,怎么解决这个乱码?执行以下代码。
	request.setCharacterEncoding("UTF-8");
	
	// 在Tomcat9之前(包括9),响应中文也是有乱码的,怎么解决这个响应的乱码?
	response.setContentType("text/html;charset=UTF-8");
	// 在Tomcat10之后,包括10在内,响应中文的时候就不在出现乱码问题了。以上代码就不需要设置UTF-8了。
	
	// 注意一个细节
	// 在Tomcat10包括10在内之后的版本,中文将不再出现乱码。(这也体现了中文地位的提升。)
	
	// get请求乱码问题怎么解决?
	// get请求发送的时候,数据是在请求行上提交的,不是在请求体当中提交的。
	// get请求乱码怎么解决
	// 方案:修改CATALINA_HOME/conf/server.xml配置文件
	  <Connector URIEncoding="UTF-8" />
    // 注意:从Tomcat8之后,URIEncoding的默认值就是UTF-8,所以GET请求也没有乱码问题了。

    // 获取应用的根路径
    String contextPath = request.getContextPath();

	// 获取请求方式
	String method = request.getMethod();
	
	// 获取请求的URI
	String uri = request.getRequestURI();  // /aaa/testRequest
	
	// 获取servlet path
	String servletPath = request.getServletPath(); //   /testRequest

在一个web应用中如何完成资源的跳转

在一个web应用中通过两种方式,可以完成资源的跳转:

  • 第一种方式:转发
  • 第二种方式:重定向

在这里插入图片描述
转发:
在这里插入图片描述
转发:
在这里插入图片描述
重定向:

在这里插入图片描述
转发和重定向区别:
转发和重定向应该如何选择?什么时候使用转发,什么时候使用重定向?

● 如果在上一个Servlet当中向request域当中绑定了数据,希望从下一个Servlet当中把request域里面的数据取出来,使用转发机制。

● 剩下所有的请求均使用重定向。(重定向使用较多。)
● 他俩跳转的资源只要是服务器内部合法的资源即可。(Servlet,JSP,HTML)…
● 转发会存在浏览器刷新问题

Servlet注解

在这里插入图片描述

package com.javawvb.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

@WebServlet(name="hello",
        urlPatterns = {"/hello1","/hello2","/hello3"},
        //loadOnStartup = 1,
initParams = {@WebInitParam(name ="username",value = "root"),@WebInitParam(name = "password",value = "123")})
public class HelloServlet extends HttpServlet {

    public HelloServlet() {
        System.out.println("无参数构造方法执行");

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        //获取Servlet Name
        String servletName = getServletName();
        out.print("servlet name= "+servletName+"<br>");

        //获取Servlet Name
        String contextPath = request.getContextPath();
        out.print("servlet path= "+contextPath+"<br>");

        //获取初始化参数
        Enumeration<String> names = getInitParameterNames();
        while (names.hasMoreElements()){
            String name = names.nextElement();
            String value = getInitParameter(name);
            out.print(name+"="+value+"<br>");
        }

    }
}

// @WebServlet(urlPatterns = { " /welcome1","/welcome2"3)
// 注意:当注解的属性是一个数组,并且数组中只有一个元素,大括号可以省略。
// @WebServlet(urlPatterns = "/welcome ")
//这个value属性和urlPatterns属性一致,都是用来指定Servlet的映射路径的。
// @WebServlet(value = {" /welcome1","/welcome2"})
//如果注解的属性名是value的话,属性名也是可以省略的。
//@WebServlet(value = " /welcome1")
@WebServlet("/welcome")
public class WelcomeServlet extends HttpServlet {}

七.JSP

7.1 概念

在这里插入图片描述

7.2 JSP的语法

1.在jsp文件中直接编写文字会被翻译到servlet类的service方法的out.write(“翻译到这里”),直接翻译到双引号里,被java程序当做普通字符串打印输出到浏览器。
(在JSP中编写的HTML CSS JS代码,这些代码对于JSP来说只是一个普通的字符串。但是JSP把这个普通的字符串一旦输出到浏览器,浏览器就会对HTML CSS JS进行解释执行。展现一个效果.)
2.在JSP中编写java程序

<% java语句; %>
//向浏览器上输出一个java变量。
<% String name = “jack”;  
out.write("name = " + name); %>

● 在这个符号当中编写的被视为java程序,被翻译到Servlet类的service方法内部。
● 在service方法当中编写的代码是有顺序的,方法体当中的代码要遵循自上而下的顺序依次逐行执行。
● service方法当中不能写静态代码块,不能写方法,不能定义成员变量。。。。。。
● 在同一个JSP当中 <%%> 这个符号可以出现多个。
● 注意:以上代码中的out是JSP的** **。可以直接拿来用。当然,必须只能在service方法内部使用。

<%! %> 在这个符号当中编写的java程序会自动翻译到service方法之外

<%--在这个符号当中编写的java程序会自动翻译到service方法之外。--%>
<%!
    //成员变量
   private String name="jackson";
    //静态代码块
   static {
       System.out.println("静态代码块执行!");
   }
    //方法
   public static void m1(){
       System.out.println("m1 method execute!");
   }
%>

这个语法很少用,为什么?不建议使用,因为在service方法外面写静态变量和实例变量,都会存在线程安全问题,ISP就是servlet,servlet是单例的,多线程并发的环境下,这个静态变量和实例变量一旦有修改操作,必然会存在全问题。

<%= %> 这个符号会被翻译到哪里?最终翻译成什么?
● 翻译成了这个java代码: out.print();
翻译到service方法当中了。
什么时候使用<%=%>输出呢?输出的内容中含有java的变量,输出的内容是一个动态的内容,不是一个死的字符串。如果输出的是一个固定的字符串,直接在JSP文件中编写即可。

3.在JSP中如何编写JSP的专业注释

<!--这种注释属于HTML的注释,这个注释信息仍然会被翻译到java源代码当中,不建议。-->
<%--JSP的专业注释,不会被翻译到java源代码当中。--%>
<%--注释
    int i;
--%>

JSP基础语法总结:
在这里插入图片描述
在这里插入图片描述

7.3 session和cookie

关于B/S结构系统的session机制

● 什么是会话?
○ 用户打开浏览器,进行一系列操作,然后最终将浏览器关闭,这个整个过程叫做:一次会话。会话在服务器端也有一个对应的java对象,这个java对象叫做:session。
○ 什么是一次请求:用户在浏览器上点击了一下,然后到页面停下来,可以粗略认为是一次请求。请求对应的服务器端的java对象是:request。
一个会话当中包含多次请求。(一次会话对应N次请求。)

● 在java的servlet规范当中,session对应的类名:HttpSession(jarkata.servlet.http.HttpSession)
● session机制属于B/S结构的一部分。如果使用php语言开发WEB项目,同样也是有session这种机制的。session机制实际上是一个规范。然后不同的语言对这种会话机制都有实现。
● session对象最主要的作用是:保存会话状态。(用户登录成功了,这是一种登录成功的状态,你怎么把登录成功的状态一直保存下来呢?使用session对象可以保留会话状态。)
● 为什么需要session对象来保存会话状态呢?
  ○ 因为HTTP协议是一种无状态协议。
  ○ 什么是无状态:请求的时候,B和S是连接的,但是请求结束之后,连接就断了。为什么要这么做?HTTP协议为什么要设计成这样?因为这样的无状态协议,可以降低服务器的压力。请求的瞬间是连接的,请求结束之后,连接断开,这样服务器压力小。
  ○ 只要B和S断开了,那么关闭浏览器这个动作,服务器知道吗?
    ■ 不知道。服务器是不知道浏览器关闭的。
● 为什么不使用request对象保存会话状态?为什么不使用ServletContext对象保存会话状态?
  ○ request.setAttribute()存,request.getAttribute()取,ServletContext也有这个方法。request是请求域。ServletContext是应用域。
  ○ request是一次请求一个对象。
  ○ ServletContext对象是服务器启动的时候创建,服务器关闭的时候销毁,这个ServletContext对象只有一个。
  ○ ServletContext对象的域太大。
  ○ request请求域(HttpServletRequest)、session会话域(HttpSession)、application域(ServletContext)
  ○ request < session < application

session的实现原理:
● JSESSIONID=xxxxxx 这个是以Cookie的形式保存在浏览器的内存中的。浏览器只要关闭。这个cookie就没有了。
● session列表是一个Map,map的key是sessionid,map的value是session对象。
● 用户第一次请求,服务器生成session对象,同时生成id,将id发送给浏览器。
● 用户第二次请求,自动将浏览器内存中的id发送给服务器,服务器根据id查找session对象。
● 关闭浏览器,内存消失,cookie消失,sessionid消失,会话等同于结束
请添加图片描述
● Cookie禁用了,session还能找到吗?
○ cookie禁用是什么意思?服务器正常发送cookie给浏览器,但是浏览器不要了。拒收了。并不是服务器不发了。
○ 找不到了。每一次请求都会获取到新的session对象。
○ cookie禁用了,session机制还能实现吗?
■ 可以。需要使用URL重写机制。
■http://localhost:8080/servlet12/test/session;jsessionid=19D1C99560DCBF84839FA43D58F56E16
■ URL重写机制会提高开发者的成本。开发人员在编写任何请求路径的时候,后面都要添加一个sessionid,给开发带来了很大的难度,很大的成本。所以大部分的网站都是这样设计的:你要是禁用cookie,你就别用了。
在这里插入图片描述
销毁session对象:session.invalidate();

Cookie

session的实现原理中,每一个session对象都会关联一个sessionid,例如:

  • JSESSIONID=41C481F0224664BDB28E95081D23D5B8
  • 以上的这个键值对数据其实就是cookie对象。
  • 对于session关联的cookie来说,这个cookie是被保存在浏览器的“运行内存”当中。
  • 只要浏览器不关闭,用户再次发送请求的时候,会自动将运行内存中的cookie发送给服务器。
  • 例如JSESSIONID=41C481F0224664BDB28E95081D23D5B8就会再次发送给服务器。
  • 服务器就是根据41C481F0224664BDB28E95081D23D5B8这个值来找到对应的session对象的
    在这里插入图片描述
    ● cookie机制和session机制其实都不属于java中的机制,实际上cookie机制和session机制都是HTTP协议的一部分。php开发中也有cookie和session机制,只要是你是做web开发,不管是什么编程语言,cookie和session机制都是需要的。
    ● HTTP协议中规定:任何一个cookie都是由name和value组成的。name和value都是字符串类型的。
    ● 在java的servlet中,对cookie提供了哪些支持呢?
    ○ 提供了一个Cookie类来专门表示cookie数据。jakarta.servlet.http.Cookie;
    ○ java程序怎么把cookie数据发送给浏览器呢?response.addCookie(cookie);
    ● 在HTTP协议中是这样规定的:当浏览器发送请求的时候,会自动携带该path下的cookie数据给服务器。(URL。)
    在这里插入图片描述
@WebServlet("/cookie/generate")
public class GenerateCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //创建Cookie对象
        Cookie cookie = new Cookie("productid","123");
        Cookie cookie1 = new Cookie("username", "zhangsan");

        //设置cookie在一小时之后失效。(保存在硬盘文件中)
        //cookie.setMaxAge(60*60);

        //设置cookie的有效期为0,表示该cookie被删除。主要应用在:使用这种方式删除浏/览器上的同名cookie。
        //cookie.setMaxAge(0);

        //设置cookie的有效期<0,表示该cookie不会被存储。(表示不会被存储到硬盘文件中。会放在浏览器运行内存当中。)
        cookie.setMaxAge(-1); //和不调用sexMaxAge是同一个效果。
        cookie1.setMaxAge(-1);

        //默认情况下,没有设置path的时候,cookie关联的路径是什么?
        //手动设置路径
        cookie.setPath("/Servlet11");
        cookie1.setPath(request.getContextPath());

        //将cookie响应到浏览器
        response.addCookie(cookie);
        response.addCookie(cookie1);
    }
}

浏览器发送cookie给服务器了,服务器中的java程序怎么接收?

Cookie[] cookies = request.getCookies(); // 这个方法可能返回null
if(cookies != null){
    for(Cookie cookie : cookies){
        // 获取cookie的name
        String name = cookie.getName();
        // 获取cookie的value
        String value = cookie.getValue();
    }
}

7.4 JSP指令

JSP的指令
● 指令的作用:指导JSP的翻译引擎如何工作(指导当前的JSP翻译引擎如何翻译JSP文件。)
● 指令包括哪些呢?
include指令:包含指令,在JSP中完成静态包含,很少用了。(这里不讲)
○ taglib指令:引入标签库的指令。这个到JJSTL标签库的时候再学习。现在先不管。
page指令:目前重点学习一个page指令。
● 指令的使用语法是什么?
○ <%@指令名 属性名=属性值 属性名=属性值 属性名=属性值…%>
● 关于page指令当中都有哪些常用的属性呢?

<%@page session="true|false" %>
true表示启用JSP的内置对象session,表示一定启动session对象。没有session对象会创建。
如果没有设置,默认值就是session="true"
session="false" 表示不启用内置对象session。当前JSP页面中无法使用内置对象session。
<%@page contentType="text/json" %>
contentType属性用来设置响应的内容类型
但同时也可以设置字符集。
<%@page contentType="text/json;charset=UTF-8" %>
<%@page import="java.util.List, java.util.Date, java.util.ArrayList" %>
<%@page import="java.util.*" %>
import语句,导包。
<%@page errorPage="/error.jsp" %>
当前页面出现异常之后,跳转到error.jsp页面。
errorPage属性用来指定出错之后的跳转位置。
<%@page isErrorPage="true" %>
表示启用JSP九大内置对象之一:exception
默认值是false

7.5 JSP的九大内置对象

○ jakarta.servlet.jsp.PageContext pageContext 页面作用域
○ jakarta.servlet.http.HttpServletRequest request 请求作用域
○ jakarta.servlet.http.HttpSession session 会话作用域
○ jakarta.servlet.ServletContext application 应用作用域
■ pageContext < request < session < application
■ 以上四个作用域都有:setAttribute、getAttribute、removeAttribute方法。
■ 以上作用域的使用原则:尽可能使用小的域。
○ java.lang.Throwable exception
○ jakarta.servlet.ServletConfig config
○ java.lang.Object page (其实是this,当前的servlet对象)
○ jakarta.servlet.jsp.JspWriter out (负责输出)
○ jakarta.servlet.http.HttpServletResponse response (负责响应)

7.6 EL表达式

1.什么是EL表达式

在这里插入图片描述

2.EL表达式的使用

<%
	// 创建User对象
	User user = new User();
	user.setUsername("jackson");
	user.setPassword("1234");
	user.setAge(50);

	// 将User对象存储到某个域当中。一定要存,因为EL表达式只能从某个范围中取数据。
	// 数据是必须存储到四大范围之一的。
	request.setAttribute("userObj", user);
%>

<%--使用EL表达式取--%>
${这个位置写什么????这里写的一定是存储到域对象当中时的name}
要这样写:
${userObj}
等同于java代码:<%=request.getAttribute("userObj")%>
你不要这样写:${"userObj"}

面试题:
	${abc} 和 ${"abc"}的区别是什么?
		${abc}表示从某个域中取出数据,并且被取的这个数据的name是"abc",之前一定有这样的代码:.setAttribute("abc", 对象);
		${"abc"} 表示直接将"abc"当做普通字符串输出到浏览器。不会从某个域中取数据了。

${userObj} 底层是怎么做的?从域中取数据,取出user对象,然后调用user对象的toString方法,转换成字符串,输出到浏览器。

<%--如果想输出对象的属性值,怎么办?--%>
${userObj.username} 使用这个语法的前提是:User对象有getUsername()方法。
${userObj.password} 使用这个语法的前提是:User对象有getPassword()方法。
${userObj.age} 使用这个语法的前提是:User对象有getAge()方法。
${userObj.email} 使用这个语法的前提是:User对象有getEmail()方法。
EL表达式中的. 这个语法,实际上调用了底层的getXxx()方法。
注意:如果没有对应的get方法,则出现异常。报500错误。

${userObj.addr222.zipcode}
以上EL表达式对应的java代码:
user.getAddr222().getZipcode()

在这里插入图片描述
在这里插入图片描述

<%@ page import="jakarta.servlet.http.HttpServlet" %>
<%@ page import="jakarta.servlet.http.HttpServletRequest" %>
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %>
<%
    request.setAttribute("username","zhangsan");
%>
\${username}
${username}<br>
${username}<br>

<%--
//JSP有九大内置对象
// pageContext, request,session, application, nesponse, out, config, page , exception
//其中四个域对象,其中最小的域是pageContext
// pageContext翻译为:页面上下文。通过pageContext可以获取????--%>

<%--从以下代码来看,pageContext. getRequest()方法是没用的。这是获取request对象。
而JSP中自带了内置对象request,直接用nequest内置对像就行了。--%>
<%=pageContext.getRequest()%><br>
<%=request%><br>
<%--
    在EL表达式当中没有request这个隐式对象。
    requestScope 这个只代表“请求范围"。不等同于request对象。在EL表达式当中有一个隐式的对象:pageContext
    EL表达式中的pageContext和JSP中的九大内置对象pageContext是同一个对象。
--%>
<hr>

<%=((HttpServletRequest)pageContext.getRequest()).getContextPath()%><br>
通过EL表达式获取应用的根:
${pageContext.request.contextPath}<br>

${pageContext.request}<br>
<%=request.getContextPath()%>

3.EL表达式中内置对象

1. pageContext

应用的根路径:${pageContext.request.contextPath}

(因为只有pageContext,没有request内置对象所以通过pageContext的方法获取request)

2. param

用户名:<%=request.getParameter("username")%>
//使用param
用户名:${param.username}

3. paramValues

爱好:${paramValues.aihao[0]}${paramValues.aihao[1]}${paramValues.aihao[2]}

4. initParam

  <!--Servlet上下文初始化参数-->
  <!--上下文初始化参数被封装到:ServletContext对象当中了-->
  <context-param>
    <param-name>pageSize</param-name>
    <param-value>20</param-value>
  </context-param>


<%
    String a =application.getInitParameter("pageSize");
%>
    每页显示的记录条数:<%=a%>  //20
    //使用initParam
每页显示的记录条数${initParam.pageSize} //20

4.EL表达式中的运算符

在这里插入图片描述
在这里插入图片描述

7.7. JSTL标签库

1.什么是jstl标签库
● Java Standard Tag Lib (Java标准的标签库)
● JSTL标签库通常结合EL表达式一起使用。目的是让JSP中的java代码消失。
● 标签是写在JSP当中的,但实际上最终还是要执行对应的java程序。(java程序在jar包当中。)
2.使用jstl的步骤
表面使用的是标签,底层实际上还是java程序。
JSTL标签原理:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
以上uri后面的路径实际上指向了一个×x×.tld文件。
tld文件实际上是一个xml配置文件。
在tld文件中描述了"标签""java类"之间的关系。
以上核心标签库对应的tld文件是:c.tld文件。它在哪里。
在jakarta.serv1et.jsp.jst1-2.0.0.jar里面META-INF目录下,有一个c.t1d文件。

配置文件:tld解析

<tag>
        <description>对标签的描述</description>
        <name>标签的名字</name>
        <tag-class>标签对应java类</tag-class>
        <body-content>JSP</body-content>标签体当中可以出现的内容,如果是JSp,
        就表示标签体中可以出现符合JSp所有语法的代码。例如EL表达式。

        <attribute>
            <description>
                对这个属性的描述
            </description>
            <name>var</name>属性名
            <required>false</required>false表示该属性不是必须的
            <rtexprvalue>false</rtexprvalue>false 不支持EL表达式
        </attribute>
    </tag>

3.常用的标签
在这里插入图片描述

<%@ page import="java.util.List" %>
<%@ page import="com.javaweb.jsp.bean.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%--引入标签库,jstl核心标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

<%
    List<User> userList=new ArrayList<>();
    User u1=new User("110","警车",1);
    User u2=new User("120","救护车",2);
    User u3=new User("119","消防车",3);

    userList.add(u1);
    userList.add(u2);
    userList.add(u3);

    request.setAttribute("userList",userList);
%>
<%
    List<User> users=(List<User>) request.getAttribute("userList");
    for (User user : users) {
%>
    id:<%=user.getUsername()%>,psw:<%=user.getPassword()%>,age:<%=user.getAge()%><br>
<%
    }
%>
<hr>
<%--使用core标签库中forEach标签。对List集合进行遍历--%>
<%--EL表达式只能从域中取数据--%>
<%--var后面的名字是随意的。var属性代表的是集合中的每一个元素。--%>
<c:forEach items="${userList}" var="s">
    id:${s.username},psw:${s.password},age:${s.age}<br>
</c:forEach>


<%--核心标签库中的if标签--%>
<%--test属性是必须的。test属性支持EL表达式。test属性值只能是boolean类型。--%>
<c:if test="${empty param.username}">
<h1>用户名不能为空</h1>
</c:if>

<%--没有else标签的话,可以搞两个if出来。--%>
<%--if标签还有var属性,不是必须的。--%>
<%--if标签还有scope属性,用来指定van的存储域。也不是必须的。--%>
<%--scope有四个值可选,page(pageContext域)、request(requestil域)、session(session域)、application(application城)--%>
<%--将var中的v存储到request域。--%>
<c:if test="${not empty param.username}" var="v" scope="request">
    <h1>欢迎你${param.username}</h1>
</c:if>

<%--v变量中存储的是test届性的值。--%>
${v} <%--true--%>

<hr>

<%--var用来指定循环中的变量--%>
<%--begin开始--%>
<%--end结束--%>
<%--step步长--%>
<%--底层实际上:会将i存储到pageContext域当中。--%>
<c:forEach var="i" begin="1" end="10" step="1">
    <%--所以这里才会使用EL表达式将其取出,一定是从某个域当中取出的。--%>
    ${i}<br>
</c:forEach>

<hr>
<%--var="s"这个s代表的是集合中的每个Student对象--%>
<%--varStatus="这个属性表示var的状态对象,这里是一个java对象,这个java对象代表了var的状态"--%>
<%--varStatus="这个名字是随意的"--%>
<%--varStatus这个状态对象有count属性。可以直接使用。--%>
<c:forEach items="${userList}" var="s" varStatus="userStatus">
    <%--varStatus的count值从1开始,以1递增,主要是用于编号/序号。--%>
    编号:${userStatus.count} id:${s.username},psw:${s.password},age:${s.age}<br>
</c:forEach>

<hr>
<%--注意:这个嵌套结构不能随便改,只能这样嵌套。类似于if else--%>
<c:choose>
    <c:when test="${param.age<18}">
        青少年
    </c:when>
    <c:when test="${param.age<18}">
        中年
    </c:when>
    <c:when test="${param.age<18}">
        老年
    </c:when>
    <c:otherwise>
    	其他
    </c:otherwise>
</c:choose>

在这里插入图片描述

7.8 过滤器和监听器

Filter过滤器

在这里插入图片描述
在这里插入图片描述
第二步:在web.xml文件中对Filter进行配置。这个配置和Servlet很像。
在这里插入图片描述

Listener监听器

在这里插入图片描述
在这里插入图片描述

八、MVC三层架构

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值