JavaWeb

385 阅读23分钟

Web

基本概念

​ Web,网页的意思。

  • 静态web
    • html+css
    • 提供给所有人看的数据始终不会变化
  • 动态web
    • 几乎所有的网站
    • 提供给不同人看的数据会不同,每个人在不同时间地点看到的内容不同。
    • 技术栈:Servlet/JSP,ASP,PHP

在Java中,动态web资源开发的技术统称为JavaWeb。

web应用程序

web应用程序:可以提供浏览器访问的程序。

  • Web应用程序是由多个Servlet、JSP页面、HTML文件以及图像文件等组成。
  • 能访问到的任何资源都在世界的某台服务器上。
  • 这些统一的web资源会被放在同一个文件夹下
  • 一个Web应用程序组成部分:
    • Html,CSS,JavaScript
    • JSP,Servlet
    • Java程序
    • jar包
    • 配置文件(Properties)

web应用程序编写完毕后,若想要提供给外界访问:需要一个服务器。

静态web

image.png

缺点:

  • 页面无法动态更新,所有用户看到相同界面
    • 可以通过JS实现伪动态交互,如轮播图。
  • 无法和数据库交互(无法持久化数据)

动态web

​ web页面展示的效果因人而异,淘宝千人千面。

image.png

缺点

  • 假如服务器的动态web资源出现异常,需要重新编写后台程序
    • 停机维护

Web服务器

技术讲解

  • ASP
    • 微软:国内最早流行
    • 在HTML中嵌入了VB脚本,耦合度极高,维护成本高
    • ASP做前台页面,后台使用VB COM+组件对数据进行操作
    • 现在基本用C#编写,IIS发布
  • PHP
    • 开发速度快,功能很强大,跨平台代码简单
    • 无法承载大访问量,但是国内基本都是中小型网站,所以目前依旧应用广泛
  • JSP/Servlet
    • Sun公司主推的B/S架构
    • 基于Java语言(所有的大公司,或者一些开源组件都是Java编写的)
    • 可以承载高并发、高可用、高性能带来的影响
    • 语法像ASP,有利于ASP转JSP,抢占市场

Web服务器

服务器是一种被动操作,用来处理用户请求和相应用户新消息。

  • IIS
    • 微软windows系统自带
  • Tomcat
    • Tomcat是Apache 软件基金会的Jakarta 项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。
    • 因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
    • Tomcat 实际上运行JSP 页面和Servlet。
  • ...

Tomcat

安装运行

Tomcat官网

image.png

  1. 下载完后解压

    image.png

  2. 新建系统变量CATALINA_HOME,值为解压后的(上图中的)E:\apache-tomcat-9.0.40

  3. 加入Path,%CATALINA_HOME%\bin%CATALINA_HOME%\lib

  4. 点击bin\startup.bat,出现控制台,访问http://localhost:8080/

    image.png

  5. 退出:Ctrl+C、关闭窗口或点击bin\shutdown.bat

配置文件

​ 配置文件均在conf文件夹下。

  • server.xml 服务器配置

    <!-- 仅放部分配置信息 -->
    <!-- 配置端口号 主机名:8080-->
    <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
    <!-- name主机名 localhost:端口号 若改为某个域名 需要修改hosts文件 -->
    <!-- appBase网站资源存放的目录 自动访问的是webapps/ROOT -->
    <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
    	...
    </Host>
    

面试题

网站是如何进行访问的?

  1. 浏览器访问域名
  2. 查看本机host(C:\Windows\System32\drivers\etc)文件中有没有该域名对应的ip
    • 有:直接访问该ip
    • 没有:去DNS(域名解析服务器)中查找该域名对应的ip并访问,若找不到则访问失败

发布网站

  • webapps是存放网站资源的目录,只要把自己的网站文件夹放入webapps中即可
  • 通过http://localhost:8080/网站文件夹名访问,会默认访问你的index.html
  • 若没有 index.html,则 http://localhost:8080/网站文件夹名/自定义.html
- webapps
    //默认存在的网站
	- ROOT	// http://localhost:8080
	- docs	// http://localhost:8080/docs 以下类推
	- examples
	- host-manager
	- manager
    //自己的网站
	- mywebsite	//http://localhost:8080/mywebsite
    	- WEB-INF
    		- classes //java程序
    		- lib	  //依赖包
    		- web.xml //网站配置
    	- index.html	//默认首页
    	- static	  //静态资源
    		- css
    		- js
    		- img

HTTP

HTTP是什么

​ HTTP(HyperText Transfer Protocol,超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。

  • 超文本是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本。
  • 端口:80

​ HTTPS(Hyper Text Transfer Protocol over SecureSocket Layer,安全超文本传输协议)

  • 是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性,HTTPS 在HTTP 的基础下加入SSL 层,HTTPS 的安全基础是 SSL。

  • 端口号:443

两个时代

  1. HTTP/1.0
    • 客户端可以与web服务器连接后,只能获得一个web资源就断开
  2. HTTP/1.1
    • 客户端可以与web服务器连接后,可以获得多个web资源

HTTP请求与响应

​ 以访问百度为例,打开浏览器,按F12打开开发者工具,访问百度网址。

image.png

综合体

Request URL: https://www.baidu.com/ #请求的URL
Request Method: GET	#请求方法
Status Code: 200 OK	# 状态码
Remote Address: 127.0.0.1:1080	 #远程地址
Referrer Policy: strict-origin-when-cross-origin

GET和POST

GETPOST
后退/刷新无害数据会被重新提交(浏览器应该告知用户数据会被重新提交)。
书签可收藏为书签不可收藏为书签
缓存能被缓存不能缓存
编码类型application/x-www-form-urlencodedapplication/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。
历史参数保留在浏览器历史中。参数不会保存在浏览器历史中。
对数据长度的限制是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。无限制。
对数据类型的限制只允许 ASCII 字符。没有限制。也允许二进制数据。
安全性与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET !POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。
可见性数据在 URL 中对所有人都是可见的。数据不会显示在 URL 中。

状态码

  • 1XX:信息,服务器收到请求,需要请求者继续执行操作
  • 2XX:成功,操作被成功接收并处理
  • 3XX:重定向,需要进一步的操作以完成请求
  • 4XX:客户端错误,请求包含语法错误或无法完成请求
  • 5XX:服务器错误,服务器在处理请求的过程中发生了错误

状态码详细表

请求头

#展示部分
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 #接受的数据类型
Accept-Encoding: gzip, deflate, br #告诉服务器 支持的编码
Accept-Language: zh-CN,zh;q=0.9	#告诉服务器 支持的语言
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Cache-Control: no-cache # 缓存控制
Connection: keep-alive	# 请求完成连接保持
Cookie: #过长省略
Host: www.baidu.com	#主机名百度
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 #客户端信息

响应头

Cache-Control: private
Connection: keep-alive
Content-Type: text/html;charset=utf-8
Date: Wed, 09 Dec 2020 08:47:38 GMT #时间
Expires: Wed, 09 Dec 2020 08:47:37 GMT	#过期时间

Maven

​ 在JavaWeb开发中,需要使用大量的jar包,我们手动去导入,Maven可以帮助我们自动导入包。

​ Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。

Maven核心思想:约定大于配置

  • 有约束,不要去违反

安装运行

Maven官网

image.png

  1. 下载解压

  2. 环境变量

    • MAVEN_HOME:Maven目录
    • M2_HOME:Maven目录下的bin目录
    • Path中添加%MAVEN_HOME%\bin也可以直接%M2_HOME%,只要指向的是bin目录即可
  3. 打开CMD,测试

    mvn -version
    

配置阿里云镜像

​ Maven的默认仓库是国外的,要么翻墙,要么下载速度很慢,所以将仓库改为阿里云的国内仓库。

  • 打开conf\settings.xml(以下是删除所有注释后的内容)

  • mirrors标签中插入以下配置

<!-- 阿里云仓库 -->
<mirror>
    <id>alimaven</id>
    <mirrorOf>central</mirrorOf>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>

<!-- 中央仓库1 -->
<mirror>
    <id>repo1</id>
    <mirrorOf>central</mirrorOf>
    <name>Human Readable Name for this Mirror.</name>
    <url>http://repo1.maven.org/maven2/</url>
</mirror>

<!-- 中央仓库2 -->
<mirror>
    <id>repo2</id>
    <mirrorOf>central</mirrorOf>
    <name>Human Readable Name for this Mirror.</name>
    <url>http://repo2.maven.org/maven2/</url>
</mirror>

本地仓库

<!-- settings.xml下加入 路径自定义 以后包都会放在这个目录下 -->
<localRepository>E:\apache-maven-3.6.3\maven-repo</localRepository>

settings.xml的最终配置

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <localRepository>
        E:\apache-maven-3.6.3\maven-repo
    </localRepository>
    <pluginGroups>

    </pluginGroups>
    <proxies>

    </proxies>
    <servers>

    </servers>
    <mirrors>
        <!-- 阿里云仓库 -->
        <mirror>
            <id>alimaven</id>
            <mirrorOf>central</mirrorOf>
            <name>aliyun maven</name>
            <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
        </mirror>

        <!-- 中央仓库1 -->
        <mirror>
            <id>repo1</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo1.maven.org/maven2/</url>
        </mirror>

        <!-- 中央仓库2 -->
        <mirror>
            <id>repo2</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo2.maven.org/maven2/</url>
        </mirror>
    </mirrors>
    <profiles>

    </profiles>
</settings>

在IDEA中使用Maven

使用模板

  1. 创建Maven项目

    image.png

    image.png

    image.png

    image.png

  2. 勾选自动导入包

image.png

  1. 本地仓库的变化

    image.png

  2. 创建完后的注意事项,改完后可以在File—Other Settings—Settings for New Projects再设置,一劳永逸

    image.png

    image.png

  3. 使用模板的项目结构

    image.png

不使用模板

  1. 不勾选模板

    image.png

  2. 组名项目名

    image.png

  3. 直接最后一步

    image.png

  4. 干净纯粹的maven项目结构(这里可以选择做别的项目了)

    image.png

  5. 手动添加web框架,右键项目名

    image.png

  6. 勾选Web Application

    image.png

  7. 效果

    image.png

拓展:文件夹标记

文件夹标记会影响右键创建文件类型的选项。

image.png

image.png

添加Tomcat

image.png

image.png

image.png

image.png

image.png

image.png

pom文件

maven项目结构

image.png

  • clean命令的使用

    • Tomcat运行网站后,会生成一个target文件夹,相当于打包好的项目

      image.png

    • 双击clean可以删除target文件夹

  • 依赖关系图

    image.png

pom.xml配置解析

<?xml version="1.0" encoding="UTF-8"?>
<!-- xml的命名空间 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
<!-- 之前配置的 -->
  <groupId>com.volcano</groupId>
  <artifactId>javaweb-01-maven</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!-- 项目打包方式
   1:jar java程序
   2:war JavaWeb程序
   -->
  <packaging>war</packaging>
  <!-- 没什么用的东西 -->
  <name>javaweb-01-maven Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>
<!-- 配置 -->
  <properties>
    <!-- 项目构建编码 -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- 编译版本 -->
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
<!-- 项目依赖 -->
  <dependencies>
    <!-- 具体依赖项 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
    
<!-- 构建项目需要用的东西 这里是模板需要的,可以全部删除,所以不推荐使用模板创建maven,建议添加自行需要 -->
    
  <build>
    <finalName>javaweb-01-maven</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
        
      <!-- 插件 -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

使用

Maven仓库

  1. 在Maven仓库中寻找需要的包

  2. 复制Maven代码到pom.xml中的denpencies

    image.png

  3. Maven会自动下载这个包,Maven的高级之处在于会自动导入该包所依赖的包

可能遇到的问题

  • maven版本和IDEA版本不匹配,使用低版本maven可解决,记得修改上文提及配置和环境变量

    • 本文IDEA2018.2.4,Maven3.6.3,遇到此问题,将Maven版本换为3.5.4成功解决

      image.png

  • 由于Maven的核心思想:约定大于配置,会遇到的问题之一就是,java写了java代码之外的文件,比如.properties.xml等等,这些在项目导出时会被忽略,因为约定java目录只写java文件

    • 解决方法:修改pom.xml的build配置

      <build>
          <resources>
              <resource>
                  <!-- 允许src/main/resources包括includes节点中的文件类型 -->
                  <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>
      
  • 修改web.xml的最佳版本

    • IDEA自动生成的web.xml内容

      <!DOCTYPE web-app PUBLIC
       "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
       "http://java.sun.com/dtd/web-app_2_3.dtd" >
      
      <web-app>
        <display-name>Archetype Created Web Application</display-name>
      </web-app>
      
    • Tomcat的ROOT的web.xml

      <?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"
        metadata-complete="true">
      
        <display-name>Welcome to Tomcat</display-name>
        <description>
           Welcome to Tomcat
        </description>
      
      </web-app>
      
    • 最好与Tomcat的一致,避免出现后续问题

  • Tomcat 控制台乱码

Servlet

简介

  • Servlet就是Sun公司开发动态web的一门技术
  • Sun公司在这些API中提供一个接口叫做Servlet,要开发一个Servlet程序,需要两步
    • 编写一个类,实现Servlet接口
    • 把开发好的Java类部署到web服务器上
  • 实现了Servlet接口的Java程序叫做,Servlet

HelloServlet

前提准备和解释

  1. 新建一个不使用模板的Maven项目,删除里面的src目录,一个空的Maven项目,我们可以创建不同的module来对应一个子项目,这些项目都共用一个pom.xml中的依赖,不用新建项目再重新各种导入。

  2. 右键主项目根目录,创建新module,使用webapp的模板,这个module相当于一个子项目,有自己的结构,如下(自行创建java和resources文件夹并标记,修改web.xml结构为最新):

    image.png

  3. 在主项目的pom.xml中会有如下变化

    <modules>
        <module>servlet01</module>
    </modules>
    
  4. 子项目的pom.xml中的对应结构

    <parent>
        <artifactId>javaweb-02-maven</artifactId>
        <groupId>com.volcano</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    
  5. 子项目中的包和java程序只能给子项目用,主项目的包和java程序可以给子项目用。

开始编写

  1. 导入Servlet的两个依赖包

    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
    
    </dependencies>
    
  2. 创建一个类实现HttpServlet接口

    • Sun公司有两个默认的Servlet接口:HttpServlet、GenericServlet
    • 继承关系为:Servlet—>GenericServlet—>HttpServlet—>自己的类
    import javax.servlet.ServletException;
    import javax.servlet.ServletInputStream;
    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 HelloServlet extends HttpServlet {
        //由于get和post只是请求实现的不同方式,可以互相调用,业务逻辑都一样
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //响应流
            PrintWriter writer = resp.getWriter();
            writer.write("Hello Servlet");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  3. 编写Servlet的映射

    • 为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,浏览器连接web服务器,所以需要在web服务器中注册写好的Servlet,给他一个浏览器能够访问的路径。
    • 映射需要在web.xml中配置。
    <!-- 注册Servlet -->
    <servlet>
        <servlet-name>hello</servlet-name>
        <!-- 一个Servlet对应一个Servlet实现类 -->
        <servlet-class>com.volcano.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <!-- 给一个访问地址 -->
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  4. 配置Tomcat(前文提及),虚拟路径设置为/servlet01

    image.png

  5. 运行测试 http://localhost:8080/servlet01/hello

    image.png

Servlet原理

  1. 前文提过,Servlet就是一个接口,那么接口就是定义一个规范。其中只有5个方法

    void init(ServletConfig var1) throws ServletException;
    
    ServletConfig getServletConfig();
    
    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    
    String getServletInfo();
    
    void destroy();
    
  2. 不论是HttpServlet和GenericServlet都只是基于Servlet的规范,进一步完成了初始化、获得信息、配置、处理请求和销毁的具体实现。

  3. 我们自己的类继承于HttpServlet,HttpServlet基本上帮我们做了除了处理请求之外的所有事情,我们可以专注于业务。

  4. Servlet不会和客户端打交道,因为我们没有在使用Servlet的时候监听端口,所以客户端来的请求不能直接到达Servlet,而是通过Tomcat这个web容器。

  5. Tomcat直接和客户端打交道,监听了端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端。

image.png

Mapping

  • 一个Servlet可以映射一个或多个url-pattern

    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.volcano.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    
  • Servlet映射url-pattern可以使用通配符

    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.volcano.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
      	<!-- 不建议使用 会覆盖index.jsp的访问路径 -->  
        <!-- <url-pattern>/*</url-pattern> -->  
    </servlet-mapping>
    
  • Servlet映射url-pattern可以使用后缀

    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.volcano.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <!-- *前不能有/ 但是输入的内容中*可以包含/ -->
        <url-pattern>*.vol</url-pattern>
    </servlet-mapping>
    
  • 优先级

    • 明确的url>通配符url

ServletContext

​ ServletContext,即Servlet上下文,运行一个web程序,就会有一个ServletContext,凌驾于所有Servlet之上,实现各个Servlet之间的数据通信等功能。

数据通信

​ 新建一个servlet02的module,按照之前的操作优化一下结构和内容,记得把Tomcat中的虚拟路径映射改为/servlet02。

​ 由于之前Tomcat打包的内容是servlet01,所以将01移除加入02,仅加入02,如果加其他的会被一起打包,没有必要。

image.png

  1. 目录结构

    image.png

  2. HelloServlet中的内容

    package com.volcano.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 HelloServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            PrintWriter writer = resp.getWriter();
            writer.write("Hello,Servlet");
            //获得ServletContext
            ServletContext context = this.getServletContext();
            //设置属性
            context.setAttribute("username","灿大帅");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  3. HelloServletContext中的内容

    package com.volcano.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 HelloServletContext extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setCharacterEncoding("utf8");
            resp.setContentType("text/html");
            PrintWriter writer = resp.getWriter();
            //获得ServletContext
            ServletContext context = this.getServletContext();
            //获得属性
            String username = (String) context.getAttribute("username");
            //显示
            writer.write("<h1>用户名:"+username+"</h1>");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  4. web.xml,仅放servlet部分

    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.volcano.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>username</servlet-name>
        <servlet-class>com.volcano.servlet.HelloServletContext</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>username</servlet-name>
        <url-pattern>/username</url-pattern>
    </servlet-mapping>
    
  5. 注意事项

    1. 因为在给ServletContext设置属性是在处理/hello中进行的,所以要先访问/hello,再访问/username
    2. 设置响应头很重要,不然会是乱码或者响应内容会变成文件被下载
  6. 效果

    image.png

获得初始化数据

  1. 配置初始化数据

    1. 在web.xml中

      <context-param>
          <param-name>url</param-name>
          <param-value>jdbc:mysql//localhost:3306/jdbcstudy</param-value>
      </context-param>
      
    2. 在java代码中

      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          PrintWriter writer = resp.getWriter();
          //获得ServletContext
          ServletContext context = this.getServletContext();
          //配置初始化数据
      context.setInitParameter("url","jdbc:mysql//localhost:3306/jdbcstudy");
      }
      
  2. 得到数据

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        //获得ServletContext
        ServletContext context = this.getServletContext();
        //获取数据
    	String initParm = context.getInitParameter("url");
        //显示
        writer.write("<h1>url:"+initParm+"</h1>");
    }
    

转发

  1. HelloServletContext中的内容

    public class HelloServletContext extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setCharacterEncoding("utf8");
            resp.setContentType("text/html");
            PrintWriter writer = resp.getWriter();
            //获得ServletContext
            ServletContext context = this.getServletContext();
            //一旦访问的请求到这个Servlet就会被 转发到 /disp
            context.getRequestDispatcher("/disp").forward(req,resp);
        }
    
  2. 新建HelloDispatcher类中的内容

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().print("I got it");
    }
    
  3. web.xml

    <servlet>
        <servlet-name>disp</servlet-name>
        <servlet-class>com.volcano.servlet.HelloDispather</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>disp</servlet-name>
        <url-pattern>/disp</url-pattern>
    </servlet-mapping>
    

读取资源文件

  1. 在java和resources目录下新建一个.properties文件

  2. 发现打包后,java下的.properties文件未被导出,而resources下的文件被导出在classes目录下,我们称该路径为classpath

    image.png

所以要回到Maven—可能遇到的问题

配置之后,java下的.properties也被打包了。

image.png

读取资源要用到打包后的项目相对路径。

  1. db.properties

    username=root
    password=123456
    
  2. 新建ReadProperties类

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = req.getServletContext();
        //注意用的是导出后的项目相对路径
        InputStream stream = context.getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties properties = new Properties();
        properties.load(stream);
        String username = properties.getProperty("username");
        String password = properties.getProperty("username");
        resp.getWriter().print(username+":"+password);
    }
    
  3. web.xml

    <servlet>
        <servlet-name>getinfo</servlet-name>
        <servlet-class>com.volcano.servlet.ReadProperties</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getinfo</servlet-name>
        <url-pattern>/getinfo</url-pattern>
    </servlet-mapping>
    
  4. 结果

    image.png

HttpServletResponse

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

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

分类

  • 向浏览器发送数据的方法

    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 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);
    
  • 状态码常量:状态码详细表

常见应用

  • 向浏览器输出信息

  • 下载文件(web.xml已配置)

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取下载文件的真实路径,是打包好后的路径
        String realPath = "F:\\云\\Code\\JavaWeb\\javaweb-02-maven\\response\\target\\response\\WEB-INF\\classes\\家教壁纸.jpg";
        System.out.println(realPath);
        //2.获取文件名
        String filename = realPath.substring(realPath.lastIndexOf('\\')+1);
        System.out.println(filename);
        //3.文件输入流
        FileInputStream in = new FileInputStream(realPath);
        //4.响应文件输出流
        ServletOutputStream out = resp.getOutputStream();
        //5.设置下载文件的响应头,设置编码,避免中文乱码
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
        //6.输出文件
        int len=0;
        byte[] buffer=new byte[1024];
        while((len=in.read(buffer))>0){
            out.write(buffer,0,len);
        }
        out.close();
        in.close();
    }
    
  • 验证码(web.xml已配置)

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置浏览器每3秒刷新一次
        resp.setHeader("refresh","3");
        //1.在内存画一张图
        BufferedImage image = new BufferedImage(80,40,BufferedImage.TYPE_INT_RGB);
        //2.获取画笔
        Graphics2D graphics = (Graphics2D) image.getGraphics();
        //3.设置背景
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0,0,80,40);
        //4.画随机数
        graphics.setColor(Color.BLUE);
        graphics.drawString(createRandom(),20,20);
        //5.设置响应头
        //返回数据类型 jpg 图片
        resp.setHeader("Content-Type","image/jpg");
        //不缓存
        resp.setHeader("expires","-1");
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");
        ImageIO.write(image,"jpg",resp.getOutputStream());
    }
    
  • 重定向(重要)

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
            * 重定向本质
            * resp.setStatus(302);
            * resp.setHeader("Location","/response/vercode");
            * */
        resp.sendRedirect("/response/vercode");
    }
    
  • 重定向和转发的相同点和区别

    • 相同点
      • 页面都会跳转
    • 不同点
      • 转发页面URL不会变,重定向会变
      • 转发的url中/代表当前项目,重定向中需要当前项目的路径
      • 转发(307)
      • image.png
      • 重定向(302)
      • image.png

HttpServletRequest

​ HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息会被封装到HttpServletRequest,通过HttpServletRequest的方法,获得客户端的所有信息。

常见应用

  • 获取Request数据

    • 首次开始使用JSP页面,切记已经导入javax.servlet.jsp-api这个包
    <%-- index.jsp --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <body>
    <%-- 在JSP中,${}中可以编写java代码,这里是获取网站的根目录 --%>
    <form action="${pageContext.request.contextPath}/dealform" method="post">
        用户名:<input type="text" name="username"> <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="乒乓球">乒乓球
        <br>
        <input type="submit">
    </form>
    </body>
    </html>
    
    <%-- success.jsp --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Success</title>
    </head>
    <body>
    <h2>登录成功</h2>
    </body>
    </html>
    
    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(Arrays.toString(hobbies));
        System.out.println(username);
        System.out.println(password);
        //转发时, / 就已经代表着当前项目
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
    }
    

image.png

Cookie和Session

  • Cookie
    • 客户端技术
    • 存放键值对,只能是字符串
    • 每个浏览器的存放上限不同
    • 每个大小4KB左右
    • 录取证书,证明我是这里的学生
  • Session
    • 服务端技术
    • 服务端对每个访问它的浏览器一个Session,默认浏览器关闭失效
    • Session可以存放对象
    • Sessionid一般通过cookie返回
    • 学校登记过,证明我是这里的学生

Cookie

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;Charset=utf-8;");
    PrintWriter writer = resp.getWriter();
    //获取请求中的Cookies
    Cookie[] cookies = req.getCookies();
    System.out.println(Arrays.toString(cookies));
    if(cookies!=null){
        writer.write("最近一次访问是在:");
        for(Cookie cookie:cookies){
            //获得cookie的key
            if("lastLoginTime".equals(cookie.getName())){
                //获得cookie的value
                long timestamp = Long.parseLong(cookie.getValue());
                writer.write((new Date(timestamp)).toLocaleString());
            }
        }
    }
    //响应添加cookie,cookie只能存字符串
    //每次访问都给一个新的Cookie存放这次的访问时间戳
    Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
    //设置过期时间,单位 秒
    //经测试 -1 或 不设置 浏览器关闭则过期
    //0 马上过期(不会有显示的机会)
    //cookie.setMaxAge(0);
    resp.addCookie(cookie);
}

image.png

Session

//getSession
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8;");
    //获得session对象
    HttpSession session = req.getSession();
    //获得sessionid
    String sessionId = session.getId();
    PrintWriter writer = resp.getWriter();
    //获得session中的属性
    Person person = (Person) session.getAttribute("Person");
    if(person==null){
        writer.write("SessionID:"+sessionId);
    }else {
        writer.write("SessionID:"+sessionId+"<br>"+person.getName());
    }
}
//setSession
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    HttpSession session = req.getSession();
    Person person = new Person("volcano","男",21);
    //设置Session中的属性
    session.setAttribute("Person",person);
}
//clearSession
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    HttpSession session = req.getSession();
    //另Session失效
    session.invalidate();
}
<!-- web.xml -->
<session-config>
    <!-- Session自动过期时间 单位分钟 -->
    <session-timeout>60</session-timeout>
</session-config>

image.png

JSP

JSP是什么

​ JSP(Java Server Pages),Java服务端页面,属于动态web技术。

​ 特点:HTML中可以嵌入Java代码

JSP原理

  1. 每当用IDEA中的Tomcat生成一个网站,就会在本机的C:\Users\当前用户名\.IntelliJIdeaXXXX.x\system\tomcat\Unnamed_项目名中生成一个work目录。

  2. \work\Catalina\localhost\ROOT\org\apache\jsp该目录下存在着index_jsp.java

    image.png

  3. 查看源码后发现:JSP的本质就是一个Servlet,其实不管浏览器向服务器发送什么请,都是访问了某个Servlet

    1. 继承和实现关系index_jsp——>HttpJspBase——>HttpServlet

    2. JSP内置对象都可以在这个Java文件中找到

      final javax.servlet.jsp.PageContext pageContext;
      javax.servlet.http.HttpSession session = null;	//session
      final javax.servlet.ServletContext application;	//ServletContext
      final javax.servlet.ServletConfig config;
      javax.servlet.jsp.JspWriter out = null;	//JspWriter
      final java.lang.Object page = this;
      javax.servlet.jsp.JspWriter _jspx_out = null;
      javax.servlet.jsp.PageContext _jspx_page_context = null;
      
    3. 在JSP中填写HTML代码其实都是Java代码输出的

      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中显示的HTML标签
      out.write("<html>\n");
      out.write("<body>\n");
      out.write("<h2>Hello World!</h2>\n");
      out.write("</body>\n");
      out.write("</html>\n");
      
    4. 每当重新运行一次Tomcat,work目录都会被销毁,运行完毕之后会重新生成一个work目录,其中的XXX_jsp.java,会随着页面的访问而增加,不访问不会被转换为Java类

JSP基础语法

​ JSP中除了HTML标签,还有自己独有的语法,支持所有Java代码。

准备

<dependencies>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/taglibs/standard -->
    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>
</dependencies>

语法

  • JSP表达式

    <!-- <%= 变量或表达式%> -->
    <%= new java.util.Date()%>
    <!-- 等价于 -->
    <jsp:expression>
       表达式
    </jsp:expression>
    <!-- 可以用EL表达式替代 -->
    <!-- 若值为null则el表达式不会显示,而jsp表达式会显示null -->
    ${new java.util.Date()}
    
  • JSP脚本片段

    <%
    int sum = 0;
    for (int i = 0; i < 10 ; i++) {
        //out 内置对象
        out.write(i+"<br>");
    }
    %>
    
  • Java嵌套Html

    <%
        int sum = 0;
        for (int i = 0; i < 10 ; i++) {
            %>
        <p>Hello,World <%=i%></p>
        <%
        }
    %>
    
  • JSP声明

    • 上面的几个嵌入的代码都是在XXX_jsp.java中的public void _jspService()的方法体中,方法体中无法定义方法和定义全局变量
      <%!
        static {
          System.out.println("进入static");
        }
        int globalint = 10;
        public void mymethod(){
          System.out.println(globalint);
        }
      %>
      <%
        //调用要在这里
        mymethod();
      %>
    
  • JSP注释

    <%-- 
    	JSP注释不会出现JSP源码中
    --%>
    <!-- HTML注释 会出现浏览器源码中 -->
    

JSP指令

  • page

    • import

      <%@page import="java.util.*" %>
      
    • errorPage

      <!-- 如果页面报错,则转到404.jsp -->
      <%@page errorPage="404.jsp" %>
      
    • ...

  • include

  <!-- 抽取页面公共部分  header.jsp和footer.jsp -->
<!-- 本质:将这两个jsp文件的内容 write 在一起 本质是写到一个页面 -->
  <%@include file="header.jsp" %>
<h2>
      我是主内容
  </h2>
  <%@include file="footer.jsp" %>
<!-- 类似 注意需要最前面要加/ -->
<!-- 本质:读取了文件 并且拼接,本质还是多个jsp -->
<jsp:include page="/header.jsp"/>
  • taglib

九大内置对象

对象描述
requestHttpServletRequest类的实例
responseHttpServletResponse类的实例
outPrintWriter类的实例,用于把结果输出至网页上
sessionHttpSession类的实例
applicationServletContext类的实例,与应用上下文有关
configServletConfig类的实例
pageContextPageContext类的实例,提供对JSP页面所有对象以及命名空间的访问
page类似于Java类中的this关键字
exceptionexception 类的对象,代表发生错误的 JSP 页面中对应的异常对象

存储功能、作用域

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    pageContext.setAttribute("name1","volcano1");//仅在这个页面有效
    request.setAttribute("name3","volcano3");//在请求转发中有效
    session.setAttribute("name2","volcano2");//在一次会话中有效,默认浏览器关闭前有效
    application.setAttribute("name4","volcano4");//在服务器中有效,服务器关闭前有效
%>
<%
    //findAttribute 一层一层找pageContext->request->session->application
    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");//null
    //转发功能,等价于 request.getRequestDispatcher("/index.jsp").forward(request,response);
    pageContext.forward("/index.jsp");
%>
<h2>${name1}</h2>
<h2>${name2}</h2>
<h2>${name3}</h2>
<h2>${name4}</h2>
<%-- 不显示 --%>
<h2>${name5}</h2>
</body>
</html>

JSP行为、JSTL标签、EL表达式

JSP行为

语法描述
jsp:include用于在当前页面中包含静态或动态资源
jsp:useBean寻找和初始化一个JavaBean组件
jsp:setProperty设置 JavaBean组件的值
jsp:getProperty将 JavaBean组件的值插入到 output中
jsp:forward从一个JSP文件向另一个文件传递一个包含用户请求的request对象
jsp:plugin用于在生成的HTML页面中包含Applet和JavaBean对象
jsp:element动态创建一个XML元素
jsp:attribute定义动态创建的XML元素的属性
jsp:body定义动态创建的XML元素的主体
jsp:text用于封装模板数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<jsp:forward page="jspforward.jsp">
    <%-- 携带request参数 --%>
    <jsp:param name="name" value="volcano"/>
    <jsp:param name="age" value="21"/>
</jsp:forward>
</body>
</html>

JSTL标签

​ JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。

使用步骤

  1. 导入jstl和standard(后两个)

  2. JSP页面中引入(核心库)

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
  3. 若失败了,试着把这两个包也放入Tomcat的lib中

核心库

  • 引入

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
标签描述
<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

格式化、SQL、XML、JSTL函数

菜鸟教程

JavaBean

JavaBean就是一个实体类,JavaBean 具有以下特征:

  • 提供一个默认的无参构造函数。
  • 需要被序列化并且实现了 Serializable 接口。
  • 有一系列可读写属性。
  • 有一系列的 getter 或 setter 方法。

一般用来和数据库的字段做映射:ORM(Object Relational Mapping,对象关系映射)

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

数据库有这么一张表People

idnamebirthday
1volcano1995/5/5
2LLY2000/10/24
3ZX2005/8/10

需要一个实体类进行映射,字段一一对应属性

package com.volcano.entity;

import java.util.Date;

public class People {
    private int id;
    private String name;
    private Date birthday;

    public People() {
    }

    public People(int id, String name, Date birthday) {
        this.id = id;
        this.name = name;
        this.birthday = birthday;
    }

    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 Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
<%@ page import="java.util.Date" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    //等价于这些代码
    /*
        People people = new People();
        people.setId(1);
        people.getId();
    */
%>
    <jsp:useBean id="people" class="com.volcano.entity.People" scope="page"/>
    <jsp:setProperty name="people" property="id" value="1"/>
    <jsp:setProperty name="people" property="name" value="volcano"/>
    <jsp:setProperty name="people" property="birthday" value="<%=new Date(1995,5,5)%>"/>

id:<jsp:getProperty name="people" property="id"/>
    <br>
姓名:<jsp:getProperty name="people" property="name"/>
    <br>
生日:<jsp:getProperty name="people" property="birthday"/>
</body>
</html>

MVC三层架构

M:Model

V:View

C:Controller

image.png

Filter

过滤器,用来过滤网站的数据和请求。

  • 处理中文乱码
  • 过滤垃圾请求

使用

  1. 依旧是那四个包

  2. 目录结构

    image.png

  3. EncodingFilter

    package com.volcano.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    //这里实现的Filter必须是javax.servlet下的
    public class EncodingFilter implements Filter {
        //服务器启动时就会被初始化
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("过滤器初始化");
        }
    
        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;");
    
            //必须要有这一段代码,把Request和Response对象传递下去
            //传递给下一个过滤器或者给处理的Servlet
            //不写的话,这个过滤器无效
            System.out.println("过滤前");
            filterChain.doFilter(servletRequest,servletResponse);
            System.out.println("过滤后");
    
        }
        //服务器关闭时销毁
        public void destroy() {
            System.out.println("过滤器被销毁");
        }
    }
    
  4. FilteredServlet

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("你好,过滤器");
    }
    
  5. web.xml

    <servlet>
        <servlet-name>filtered</servlet-name>
        <servlet-class>com.volcano.servlet.FilteredServlet</servlet-class>
    </servlet>
    <!-- 只过滤指定url的Servlet -->
    <servlet-mapping>
        <servlet-name>filtered</servlet-name>
        <url-pattern>/filtered</url-pattern>
    </servlet-mapping>
    <!-- 这里的一个Servlet映射了两个路径,一个用来过滤,一个不过滤 -->
    <servlet-mapping>
        <servlet-name>filtered</servlet-name>
        <url-pattern>/unfiltered</url-pattern>
    </servlet-mapping>
    
    <!-- 过滤器设置,和Servlet大同小异 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>com.volcano.filter.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <!-- 不仅可以指定url 也可以直接指定具体Servlet -->
        <!-- <servlet-name>filtered</servlet-name> -->
        <url-pattern>/filtered</url-pattern>
    </filter-mapping>
    
  6. 结果

image.png

监听器

​ 监听一些事件的发生,并且采取一些操作。

​ 由于监听器种类过多,这里只说如何用HttpSessionListener实现在线人数统计。

  1. 目录结构

    image.png

  2. OnlineCountListener

    package com.volcano.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    //实现HttpSessionListener接口,是javax.servlet.http下的
    public class OnlineCountListener implements HttpSessionListener {
        //Session被创建时
        public synchronized void sessionCreated(HttpSessionEvent se) {
            //每当一个Session创建时,在ServletContext中设置属性+1
            ServletContext context = se.getSession().getServletContext();
            System.out.println(se.getSession().getId()+"创建");
            Integer onlineCount = (Integer) context.getAttribute("OnlineCount");
            if(onlineCount==null){
                context.setAttribute("OnlineCount",1);
            }else{
                int count = onlineCount.intValue();
                context.setAttribute("OnlineCount",count+1);
            }
        }
        //Session被销毁时
        public synchronized void sessionDestroyed(HttpSessionEvent se) {
            HttpSession session = se.getSession();
            ServletContext context = session.getServletContext();
            Integer onlineCount = (Integer) context.getAttribute("OnlineCount");
            if(onlineCount==null){
                context.setAttribute("OnlineCount",0);
            }else{
                int count = onlineCount.intValue();
                context.setAttribute("OnlineCount",count-1);
            }
            System.out.println("Session销毁");
        }
    }
    
  3. web.xml

    <!-- listener的注册就这么简单 -->
    <listener>
        <listener-class>com.volcano.listener.OnlineCountListener</listener-class>
    </listener>
    
  4. index.jsp

    <h2>当前在线人数:<%=request.getServletContext().getAttribute("OnlineCount")%></h2>
    
  5. 注意:服务器运行后,因为连接浏览器可能会失败,所以会多连接几次,我们看到的都是成功连接的那一次,但其实已经产生多个了Session,所以数字可能会显示大于1。只要Redeploy重新打包一下就好。

  6. 结果

    image.png