JavaWeb基础知识

JavaWeb

JavaWeb基本概念

Java Web,是用Java技术来解决相关web互联网领域的技术栈。web包括:web服务端和web客户端两部分。Java在客户端的应用有Java Applet,不过使用得很少,Java在服务器端的应用非常的丰富,比如Servlet,JSP、第三方框架等等。

静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变 。静态web资源开发技术:HTML、CSS

动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。。动态web资源开发技术:JavaScript、JSP/Servlet、ASP、PHP等。在Java中,动态web资源开发技术统称为Java Web

Web概述

XML基础

XML语法:

<?xml 版本信息 [编码信息] [文档独立性信息] ?>
<?xml version="1.0" encoding="UTF-8"?>

XML注释:

<!--注释信息-->

DTD约束

文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。

DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

内部的 DOCTYPE 声明

假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:

<!DOCTYPE 根元素 [元素声明]>

Schema约束

schema概述

schema约束同为xml文件的约束模式语言之一, 最大的作用是为了验证xml文件的规范性的.

HTTP

HTTP简介

  • HTTP:超文本传输协议 (Hypertext Transfer Protocol)

  • 默认端口号:80

  • HTTPS 默认端口号 443 (S代表Safe 安全的)

  • HTTP1.0

    • HTTP1.0 协议的客户端与服务器在交互过程中需要经过建立连接,发送请求消息,回送响应消息,关闭连接四个步骤。客户端与服务器建立连接后,每次只能处理一个HTTP请求
  • HTTP1.1

    • 客户端与服务器建立连接后,可以传送多个HTTP请求和响应

HTTP请求

  • 客户端------>发送请求------->服务器

General:

Request URL: http://localhost:2019/servlet_war/Servlet01   //请求地址
Request Method: GET                                        //请求方法,get/post方法
Status Code: 200                                           //状态码
Remote Address: [::1]:2019                                 //远程地址

Request Header:

Accept:text/html        
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7,zh-TW;q=0.6,zh;q=0.5
Cache-Control: max-age=0
Connection: keep-alive
Cookie: JSESSIONID=83A28ABEF514F89A9A746C55FACCC21C; Idea-6b53f3ef=66018b3b-efdd-4d19-8e0b-c206dfe4b3e0
Host: localhost:2019
......
  • HTTP请求行

    1. 请求行中的请求方式:Get
    2. 请求方式:Get、Post、(最为常用) HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS
  • HTTP请求消息头

    Accept              //指出客户端程序(浏览器)能够支持的类型
    Accept-Encoding     //支持哪种编码格式  GBK、UTF-8、GB2312、ISO8859-1
    Accept-Language     //支持的语言环境
    Cache-Control:      //缓存控制
    Connection          //连接
    Cookie              //Cookie
    Host                //主机
    ......
    

HTTP响应

  • 服务器----->响应----->客户端

Response Header:

Cache-Control: private                   //缓存控制
Connection: keep-alive                   //连接
Content-Encoding: gzip                   //文本编码
Content-Type: text/html;charset=utf-8    //文本类型
......
  • HTTP响应状态码

    1. 1xx:表示请求已接收,需要继续处理
    2. 2xx(200):表示请求已经成功被服务器接收、理解并接受
    3. 3xx(302,304):为完成请求,客户端需进一步细化请求
    4. 4xx(404):客户端的请求有错误
    5. 5xx(500):服务端出现错误
  • HTTP响应消息头

Accept              //指出客户端程序(浏览器)能够支持的类型
Accept-Encoding     //支持哪种编码格式  GBK、UTF-8、GB2312、ISO8859-1
Accept-Language     //支持的语言环境
Cache-Control:      //缓存控制
Connection          //连接
Cookie              //Cookie
Host                //主机
Refresh             //告诉客户端多久刷新一次
location            //让网页重新定向
......

Tomcat

目录图:

在这里插入图片描述

Servlet

servlet体系结构图:

在这里插入图片描述

Servlet接口中的抽象方法

//  容器在创建好Servlet对象后,就会调用此方法。该方法接收一个ServletConfig类型的参数,Servlet容器通过这个参数向Servlet传递初始值
void init(ServletConfig var1);
//用于获取Servlet对象的配置信息,返回Servlet的ServletConfig对象
ServletConfig getServletConfig();
//负责响应用户的请求,当容器(指web服务器)接收到客户端访问Servlet对象的请求时,就会调用此方法。(提供服务的方法,每一次Servlet被访问时执行,会执行多次。)
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
//返回一个字符串,其中包含关于Servlet的信息,如:作者,版权和版本等信息
String getServletInfo();
//负责释放Servlet对象占用的资源。当服务器关闭或者Servlet对象被移除时,Servlet对象会被摧毁,容器调用此方法
void destroy();

HttpServlet类常用的方法:

//用于处理GET类型的HTTP请求方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
//用于处理POST类型的HTTP请求方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp)

Servlet虚拟路径的映射

  • Servlet的多重映射
    1. 配置多个元素
    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>com.sgl.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/Servlet01</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/Servlet001</url-pattern>
    </servlet-mapping>

​ 2. 在一个元素下配置多个 子元素

    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>com.sgl.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/Servlet01</url-pattern>
        <url-pattern>/Servlet001</url-pattern>
    </servlet-mapping>
  • Servlet映射路径中使用的通配符

    1. “ *.拓展名
    2. /* ”
  • 缺省Servlet

  1. web.xml文件中
<servlet-mapping><url-patten>/</url-patten></servlet-mapping>

即url的值为/的servlet为此项目的缺省servlet,映射路径仅仅十余个正斜线(/)

ServletConfig接口

当Tomcat初始化一个Servlet时,会将Servlet的配置信息封装到一个ServletConfig对象中,通过调用init(ServletConfig var1)方法将ServletConfig对象传递给Servlet,ServletConfig定义了一系列获取配置信息的方法

ServletConfig接口的常用方法

String getInitParameter(String name)     //根据初始化参数名返回对应的初始化参数值
Enumeration getInitParameterNames()      //返回一个Enumeration对象,其中包含了所有的初始化参数名
ServletContext getServletContext()       //返回一个代表当前Web应用的ServletContext对象
String getServletName()                  //返回Servlet的名字,即web.xml中<servlet-name>元素的值

web.xml配置

    <servlet>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>com.sgl.servlet.TestServlet01</servlet-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/Servlet02</url-pattern>
    </servlet-mapping>
package com.sgl.servlet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class TestServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        //获得ServletConfig对象
        ServletConfig config = this.getServletConfig();
        //获得参数名为encoding对应的参数值
        String param = config.getInitParameter("encoding");
        writer.println("encoding="+param);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

启动Tomcat服务器结果

在这里插入图片描述

ServletContext接口

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletConfig对象,它代表了当前的web应用

共享数据

在这个Servlet中保存的数据可以在另一个Servlet中拿到

web.xml配置

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.sgl.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>GetHelloServlet</servlet-name>
        <servlet-class>com.sgl.servlet.GetHelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>GetHelloServlet</servlet-name>
        <url-pattern>/GetHelloServlet</url-pattern>
    </servlet-mapping>
package com.sgl.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //this.getInitParameter();   初始化参数
        //this.getServletConfig();   Servlet配置
        //this.getServletContext();  Servlet上下文
        ServletContext servletContext = this.getServletContext();

        String username = "刚龙";
        servletContext.setAttribute("username",username); //将一个数据保存在ServletContext中,名字为:username   值为:username
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

package com.sgl.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class GetHelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String username = (String) servletContext.getAttribute("username");

        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println("名字:"+username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

获得初始化参数

web.xml配置

    <!--配置一些web应用的初始化参数-->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
    </context-param>
package com.sgl.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String url = servletContext.getInitParameter("url");
        resp.getWriter().println("url:"+url);

    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

请求转发
  • 请求转发
    1. 请求转发: xxServlet收到请求,然后直接转发给yyServlet,然后yyServlet返回给客户端。整个过程中,客户端发出一个请求,收到一个响应。
    2. 请求转发:利用RequestDispather接口中的forward方法实现请求转发。

在这里插入图片描述

  • 重定向
    1. 重定向:xxServlet收到请求,然后发出一个响应给客户端,客户端立即又发送一个请求访问xxServlet中给的URL,即yyServlet的路径,然后yyServlet给客户端一个响应。整个过程中,客户端发出两个请求,收到两个响应。
    2. 请求重定向:利用HttpServletResponse的sendRedirect方法实现请求重定向。

在这里插入图片描述

ABC代替,大概就是这样:

在这里插入图片描述

package com.sgl.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        //RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/TestServlet01");
        //requestDispatcher.forward(req,resp);         //调用forward实现请求转发
        servletContext.getRequestDispatcher("/TestServlet01").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

读取资源文件

Properties

  • 在Java目录下新建properties
  • 在resources目录下新建properties

都被打包在同一个路径下:classes,这个路径俗称为classpath

思路:需要一个文件流

db.properties(resources目录下)

username=root
password=123456

aa.properties (Java目录下),需要解决资源导出问题

username=root
password=456789

解决资源导出问题 : 在pom.xml(该模块下的)文件加入以下:

  <!--在build中配置resources,来防止我们资源导出失败的问题-->
  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
package com.sgl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class TestProperties extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/sgl/servlet/aa.properties");
        Properties properties = new Properties();
        properties.load(is);
        String user = properties.getProperty("username");
        String pwd = properties.getProperty("password");
        resp.getWriter().println("user:"+user);
        resp.getWriter().println("pwd:"+pwd);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

HttpServletResponse

web服务器接收到客户端的http请求。针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的HttpServletResponse

  • 如果获取客户端请求过来的参数 找:HttpServletRequest
  • 如果要给客户端响应一些信息 找:HttpServletResponse

HttpServletResponse对象提供解决乱码问题

第一种方式

//设置HttpServletResponse使用utf-8编码
resp.setCharacterEncoding("utf-8");
//通知浏览器使用utf-8
resp.setHeader("Context-Type","text/html;charset=utf-8");

第二种方式

//包含第一种方式的两种功能
resp.setContentType("text/html;charset=utf-8");

分类

以下方法都是HttpServletResponse类(HttpServletResponse继承ServletResponset)和ServletResponset类中的方法

  • 负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
  • 负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setBufferSize(int var1);
void sendError(int var1, String var2) throws IOException;
void sendError(int var1) throws IOException;
void sendRedirect(String var1) throws IOException;
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
void setStatus(int var1);
  • 响应的状态码
int SC_OK = 200;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_NOT_MODIFIED = 304;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_BAD_GATEWAY = 502;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

下载文件

  1. 获取要下载的文件的绝对路径
  2. 获取要下载的文件名
  3. 设置content-disposition响应头控制浏览器以下载的形式打开文件
  4. 获取要下载的文件输入流
  5. 创建数据缓冲区
  6. 通过response对象获取OutputStream流
  7. 将FileInputStream流写入到buffer缓冲区
  8. 使用OutputStream将缓冲区的数据输出到客户端浏览器
package com.sgl.demo01;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取要下载的文件的绝对路径
        //String realPath = "E:\\Idea\\Javaweb-02-Servlet02\\HttpServletResponse\\src\\main\\resources\\1.jpeg";
        String realPath = "E:\\Idea\\Javaweb-02-Servlet02\\HttpServletResponse\\src\\main\\resources\\刚龙.jpeg";
        System.out.println("下载文件的路径:"+realPath);
        // 2.  获取要下载的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        // 3. 设置Content-Disposition响应头控制浏览器以下载的形式打开文件
        //resp.setHeader("Content-Disposition", "attachment;filename="+fileName);
        resp.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
        // 4. 获取要下载的文件输入流
        FileInputStream in = new FileInputStream(realPath);
        // 5. 创建数据缓冲区
        int len = 0;
        byte[] buffer = new byte[1024];
        // 6. 通过response对象获取OutputStream流
        ServletOutputStream out = resp.getOutputStream();
        // 7. 将FileInputStream流写入到buffer缓冲区
        while ((len=in.read(buffer))!=-1){
            // 8. 使用OutputStream将缓冲区的数据输出到客户端浏览器
            out.write(buffer,0,len);
        }
        in.close();
        out.close();

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

验证码功能

package com.sgl.demo01;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //如何让浏览器3秒自动刷新一次
        resp.setHeader("refresh","3");

        //在内存中创建一个图片
        BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_BGR);
        //得到图片
        Graphics g = image.getGraphics(); //🖊笔
        //设置图片的背景颜色
        g.setColor(Color.white);
        g.fillRect(0,0,80,20);
        //给图片写数据
        g.setColor(Color.BLUE);
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(makeNum(),0,20);

        //告诉浏览器,这个请求用图片打开
        resp.setContentType("image/jpeg");
        //网站存在缓存,不让浏览器存在缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        //把图片写给浏览器
        ImageIO.write(image,"jpg",resp.getOutputStream());
    }

    //生成随机数
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7-num.length(); i++) {
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }
}

实现重定向

  1. 重定向:xxServlet收到请求,然后发出一个响应给客户端,客户端立即又发送一个请求访问xxServlet中给的URL,即yyServlet的路径,然后yyServlet给客户端一个响应。整个过程中,客户端发出两个请求,收到两个响应。

  2. 请求重定向:利用HttpServletResponse的sendRedirect方法实现请求重定向。

    void sendRedirect(String var1) throws IOException;
    

在这里插入图片描述

测试:

package com.sgl.demo01;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
        resp.setHeader("Location","/HttpServletResponse_war/ImageServlet");
        resp.setStatus(302);    //resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);等价于302
        */

        resp.sendRedirect("/HttpServletResponse_war/ImageServlet");  //重定向
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

请求转发和重定向的区别:

  • 相同点:页面都会跳转
  • 不同点:
    1. 请求转发的时候,url地址栏不会发生变化
    2. 重定向的时候,url地址栏会发生变化

Response重定向

index.jsp (启动Tomcat时,显示的页面)

通过form表单 action=“${pageContext.request.contextPath}/RequestTest” ,然后输入,可以进入到RequetTest,然后右通过重定向进入到success.jsp

<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径,需要寻找到项目的路径--%>
<%--${pageContext.request.contextPath}代表当前的项目--%>
<form action="${pageContext.request.contextPath}/RequestTest" method="get">
    用户名:<input type="text" name="username"> <br>
    密码:<input type="password" name="password"> <br>
    <input type="submit">
</form>
</body>
</html>

创建的RequestTest类

package com.sgl.demo01;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入这个请求");

        //处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println(username+"    "+password);

        //重定向一定要注意路径问题  否则404
        resp.sendRedirect("/HttpServletResponse_war/success.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

success.jsp

<%--
  Created by IntelliJ IDEA.
  User: shiga
  Date: 2021/9/2
  Time: 21:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>Success</h1>
</body>
</html>

HttpServletRequest

获取参数和请求转发

index.jsp

<html>
<body>
<h2>登录</h2>

<div>
    <%--这里的表单表示的意思:以post方式提交表单,提交到我们的LoginServlet请求--%>
    <form action="${pageContext.request.contextPath}/LoginServlet" method="post">
        用户名:<input type="text" name="username" required><br>
        密码:<input type="password" name="password"><br>
        爱好:
        <input type="checkbox" name="hobbies" value="女孩">女孩
        <input type="checkbox" name="hobbies" value="代码">代码
        <input type="checkbox" name="hobbies" value="唱歌">唱歌
        <input type="checkbox" name="hobbies" value="电影">电影
        <br>
        <input type="submit">
    </form>
</div>
</body>
</html>

创建的LoginServlet类

package com.sgl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobbies");
        System.out.println("=================");
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(hobbies));
        System.out.println("=================");

        //通过请求转发
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
        

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

success.jsp

<%--
  Created by IntelliJ IDEA.
  User: shiga
  Date: 2021/9/2
  Time: 21:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>success</h1>
</body>
</html>

Cookie

在这里插入图片描述

cookie:

  • 客户端技术 (响应,请求)

常见现象:网站登录之后,下次无需登录,第二次直接登录上去

测试:

package com.sgl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

public class CookieDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setHeader("Context-Type","text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();

        //Cookie 服务端从客户端获取
        Cookie[] cookies = req.getCookies();  //返回类型为一个数据,说明cookie可以存在多个

        //判断cookie是否存在
        if (cookies!=null){
            //如果存在怎么办
            out.write("您上一个访问时间为:");

            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //获取cookie的名字
                if (cookie.getName().equals("LastLoginTime")){
                    //获取cookie的值
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastLoginTime);
                    out.write(date.toLocaleString());
                }
            }
        }
        //服务端响应一个cookie
        Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
        //cookie有效期为1天
        cookie.setMaxAge(24*60*60);
        resp.addCookie(cookie);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

用到的方法

Cookie[] cookies = req.getCookies();  //获取cookie
cookie.getName()   //获取cookie中的key
cookie.getValue()   //获取cookie中的value
Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");  //新建一个cookie
cookie.setMaxAge(24*60*60);  //设置cookie的有效期
resp.addCookie(cookie);  //响应给客户端一个cookie

Cookie:一般会保存本地的 用户目录下 appdata

一个网站cookie是存在上线!

  • 一个Cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
  • Cookie大小限制4kb
  • 300个cookie是浏览器上线

删除cookie

  • 不设置有效期,关闭浏览器自动失效
  • 设置有效期时间为0

测试删除CookieDemo01类的cookie访问信息,启动Tomcat后,访问CookieDemo01上次访问时间被保存,然后访问CookieDemo02,再访问CookieDemo01,cookie上次访问时间删除

package com.sgl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CookieDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建一个cookie,名字必须和删除的名字一致
        Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
        //将cookie有效期设置为0
        cookie.setMaxAge(0);

        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

中文数据传递

package com.sgl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;

public class CookieDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //解决中文乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setHeader("Context-Type","text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();

        //Cookie 服务端从客户端获取
        Cookie[] cookies = req.getCookies();  //返回类型为一个数据,说明cookie可以存在多个


        //判断cookie是否存在
        if (cookies!=null){
            //如果存在怎么办
            out.write("上一次访问的用户:");

            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //获取cookie的名字
                if (cookie.getName().equals("name")){
                    //输出cookie的值
                    out.write(URLDecoder.decode(cookie.getValue(),"utf-8"));  //解码
                }
            }
        }

        //编码
        Cookie cookie = new Cookie("name", URLEncoder.encode("刚龙","utf-8"));
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

用到编码和解码

 URLEncoder.encode("刚龙","utf-8")  //编码
 URLDecoder.decode(cookie.getValue(),"utf-8")  //解码

Session ***

在这里插入图片描述

session:

  • 服务端技术,保存会话信息,把信息或者数据存放在session中

  • 服务器会给每一个用户(浏览器)创建一个session对象

  • 一个Session独占一个浏览器,只要浏览器没有关闭,Session就存在

  • 用户登陆后,整个网站它都可以访问 ---->保存用户的信息;保存购物车的信息等等

HttpSession中的方法:

//得到一个Session
HttpSession session = req.getSession();
long getCreationTime();

String getId();

long getLastAccessedTime();

ServletContext getServletContext();

void setMaxInactiveInterval(int var1);

int getMaxInactiveInterval();

/** @deprecated */
@Deprecated
HttpSessionContext getSessionContext();

Object getAttribute(String var1);

/** @deprecated */
@Deprecated
Object getValue(String var1);

Enumeration<String> getAttributeNames();

/** @deprecated */
 @Deprecated
String[] getValueNames();

void setAttribute(String var1, Object var2);

/** @deprecated */
@Deprecated
void putValue(String var1, Object var2);

void removeAttribute(String var1);

/** @deprecated */
@Deprecated
void removeValue(String var1);

void invalidate();

boolean isNew();

测试:

获取Session并给Session存东西

package com.sgl.servlet;

import com.sgl.pojo.Person;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SessionDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setHeader("text/html","charset=utf-8");

        //得到一个Session
        HttpSession session = req.getSession();

        //给session存东西
        //session.setAttribute("name","刚龙");
        session.setAttribute("name",new Person("刚龙",18));

        //获取session的ID
        String sessionId = session.getId();

        //判断session是不是新创建
        if (session.isNew()){
            resp.getWriter().write("session创建成功,ID"+sessionId);
        }else {
            resp.getWriter().write("session已经再服务器中存在了,ID:"+sessionId);
        }



    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

得到Session的保存的值

package com.sgl.servlet;

import com.sgl.pojo.Person;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SessionDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setHeader("text/html","charset=utf-8");


        //得到Session
        HttpSession session = req.getSession();

        //String name = (String) session.getAttribute("name");
        Person person = (Person) session.getAttribute("name");
        //resp.getWriter().write(name);
        resp.getWriter().write(person.toString());



    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

会话过期的两种方式:

  1. 手动注销Session
package com.sgl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SessionDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.removeAttribute("name");
        //手动注销session
        session.invalidate();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  1. 会话自动过期,在web.xml中配置
    <!--设置Session默认的失效时间-->
    <session-config>
        <!--1分钟后session自动失效,以分钟为单位-->
        <session-timeout>1</session-timeout>
    </session-config>

Session和Cookie的区别:

  1. Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  2. Session是把用户的数据写到用户独占的Session中,服务端保存(保存重要的信息,减少服务器资源的浪费)
  3. Session对象由服务器创建

JSP

JSP(全称JavaServer Pages)JSP将Java代码和特定变动内容嵌入到静态的页面中,实现以静态页面为模板,动态生成其中的部分内容。

JSP原理

**浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet ** JSP本质就是一个Servlet

JSP最终会被转换成一个Java类

找不到的话,打开IDEA点击 Help 下的 Show Log in Explorer 会在文件夹中显示

在这里插入图片描述

index_jsp.java : 源代码

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/9.0.52
 * Generated at: 2021-09-03 08:44:35 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      final java.lang.String _jspx_method = request.getMethod();
      if ("OPTIONS".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        return;
      }
      if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
        return;
      }
    }

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("<html>\n");
      out.write("<body>\n");
      out.write("<h2>Hello World!</h2>\n");
      out.write("</body>\n");
      out.write("</html>\n");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

部分讲解:

方法

//初始化  
public void _jspInit() {}
//销毁
public void _jspDestroy() {}
//
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)

内置对象

final javax.servlet.jsp.PageContext pageContext;      //页面上下文
javax.servlet.http.HttpSession session = null;        //session
final javax.servlet.ServletContext application;       //applicationContext
final javax.servlet.ServletConfig config;             //config
javax.servlet.jsp.JspWriter out = null;               //out
final java.lang.Object page = this;                   //page:代表当前页
final javax.servlet.http.HttpServletRequest request   //请求
final javax.servlet.http.HttpServletResponse response //响应

输出页面前的增加的代码

response.setContentType("text/html");              //
pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;

在JSP页面中:

​ 只要是Java代码就会原封不动的输出;

​ 如果是HTML代码,就会被转换为:

out.write("<html>\n");

​ 然后输出

JSP原理图:

在这里插入图片描述

JSP基础语法

JSP表达式
  <%--JSP表达式
  作用:用来将程序输出到客户端
  <%= 变量或者表达式%>
  --%>
  <%= new java.util.Date()%>
JSP脚本片段
  <%--JSP脚本片段--%>
  <%
    int sum = 0;
    for (int i = 0; i < 100; i++) {
      sum = sum + i;
    }
    out.println("<h1>Sum="+sum+"</h1>");
  %>
脚本片段的再实现
  <%
    int x = 10;
    out.println(x);
  %>
  <%
    int y = 10;
    out.println(y);
  %>
  <hr>
  <%--在代码中嵌入HTML代码--%>
  <%
    for (int i = 0; i < 5; i++) {
  %>
    <h1>Hello World  <%=i%></h1>
  <%
    }
  %>

JSP声明

  <%!
    static {
      System.out.println("Loading Servlet");
    }
    
    private int globalVar = 0;
    
    public void test(){
      System.out.println("进入了test方法");
    }
  %>

JSP声明会被编译到JSP生成的Java类中!! 其他的会被生成到 _jspService 方法中

在JSP中嵌入Java代码即可

<%%>
<%=%>
<%!%>

<%--注释--%>

JSP的注释不会在客户端显示,HTML会!

测试定制页面错误,页面跳转到自定义错误的页面

<%--
  Created by IntelliJ IDEA.
  User: shiga
  Date: 2021/9/3
  Time: 20:58
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%--在web.xml文件配置了,这里就不需要了--%>
<%--定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>

<html>
<head>
    <title>Title</title>
</head>
<body>

<%
    int x =1/0;
%>

</body>
</html>

自定义的404和500页面:

<%--
  Created by IntelliJ IDEA.
  User: shiga
  Date: 2021/9/3
  Time: 21:20
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<img src="image/404.jpg" alt="">

</body>
</html>
<%--
  Created by IntelliJ IDEA.
  User: shiga
  Date: 2021/9/3
  Time: 20:59
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<img src="image/500.jpg" alt="">


</body>
</html>

跳转页面的两种方式:

  1. 使用JSP指令<% @ args… %>
<%--定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>
  1. 在web.xml文件中配置
    <error-page>
        <error-code>404</error-code>
        <location>/error/404.jsp</location>
    </error-page>

    <error-page>
        <error-code>500</error-code>
        <location>/error/500.jsp</location>
    </error-page>

JSP指令

<% @ page 属性名1="属性值1" 属性名2="属性值2" ... %>
属性名称取值范围描述
languageJava指明解释该JSP时采用的语言,默认为Java
import任何包名,类名import属性,写了之后会自动添加到servlet的import语句中,但不进行包存在性的检查
sessiontrue,falseSession对象是否参与会话,session="false"就没有session对象了
isErrorPagetrue,falseisErrorPage=“true false” 设置此页是否为出错页,如果被设置为true,你就能使用exception对象
errorPage某个JSP页面的相对路径设置处理异常事件的JSP文件。
contentType有效的文档类型contentType属性设置发送到客户端文档的响应报头的类型和字符编码。多个使用;号分开。 pageEncodeing属性只用于更改字符编码
PageEnCoding当前页面指定页面编码格式

例子:

<%--定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>
<%--显示的声明这是一个错误页面--%>
<%@ page isErrorPage="true" %>

<%@ page pageEncoding="utf-8" %>

include指令

网站前面的导航栏和底部栏,跳转页面一直固定不动,用的是i<%@ include file=“”%>或<jsp:include page=“”/>

<%--@ include会将两个页面合二为一--%>
<%@ include file="common/header.jsp"%>
<h2>网页主体</h2>
<%@ include file="common/footer.jsp"%>

<hr>
<%--JSP标签
    jsp:include:拼接页面,本质还是三个
        --%>
<%--JSP标签--%>
<jsp:include page="common/header.jsp"/>
<h2>网页主体</h2>
<jsp:include page="common/footer.jsp"/>  

9大内置对象(JSP隐式对象)

JSP隐式对象:

名称类型描述
outjavax.servlet.jsp.JspWriter用于页面输出
requestjavax.servlet.jsp.HttpServletRequest得到用户请求
responsejavax.servlet.jsp.HttpServletResponse服务端向客户端回应信息
configjavax.servlet.jsp.ServletConfig服务器配置,可以得到初始化参数
sessionjavax.servlet.http.HttpSession用来保存用户信息
applicationjavax.servlet.jsp.ServletContext所有用户的共享信息
pagejava.lang.Object指当前页面转换后的Servlet实例
pageContextjavax.servlet.jsp.PageContextJSP的页面容器
exceptionjava.lang.Throwable表示JSP页面所发生的异常,在错误页面才起作用

测试:

pageContextDemo01.jsp

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

<%--内置对象--%>
<%
    pageContext.setAttribute("name1","鲁班一号");//保存的数据只在一个页面中有效
    request.setAttribute("name2","鲁班二号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
    session.setAttribute("name3","鲁班三号");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    application.setAttribute("name4","鲁班四号");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>

<%--脚本片段中的代码,会被原封不动的生成到JSP.java
要求:必须保证Java语法的正确性
--%>
<%--
    public static final int PAGE_SCOPE = 1;
    public static final int REQUEST_SCOPE = 2;
    public static final int SESSION_SCOPE = 3;
    public static final int APPLICATION_SCOPE = 4;
--%>
<%
    //从PageContext取出,通过寻找的方式
    //从底层到高层(作用域):page->request->session->application
    //JVM:双亲委派机制
    String name1 = (String) pageContext.findAttribute("name1");
    String name2 = (String) pageContext.findAttribute("name2");
    String name3 = (String) pageContext.findAttribute("name3");
    String name4 = (String) pageContext.findAttribute("name4");
    String name5 = (String) pageContext.findAttribute("name5");  //不存在

    pageContext.forward("/PageDemo02.jsp");  //请求转发到PageDemo02.jsp
%>

<%--使用EL表达式输出${}--%>
<h3>取出的值为:</h3>
<h4>${name1}</h4>
<h4>${name2}</h4>
<h4>${name3}</h4>
<h4>${name4}</h4>
<h4>${name5}</h4>   <%--什么也不会输出,也不报错--%>
<h4><%=name5%></h4>  <%--会输出  null--%>

</body>
</html>

PageDemo02.jsp

从PageDemo02.jsp页面输出,只输出了 “鲁班三号和鲁班四号” (作用域不同)

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

<%--脚本片段中的代码,会被原封不动的生成到JSP.java
要求:必须保证Java语法的正确性
--%>
<%
    String name1 = (String) pageContext.findAttribute("name1");
    String name2 = (String) pageContext.findAttribute("name2");
    String name3 = (String) pageContext.findAttribute("name3");
    String name4 = (String) pageContext.findAttribute("name4");
    String name5 = (String) pageContext.findAttribute("name5");  //不存在
%>

<%--使用EL表达式输出${}--%>
<h3>取出的值为:</h3>
<h4>${name1}</h4>
<h4>${name2}</h4>
<h4>${name3}</h4>
<h4>${name4}</h4>
<h4>${name5}</h4>   <%--什么也不会输出,也不报错--%>
<h4><%=name5%></h4>  <%--会输出  null--%>

</body>
</html>

PageDemo03.jsp

关于作用域的一些方法和类(源码)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--PageContextImpl--%>
<%--
    public void setAttribute(String name, Object attribute, int scope) {
        switch(scope) {
        case 1:
            this.mPage.put(name, attribute);
            break;
        case 2:
            this.mRequest.put(name, attribute);
            break;
        case 3:
            this.mSession.put(name, attribute);
            break;
        case 4:
            this.mApp.put(name, attribute);
            break;
        default:
            throw new IllegalArgumentException("Bad scope " + scope);
        }

    }
--%>

<%--PageContext--%>
<%--
public abstract class PageContext extends JspContext {
    public static final int PAGE_SCOPE = 1;
    public static final int REQUEST_SCOPE = 2;
    public static final int SESSION_SCOPE = 3;
    public static final int APPLICATION_SCOPE = 4;
    public static final String PAGE = "javax.servlet.jsp.jspPage";
    public static final String PAGECONTEXT = "javax.servlet.jsp.jspPageContext";
    public static final String REQUEST = "javax.servlet.jsp.jspRequest";
    public static final String RESPONSE = "javax.servlet.jsp.jspResponse";
    public static final String CONFIG = "javax.servlet.jsp.jspConfig";
    public static final String SESSION = "javax.servlet.jsp.jspSession";
    public static final String OUT = "javax.servlet.jsp.jspOut";
    public static final String APPLICATION = "javax.servlet.jsp.jspApplication";
    public static final String EXCEPTION = "javax.servlet.jsp.jspException";
--%>

<%
    pageContext.setAttribute("hello1","hello2",PageContext.SESSION_SCOPE);//等价于session.setAttribute("hello1","hello2");

%>

</body>
</html>

PageContextDemo02.jsp

两者都可以实现请求转发

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

<%
    pageContext.forward("/index.jsp");//request.getRequestDispatcher("/index.jsp").forward(request,response);两个都可以实现请求转发
%>

</body>
</html>

JSP标签 JSTL标签 EL表达式

JSTL标签 EL表达式需要导入相应的包

<!--JSTL依赖-->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<!--standard标签库依赖-->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>
EL表达式

${ }

  1. 获取数据
  2. 执行运算
  3. 获取web开发的常用对象
JSP标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<jsp:forward page="jsptag02.jsp">
    <jsp:param name="name" value="sgl"/>
    <jsp:param name="age" value="22"/>
</jsp:forward>

</body>
</html>
JSTL表达式
核心标签***

格式:

<c:标签>
标签描述
<c:out>用于在JSP中显示数据,就像<%= … >
<c:set>用于保存数据
<c:remove>用于删除数据
<c:catch>用来处理产生错误的异常状况,并且将错误信息储存起来
<c:if>与我们在一般程序中用的if一样
<c:choose>本身只当做<c:when>和<c:otherwise>的父标签
<c:when><c:choose>的子标签,用来判断条件是否成立
<c:otherwise><c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行
<c:import>检索一个绝对或相对 URL,然后将其内容暴露给页面
<c:forEach>基础迭代标签,接受多种集合类型
<c:forTokens>根据指定的分隔符来分隔内容并迭代输出
<c:param>用来给包含或重定向的页面传递参数
<c:redirect>重定向至一个新的URL.
<c:url>使用可选的查询参数来创造一个URL

使用JSTL标签的步骤:

  1. 引用核心标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  1. 使用其中的方法
  2. 在Tomcat也需要引入 jstl-api 和 standard 两个包,否则会报错:JSTL解析错误

c:if c:out

EL表达式获取表单中的数据
${param.username}

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action="Jstl01.jsp" method="get">
    <%--
    EL表达式获取表单中的数据
    ${param.username}
    --%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="登录">
</form>

<%--判断如果提交的用户是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
    <c:out value="管理员欢迎你"/>
</c:if>

<%--自闭和标签--%>
<c:out value="${isAdmin}"/>

</body>
</html>

c:set c:choose c:when

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%--定义一个变量score 值为85--%>
<c:set var="score" value="85"/>

<c:choose>
    <c:when test="${score>=90}">
        <c:out value="你的成绩为优秀"/>   <%--用<c:out>输出,直接输出也可--%>
        你的成绩为优秀
    </c:when>
    <c:when test="${score>=80}">
        <c:out value="你的成绩为良好"/>
        你的成绩为良好
    </c:when>
    <c:when test="${score>=70}">
        <c:out value="你的成绩为中等"/>
        你的成绩为中等
    </c:when>
    <c:when test="${score>=60}">
        <c:out value="你的成绩为一般"/>
        你的成绩为一般
    </c:when>
    <c:when test="${score<60}">
        <c:out value="你的成绩为不及格"/>
        你的成绩为不及格
    </c:when>
</c:choose>
</body>
</html>

c:forEach

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%
    ArrayList<String> people = new ArrayList<>();
    people.add(0,"李四");
    people.add(1,"王五");
    people.add(2,"王二麻子");
    people.add(3,"天吴");
    people.add(4,"李六");
    request.setAttribute("list",people);
%>

<%--
var:每一次遍历出来的变量
items:要遍历的对象
begin: 开始
end:结束
step:步长
--%>
<c:forEach var="person" items="${list}">
    <c:out value="${person}"/>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1">
    <c:out value="${people}"/>
</c:forEach>
</body>
</html>

JavaBean(了解一下)

实体类

JavaBean有特定的写法:

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法

一般用来和数据库的字段做映射 ORM;

ORM:对象关系映射

  • 表----->类
  • 字段----->属性
  • 行记录----->对象

People表:

idnameageaddress
1鲁班一号18信阳
2鲁班二号19新县
3鲁班三号20潢川
package com.sgl.pojo;

//实体类  一般都是和数据库中的表结构一一对应!
public class People {
    private int id;
    private String name;
    private int age;
    private String address;

    public People() {
    }

    public People(int id, String name, int age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "People{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

jsp:useBean jsp:setProperty jsp:getProperty

<%@ page import="com.sgl.pojo.People" %><%--
  Created by IntelliJ IDEA.
  User: shiga
  Date: 2021/9/5
  Time: 20:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%
    People people02 = new People();
    people02.setAddress("新县");
    people02.setAge(19);
    people02.setId(2);
    people02.setName("鲁班二号");

%>
<%=people02.getAddress()%>
<%=people02.getAge()%>
<%=people02.getId()%>
<%=people02.getName()%>

<br>

<%--id="people01"  people01就相当于People类的一个实例化对象--%>
<jsp:useBean id="people01" class="com.sgl.pojo.People" scope="page"/>
<jsp:setProperty name="people01" property="address" value="信阳"/>
<jsp:setProperty name="people01" property="age" value="18"/>
<jsp:setProperty name="people01" property="id" value="1"/>
<jsp:setProperty name="people01" property="name" value="鲁班一号"/>

住址:<jsp:getProperty name="people01" property="address"/>
年龄:<jsp:getProperty name="people01" property="age"/>
id:<jsp:getProperty name="people01" property="id"/>
姓名:<jsp:getProperty name="people01" property="name"/>

</body>
</html>

在数据库建立对应的表

在这里插入图片描述

MVC三层架构

JSP Model2模型采用JSP(View)+Servlet(Controller)+JavaBean(Model)的技术

  • 模型(Model):负责管理应用程序的业务数据,定义访问控制以及以及修改这些业务数据的业务规则

简单理解:

1. 业务处理:业务逻辑(Service)
2. 数据持久化:CRUD(Dao)
  • 视图(View):负责与用户交互,它从模型中获取数据向用户展示,同时也能将用户请求传递给控制器进行处理。当模型的状态发送改变时,视图会对用户界面进行同步更新,从而保持与模型数据的一致性

简单理解:

1. 展示数据  
2. 提供链接发送Servlet请求(a,form,img.....)
  • 控制器(Controller):是负责应用程序中处理用户交互的部分,它负责从视图中读取数据,控制用户输入,并向模型发送数据

简单理解:

1. 接收用户的请求:(req:请求参数、Session信息)
2. 交给业务层处理相对于的代码  3.控制视图的跳转
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)--->交给业务层处理登录业务(判断用户密码是否正确:事务)--->Dao层查询用户和密码是否正确--->数据库

JSP Model2工作原理图

在这里插入图片描述

3个模型之间的关系和功能图

在这里插入图片描述

Filter***

Filter:过滤器,用来过滤网站的数据;

  • 处理中文乱码
  • 登录验证

在这里插入图片描述

Filter开发步骤:

  1. 导包不要导错

pom.xml

    <!--Servlet依赖-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
    </dependency>
    <!--JSP依赖-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.3</version>
    </dependency>
    <!--JSTL依赖-->
    <dependency>
      <groupId>javax.servlet.jsp.jstl</groupId>
      <artifactId>jstl-api</artifactId>
      <version>1.2</version>
    </dependency>
    <!--standard标签库依赖-->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>
    <!--连接数据库-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.37</version>
    </dependency>
  </dependencies>

在这里插入图片描述

  1. 编写过滤器

过滤器:看代码注释理解

package com.sgl.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    //初始化:web服务器启动,就初始化,随时等待过滤器对象出现
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    //销毁:web服务器关闭的时候,过滤会销毁
    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }

    //filterChain:链
    /*
    1.过滤中的所有代码,在过滤特定请求的时候都会执行
    2.必须让过滤器继续同行
       filterChain.doFilter(servletRequest,servletResponse)
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        System.out.println("CharacterEncodingFilter执行前...");
        filterChain.doFilter(servletRequest,servletResponse);//让我们的请求继续走,如果不写,程序到这里就拦截停止
        System.out.println("CharacterEncodingFilter执行后...");
    }
}

经过过滤器处理中文乱码的代码

package com.sgl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("你好呀!世界");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}


虚拟路径配置 web.xml

<servlet>
        <servlet-name>ShowServlet</servlet-name>
        <servlet-class>com.sgl.servlet.ShowServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/ShowServlet</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.sgl.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--只要是经过/CharacterEncodingFilter的请求,都会经过这个过滤器-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

监听器

实现监听器的接口:N种

  1. 编写一个监听器

    实现监听器接口

    package com.sgl.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    //统计网站在线人数:统计session
    public class OnlineCountListener implements HttpSessionListener {
        //创建session监听
        //一旦创建session就会触发这个事件
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            ServletContext context = se.getSession().getServletContext();
            Integer onlineCount = (Integer) context.getAttribute("OnlineCount");
            if (onlineCount==null){
                onlineCount = new Integer(1);
            }else {
                int count = onlineCount.intValue();
                onlineCount = new Integer(count+1);
            }
    
            context.setAttribute("OnlineCount",onlineCount);
        }
    
        //销毁session监听
        //一旦销毁session就会触发这个事件
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            ServletContext context = se.getSession().getServletContext();
            Integer onlineCount = (Integer) context.getAttribute("OnlineCount");
            if (onlineCount==null){
                onlineCount = new Integer(0);
            }else {
                int count = onlineCount.intValue();
                onlineCount = new Integer(count-1);
            }
    
            context.setAttribute("OnlineCount",onlineCount);
        }
    
        /*
        1.手动销毁  getSession().invalidate();
        2.自动销毁  在web.xml配置
        */
    
    
    }
    
    

    回忆session销毁

    1. 手动销毁 getSession().invalidate();
    2. 自动销毁 在web.xml配置
        <session-config>
            <session-timeout>1</session-timeout>
        </session-config>
    
  2. web.xml中配置监听器

    <!--注册监听器-->
    <listener>
        <listener-class>com.sgl.listener.OnlineCountListener</listener-class>
    </listener>

index.jsp

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

<h1>当前有 <span style="color: blue"><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人在线</h1>

</body>
</html>

效果:

在这里插入图片描述

过滤器 监听器的常见应用

监听器:GUI中经常使用

package com.sgl.listener;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class TestPanel {
    public static void main(String[] args) {
        Frame frame = new Frame("中秋节快乐"); //新建一个窗口
        Panel panel = new Panel(null);  //面板

        frame.setLayout(null);//设置窗体的布局
        frame.setBounds(300,300,500,500);
        frame.setBackground(new Color(0,0,0));//设置背景颜色

        panel.setBounds(50,50,300,300);
        panel.setBackground(new Color(0,25,26));

        frame.add(panel);
        frame.setVisible(true);

        //监听事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
                System.exit(1);
            }
        });
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等慢慢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值