JavaWeb

JavaWeb

1. 基本概念

1.1 前言

web开发:

  • web:网页的意思
    • 静态web:htmlcss等。提供给所有人看到的数据始终不会发生改变!
    • 动态web:ServletJSPASPPHP等。提供给所有人看到的数据始终会发生改变!
    • JavaWeb:在Java中,动态web资源开发的技术统称为JavaWeb

1.2 web应用程序

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

  • *.html等多个web资源,这些web资源可以被外界访问,对外界访问;
  • 这些统一的的web资源会被放在同一个文件夹下,Java常用的web应用程序Tomcat服务器
  • 一个web应用由多部分组成(静态web、动态web)
    • htmlcssjs
    • JSPServlet
    • Java程序
    • jar
    • 配置文件(*.Properties

web应用程序编写完毕后,若想提供给外界访问,则需要一个服务器统一管理;

1.3 静态web

*.htm*.html这些都是网页的后缀,如果服务器上一直存在这些资源,我们就可以直接进行读取;

静态web存在的缺点:

  • web页面无法动态更新,所有用户看到的都是同一个页面;
    • 伪动态:轮播图、点击特效(JavaScriptVBScript);
  • 无法和数据库交互(数据无法持久化,用户无法交互);

1.4 动态web

页面会动态展示:web页面展示的效果因人而异;

动态web存在的缺点:

  • 服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序并重新发布;

动态web存在的优点:

  • web页面可以动态更新,所有用户看到的都不是同一个页面
  • 可以和数据库交互;

2. web服务器

2.1 技术讲解

ASPIIS服务器

  • 微软:国内最早流行的就是ASP
  • HTML中嵌入了VB脚本,ASP+COM;
  • ASP开发中,基本一个页面都有几千行的业务代码,页面极其混乱,维护成本高;

PHP

  • PHP开发速度快,功能很强大,跨平台,代码很简单;
  • 无法承载大访问量的情况,有局限性;

JSP/Servlet

  • sun公司主推的B/S结构
  • 基本Java语言(所有大公司或一些开源的组件,都是用Java写的)
  • 可以承载三高问题带来的影响;
  • 语法像ASP,加强市场强度;

2.2 web服务器

服务器是一种被动的操作,用来处理用户的一些请求和给用户一些相应信息;

IIS:微软公司出品,Windows系统自带;

Tomcat

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,它是最佳的选择。

诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。Tomcat最新版本为10.0.5

Tomcat 实际上运行JSP 页面和Servlet。Tomcat最新版本为10.0.5。

3. Tomcat

Tomcat官网地址:http://tomcat.apache.org/

3.1 Tomcat重要文件夹的作用

  • bin:启动和关闭的脚本文件
  • conf:配置信息
  • lib:依赖的jar
  • logs:日志
  • webapps:网站应用

3.2 Tomcat的启动、关闭与访问测试

  • 启动:执行Tomcat根目录bin文件夹下的startup.bat

  • 关闭:执行Tomcat根目录bin文件夹下的shutdown.bat

  • 访问:执行startup.bat后,在浏览器地址输入:http://localhost:8080/

3.3 Tomcat配置

核心配置文件server.xml

  • 配置启动的端口号:

    Tomcat默认端口号:8080

    MySQL默认端口号:3306

    Oracle默认端口号:1521

    http默认端口号:80

    https默认端口号:443

    <!-- 变更Connector节点的port属性值 -->
    <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
    
  • 配置主机的名称:

    主机的默认名称:localhost

    网站应用的默认存放位置:webapps

    <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
    
  • 高难度面试题:请你谈谈网站是如何进行访问的?

    • 输入一个域名;
    • 检查本机C:\Windows\System32\drivers\etc\hosts配置文件是否存在域名重定向;
      • 存在重定向:返回对应的IP地址,这个地址中存在我们访问的web程序即可直接访问;
      • 不存在重定向:去DNS服务器上寻找IP地址,这个地址中存在我们访问的web程序即可直接访问;

3.4 发布一个web网站

  • 将自己写的网站放到Tomcat中指定的webapps目录下

    -webapps:Tomcat服务器的web目录
        -ROOT
        -examples:网站的目录名
        	-WEB-INF
        		-classes:Java程序
        		-lib:web应用所依赖的jar包
        		-web.xml:网站配置文件
        	-index.html:网站默认首页
        	-static
        		-css:样式文件夹
        		-js:JS文件夹
        		-img:图片文件夹
    

4. HTTP

4.1 什么是HTTP?

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

  • 文本:html,字符串……
  • 超文本:图片、音乐、视频、定位、地图……

4.2 两个时代

  • http 1.0
    • HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接;
  • http 2.0
    • HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源;

4.3 Http请求

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

    以百度为例:

    // General
    Request URL: https://www.baidu.com/	// 请求地址
    Request Method: GET					// 请求方法 GET/POST
    Status Code: 200 OK					// 状态码
    Remote Address: 14.215.177.39:443	// 远程IP地址
    
    // Request Headers
    Accept: text/html					
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9		// 语言
    Connection: keep-alive				// 连接
    

4.3.1 请求行

  • 请求行中的请求方式:GET
  • 请求方式:GETPOST、HEAD、DELETE、PUT、TRACT……
    • GET
      • 请求能够携带的参数比较少
      • 大小有限制
      • 会在浏览器的URL地址栏显示数据内容
      • 不安全但高效
    • POST
      • 请求能够携带的参数没有限制
      • 大小没有有限制
      • 不会在浏览器的URL地址栏显示数据内容
      • 安全但不高效

4.3.2 消息头

  • Accept:告诉浏览器,它所支持的数据类型
  • Accept-Encoding:支持哪种编码格式(GBK、UTF-8、GB2312、ISO8859-1)
  • Accept-Language:告诉浏览器,它的语言环境
  • Connection:告诉浏览器,请求完成是断开还是保持连接
  • HOST:主机

4.4 Http响应

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

    以百度为例:

    // Response Headers
    Bdpagetype: 1
    Bdqid: 0xd33f965d000404bb
    Cache-Control: private					// 缓存控制
    Connection: keep-alive					// 连接
    Content-Encoding: gzip					// 编码格式
    Content-Type: text/html;charset=utf-8	// 类型
    

4.4.1 响应体

  • Accept:告诉浏览器,它所支持的数据类型
  • Accept-Encoding:支持哪种编码格式(GBK、UTF-8、GB2312、ISO8859-1)
  • Accept-Language:告诉浏览器,它的语言环境
  • Connection:告诉浏览器,请求完成是断开还是保持连接
  • HOST:主机
  • Refresh:告诉客户端,多久刷新一次
  • Location:让网页重新定位

4.4.2 响应状态码

  • 200:请求响应成功
  • 3xx:请求重定向
  • 4xx:找不到资源(404)
  • 5xx:服务器代码错误(500、502网关错误)

4.5 常见面试题

当你的浏览器地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?

5. Maven项目架构管理工具

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

  • 有约束,不要违反

Maven会规定好如何编写我们的Java代码,必须按照这个规范来实现;

Maven官网地址:https://maven.apache.org/

5.1 Maven的配置

配置环境变量

  • M2_HOME:Maven目录\bin
  • MAVEN_HOME:Maven目录
  • path%MAVEN_HOME%\bin

核心配置文件server.xml

  • LocalRepository

    • 作用:表示构建系统本地仓库的路径。
    • 默认值:~/.m2/repository
  • InteractiveMode

    • 作用:表示maven是否需要和用户交互以获得输入。如果maven需要和用户交互以获得输入,则设置成true,反之则应为false。
    • 默认值:true
  • UsePluginRegistry:

    • 作用:maven是否需要使用plugin-registry.xml文件来管理插件版本。如果需要让maven使用文件~/.m2/plugin-registry.xml来管理插件版本,则设为true。
    • 默认值:false
  • Offline:

    • 作用:这个属性表示在Maven进行项目编译和部署等操作时是否允许Maven进行联网来下载所需要的信息。如果构建系统需要在离线模式下运行,则为true。(当由于网络设置原因或者安全因素,构建服务器不能连接远程仓库的时候,该配置就十分有用)
    • 默认值:false
  • PluginGroups:

    • 作用:在pluginGroups元素下面可以定义一系列的pluginGroup元素。表示当通过plugin的前缀来解析plugin的时候到哪里寻找。pluginGroup元素指定的是plugingroupId。默认情况下,Maven会自动把org.apache.maven.pluginsorg.codehaus.mojo 添加到pluginGroups下。

      <pluginGroups>
        <!--plugin的组织Id(groupId) -->
        <pluginGroup>org.codehaus.mojo</pluginGroup>
      </pluginGroups>
      
  • Servers:

    • 作用:一般仓库的下载和部署是在pom.xml文件中的repositoriesdistributionManagement 元素中定义的。然而,一般类似用户名、密码(有些仓库访问是需要安全认证的)等信息不应该在pom.xml文件中配置,这些信息可以配置在 settings.xml 中。

      <!--配置服务端的一些设置。一些设置如安全证书不应该和pom.xml一起分发。这种类型的信息应该存在于构建服务器上的settings.xml文件中。 -->
      <servers>
        <!--服务器元素包含配置服务器时需要的信息 -->
        <server>
          <!--这是server的id(注意不是用户登陆的id),该id与distributionManagement中repository元素的id相匹配。 -->
          <id>server001</id>
          <!--鉴权用户名。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。 -->
          <username>my_login</username>
          <!--鉴权密码 。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。密码加密功能已被添加到2.1.0 +。详情请访问密码加密页面 -->
          <password>my_password</password>
          <!--鉴权时使用的私钥位置。和前两个元素类似,私钥位置和私钥密码指定了一个私钥的路径(默认是${user.home}/.ssh/id_dsa)以及如果需要的话,一个密语。将来passphrase和password元素可能会被提取到外部,但目前它们必须在settings.xml文件以纯文本的形式声明。 -->
          <privateKey>${usr.home}/.ssh/id_dsa</privateKey>
          <!--鉴权时使用的私钥密码。 -->
          <passphrase>some_passphrase</passphrase>
          <!--文件被创建时的权限。如果在部署的时候会创建一个仓库文件或者目录,这时候就可以使用权限(permission)。这两个元素合法的值是一个三位数字,其对应了unix文件系统的权限,如664,或者775。 -->
          <filePermissions>664</filePermissions>
          <!--目录被创建时的权限。 -->
          <directoryPermissions>775</directoryPermissions>
        </server>
      </servers>
      
  • Mirrors:

    • 作用:用于定义一系列的远程仓库的镜像。我们可以在pom.xml中定义一个下载工件的时候所使用的远程仓库。但是有时候这个远程仓库会比较忙,所以这个时候人们就想着给它创建镜像以缓解远程仓库的压力,也就是说会把对远程仓库的请求转换到对其镜像地址的请求。每个远程仓库都会有一个id,这样我们就可以创建自己的mirror来关联到该仓库,那么以后需要从远程仓库下载工件的时候Maven就可以从我们定义好的mirror站点来下载,这可以很好的缓解我们远程仓库的压力。在我们定义的mirror中每个远程仓库都只能有一个mirror与它关联,也就是说你不能同时配置多个mirrormirrorOf指向同一个repositoryId

      <mirrors>
        <!-- 给定仓库的下载镜像。 -->
        <mirror>
          <!-- 该镜像的唯一标识符。id用来区分不同的mirror元素。 -->
          <id>mirrorId</id>
          <!-- 镜像名称 -->
          <name>PlanetMirror Australia</name>
          <!-- 该镜像的URL。构建系统会优先考虑使用该URL,而非使用默认的服务器URL。 -->
          <url>http://downloads.planetmirror.com/pub/maven2</url>
          <!-- 被镜像的服务器的id。例如,如果我们要设置了一个Maven中央仓库(http://repo.maven.apache.org/maven2/)的镜像,就需要将该元素设置成central。这必须和中央仓库的id central完全一致。 -->
          <mirrorOf>repositoryId</mirrorOf>
        </mirror>
      </mirrors>
      
  • Proxies:

    • 作用:用来配置不同的代理。

      <proxies>
        <!--代理元素包含配置代理时需要的信息 -->
        <proxy>
          <!--代理的唯一定义符,用来区分不同的代理元素。 -->
          <id>myproxy</id>
          <!--该代理是否是激活的那个。true则激活代理。当我们声明了一组代理,而某个时候只需要激活一个代理的时候,该元素就可以派上用处。 -->
          <active>true</active>
          <!--代理的协议。 协议://主机名:端口,分隔成离散的元素以方便配置。 -->
          <protocol>http</protocol>
          <!--代理的主机名。协议://主机名:端口,分隔成离散的元素以方便配置。 -->
          <host>proxy.somewhere.com</host>
          <!--代理的端口。协议://主机名:端口,分隔成离散的元素以方便配置。 -->
          <port>8080</port>
          <!--代理的用户名,用户名和密码表示代理服务器认证的登录名和密码。 -->
          <username>proxyuser</username>
          <!--代理的密码,用户名和密码表示代理服务器认证的登录名和密码。 -->
          <password>somepassword</password>
          <!--不该被代理的主机名列表。该列表的分隔符由代理服务器指定;例子中使用了竖线分隔符,使用逗号分隔也很常见。 -->
          <nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>
        </proxy>
      </proxies>
      
  • Profiles:

    • 作用:根据环境参数来调整构建配置的列表。
      settings.xml中的profile元素是pom.xmlprofile元素的裁剪版本。它包含了idactivationrepositoriespluginRepositoriesproperties元素。这里的profile元素只包含这五个子元素是因为这里只关心构建系统这个整体(这正是settings.xml文件的角色定位),而非单独的项目对象模型设置。如果一个settings.xml中的profile被激活,它的值会覆盖任何其它定义在pom.xml中带有相同idprofile。当所有的约束条件都满足的时候就会激活这个profile

      <profiles>
          <profile>
        <!-- profile的唯一标识 -->
              <id>test</id>     
              <!-- 自动触发profile的条件逻辑 -->
              <activation>
                  <activeByDefault>false</activeByDefault>
                  <jdk>1.6</jdk>
                  <os>
                      <name>Windows 7</name>
                      <family>Windows</family>
                      <arch>x86</arch>
                      <version>5.1.2600</version>
                  </os>
                  <property>
                      <name>mavenVersion</name>
                      <value>2.0.3</value>
                  </property>
                  <file>
                      <exists>${basedir}/file2.properties</exists>
                      <missing>${basedir}/file1.properties</missing>
                  </file>
              </activation>
              <!-- 扩展属性列表 -->
              <properties />
              <!-- 远程仓库列表 -->
              <repositories />
              <!-- 插件仓库列表 -->
              <pluginRepositories />
            ...
          </profile>
      </profiles>
      
  • ActiveProfiles:

    • 作用:手动激活profiles的列表,按照profile被应用的顺序定义activeProfile。该元素包含了一组activeProfile元素,每个activeProfile都含有一个profile id。任何在activeProfile中定义的profile id,不论环境设置如何,其对应的profile都会被激活。如果没有匹配的profile,则什么都不会发生。
      例如,env-test是一个activeProfile,则在pom.xml(或者profile.xml)中对应idprofile会被激活。如果运行过程中找不到这样一个profile,Maven则会像往常一样运行。

      <activeProfiles>
          <!-- 要激活的profile id -->
          <activeProfile>env-test</activeProfile>
      </activeProfiles>
      

5.2 阿里云镜像

  • 镜像:mirrors

    • 作用:加速我们的jar包下载
  • 国内建议使用阿里云的镜像

    <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>*</mirrorOf>
      <name>阿里云公共仓库</name>
      <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
    <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>*</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror>
    

5.3 本地仓库

  • 本地仓库:LocalRepository
    • 作用:表示构建系统本地仓库的路径。
  • 默认值:~/.m2/repository
<localRepository>D:\DeveloperTools\Java\Maven\localRepository</localRepository>

5.4 在IDEA中使用Maven

5.4.1 创建MavenWeb模板项目

创建MavenWeb项目01

创建MavenWeb项目02

创建MavenWeb项目03

创建MavenWeb项目04

5.4.2 在Settings中配置Maven

Settings配置Maven

注意:经常在IDEA项目自动创建完成后,Maven的配置经常会发生改变。

5.4.3 Project Struture中配置源代码目录与资源目录

Project Struture中配置源代码目录与资源目录

5.4.4 配置Tomcat

配置Tomcat01

配置Tomcat02

配置Tomcat03

注意:Application context配置叫虚拟路径映射

5.4.5 IDEA右侧的Maven工具栏

Maven工具栏说明

5.4.6 使用MavenWeb模板创建的pom.xml说明

<?xml version="1.0" encoding="UTF-8"?>
<!-- Maven版本和头文件 -->
<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>

  <!-- Maven的GAV -->
  <groupId>net.xjbh</groupId>
  <artifactId>MavenWebDemo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!-- 项目打包方式:jar:Java应用;war:JavaWeb应用 -->
  <packaging>war</packaging>

  <!-- 配置 -->
  <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>
    <!-- 具体依赖的jar包配置信息 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <!-- 项目构建配置 -->
  <build>
    <finalName>MavenWebDemo</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>

5.4.7 Maven项目的标准目录结构

  • src
    • main
      • java 源文件
      • resources 资源文件
      • filters 资源过滤文件
      • config 配置文件
      • scripts 脚本文件
      • webapp web应用文件
    • test
      • java 测试源文件
      • resources 测试资源文件
      • filters 测试资源过滤文件
    • it 集成测试
    • assembly assembly descriptors
    • site Site
  • target
    • generated-sources
    • classes
    • generated-test-sources
    • test-classes
    • xxx.jar
  • pom.xml
  • LICENSE.txt
  • NOTICE.txt
  • README.txt

5.4.8 Maven资源导出失败的问题

构建Maven项目的时候,如果没有进行特殊的配置,Maven会按照标准的目录结构查找和处理各种类型文件。

src/main/javasrc/test/java

这两个目录中的所有*.java文件会分别在comile和test-comiple阶段被编译,编译结果分别放到了target/classestarge/test-classes目录中,但是这两个目录中的其他文件都会被忽略掉。

src/main/resouces和src/test/resources

这两个目录中的文件也会分别被复制到target/classestarget/test-classes目录中。

target/classes

打包插件默认会把这个目录中的所有内容打入到jar包或者war包中。

5.4.8.1 资源文件的配置

资源文件是Java代码中要使用的文件。代码在执行的时候会到指定位置去查找这些文件。前面已经说了Maven默认的处理方式,但是有时候我们需要进行自定义的配置。

有时候有些配置文件通常与.java文件一起放在src/main/java目录(如mybatis或hibernate的表映射文件)。有的时候还希望把其他目录中的资源也复制到classes目录中。这些情况下就需要在Pom.xml文件中修改配置了。

可以有两种方法:

  • 一是在元素下添加进行配置。

  • 另一种是在子元素中配置maven-resources-plugin等处理资源文件的插件。

    • 配置resouces节点

      <!--配置build 防止Maven 资源导出失败-->
      <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>
      
    • 配置资源处理插件

      <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>2.5</version>
          <executions>
              <execution>
                  <id>copy-xmls</id>
                  <phase>process-sources</phase>
                  <goals>
                      <goal>copy-resources</goal>
                  </goals>
                  <configuration>
                      <outputDirectory>${basedir}/target/classes</outputDirectory>
                      <resources>
                          <resource>
                              <directory>${basedir}/src/main/java</directory>
                              <includes>
                                  <include>**/*.xml</include>
                              </includes>
                          </resource>
                      </resources>
                  </configuration>
              </execution>
          </executions>
      </plugin>
      

      另一个插件也能完成相同的功能

      <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>build-helper-maven-plugin</artifactId>
          <version>1.8</version>
          <executions>
              <execution>
                  <id>add-resource</id>
                  <phase>generate-resources</phase>
                  <goals>
                      <goal>add-resource</goal>
                  </goals>
                  <configuration>
                      <resources>
                          <resource>
                              <directory>src/main/java</directory>
                              <includes>
                                  <include>**/*.xml</include>
                              </includes>
                          </resource>
                      </resources>
                  </configuration>
              </execution>
          </executions>
      </plugin>
      
5.4.8.2 打包时文件相关的配置

打包时target/classes目录中的资源文件会和class字节码一起被打进jar包或war包中。有时候默认的情况不能完全满足需求,如target/classes目录中的一些文件不希望打入jar包中,就需要额外配置maven-jar-plugin插件。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <excludes>
            <exclude>*.properties</exclude>
        </excludes>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>xxxxxx.ConsoleLauncher</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

6. Servlet

6.1 Servlet简介

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

把实现了Servlet接口的Java程序叫做Servlet

6.2 HelloServlet

6.2.1 配置父子工程

父项目的pom.xml

<modules>
    <module>servlet-01</module>
</modules>

子项目的pom.xml

<parent>
    <artifactId>JavaWebDemo</artifactId>
    <groupId>net.xjbh</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>

6.2.2 引入ServletJSP的依赖

<!-- 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/jsp-api -->
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.2</version>
</dependency>

6.2.3 Maven环境优化

  • 修改web.xml为最新
  • Maven的结构搭建完整
    • java文件夹
    • resources文件夹

6.2.4 编写Servlet实现类

package net.xjbh.servlet;

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

@WebServlet(name = "HelloServlet")
public class HelloServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();
        writer.print("Hello Servlet");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

6.2.5 配置web.xmlServlet映射

<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>net.xjbh.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>

6.3 Servlet原理

Servlet是由web服务器调用,web服务器在收到浏览器请求之后,会

Servlet原理

6.4 Mapping映射问题

  • 一个Servlet可以指定一个映射路径

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet</url-pattern>
    </servlet-mapping>
    
  • 一个Servlet可以指定多个映射路径

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet2</url-pattern>
    </servlet-mapping>
    
  • 一个Servlet可以指定通用映射路径

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet/*</url-pattern>
    </servlet-mapping>
    

    注意:尽量不要如下写法,优先级比较高且会覆盖首页

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
  • 一个Servlet可以指定一些后缀或者前缀

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    

    注意:*号前不能添加项目路径

  • 优先级:固定值 > 通配符

6.5 ServletContext

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;当前web应用的Servlet都是由同一个ServletContext对象管理。

  • 共享数据:在ServletA中保存了数据,可以在ServletB中获取数据

    Servlet01

    package net.xjbh.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 SetContext extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext servletContext = this.getServletContext();
            servletContext.setAttribute("userName", "李向丞");
            servletContext.setAttribute("company", "香江百货");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doGet(req, resp);
        }
    }
    

    servlet02

    package net.xjbh.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 GetContext extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext servletContext = this.getServletContext();
            String userName = (String) servletContext.getAttribute("userName");
            String company = (String) servletContext.getAttribute("company");
    
            resp.setContentType("text/html; charset=utf-8");
            resp.getWriter().println("userName -->" + userName);
            resp.getWriter().println("company -->" + company);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doGet(req, resp);
        }
    }
    

    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">
    
        <servlet>
            <servlet-name>setContext</servlet-name>
            <servlet-class>net.xjbh.servlet.SetContext</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>setContext</servlet-name>
            <url-pattern>/setContext</url-pattern>
        </servlet-mapping>
        <servlet>
            <servlet-name>getContext</servlet-name>
            <servlet-class>net.xjbh.servlet.GetContext</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>getContext</servlet-name>
            <url-pattern>/getContext</url-pattern>
        </servlet-mapping>
    </web-app>
    

    首先请求setContext,然后请求getContext即可获取数据

    userName -->李向丞 company -->香江百货
    
  • 转发(页面路径不会发生改变)

    Servlet

    package net.xjbh.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 ServletDispatcher extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext servletContext = this.getServletContext();
    
            servletContext.getRequestDispatcher("/getContext").forward(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doGet(req, resp);
        }
    }
    

    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">
    
        <servlet>
            <servlet-name>setContext</servlet-name>
            <servlet-class>net.xjbh.servlet.SetContext</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>setContext</servlet-name>
            <url-pattern>/setContext</url-pattern>
        </servlet-mapping>
        <servlet>
            <servlet-name>getContext</servlet-name>
            <servlet-class>net.xjbh.servlet.GetContext</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>getContext</servlet-name>
            <url-pattern>/getContext</url-pattern>
        </servlet-mapping>
        <servlet>
            <servlet-name>dispatcher</servlet-name>
            <servlet-class>net.xjbh.servlet.ServletDispatcher</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcher</servlet-name>
            <url-pattern>/dispatcher</url-pattern>
        </servlet-mapping>
    </web-app>
    

    直接请求dispatcher,页面会转发到getContext路径不会发生改变

  • 获取资源文件配置信息

    • src/main/java文件夹下创建配置文件,例如:xml文件、properties文件,需要在pom.xml文件中配置导出信息,否则该类型的文件无法生成到classes文件夹下;Maven约定大于配置

      pom.xml

      <build>
          <resources>
              <resource>
                  <directory>src/main/resources</directory>
                  <excludes>
                      <exclude>**/*.properties</exclude>
                      <exclude>**/*.xml</exclude>
                  </excludes>
                  <filtering>false</filtering>
              </resource>
              <resource>
                  <directory>src/main/java</directory>
                  <includes>
                      <include>**/*.properties</include>
                      <include>**/*.xml</include>
                  </includes>
                  <filtering>false</filtering>
              </resource>
          </resources>
      </build>
      

      servlet

      package net.xjbh.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.InputStream;
      import java.util.Properties;
      
      public class GetServletProperties extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              ServletContext servletContext = this.getServletContext();
      
              InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/oracle.properties");
              Properties prop = new Properties();
              prop.load(is);
              String strURL = prop.getProperty("url");
              String strDrivers = prop.getProperty("drivers");
              String strUserName = prop.getProperty("userName");
              String strPassWord = prop.getProperty("passWord");
      
              resp.setContentType("text/html; charset=utf-8");
              resp.getWriter().println("URL:" + strURL);
              resp.getWriter().println("Drivers:" + strDrivers);
              resp.getWriter().println("UserName:" + strUserName);
              resp.getWriter().println("PassWord:" + strPassWord);
              
              is.close();
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              this.doGet(req, resp);
          }
      }
      
    • src/main/resources文件下创建配置文件,例如:xml文件、properties文件则不需要做任何配置信息

      servlet

      package net.xjbh.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.InputStream;
      import java.util.Properties;
      
      public class GetServletProperties extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              ServletContext servletContext = this.getServletContext();
      
              InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/oracle.properties");
              Properties prop = new Properties();
              prop.load(is);
              String strURL = prop.getProperty("url");
              String strDrivers = prop.getProperty("drivers");
              String strUserName = prop.getProperty("userName");
              String strPassWord = prop.getProperty("passWord");
      
              resp.setContentType("text/html; charset=utf-8");
              resp.getWriter().println("URL:" + strURL);
              resp.getWriter().println("Drivers:" + strDrivers);
              resp.getWriter().println("UserName:" + strUserName);
              resp.getWriter().println("PassWord:" + strPassWord);
              
              is.close();
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              this.doGet(req, resp);
          }
      }
      

6.6 HttpServletResponse

6.6.1 如何下载文件

package net.xjbh.servlet;

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;

public class ServletFileDown extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1 获取下载文件的路径
        String strPath = req.getServletContext().getRealPath("\\WEB-INF\\classes\\img\\head.jpg");
        // 2 获取下载的文件名
        String strFileName = strPath.substring(strPath.lastIndexOf("\\") + 1);
        // 3 设置浏览器支持下载的文件配置信息,此段不需要记忆,直接面向百度编程
        resp.setContentType("text/html;charset=UTF-8");
        // resp.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(strFileName, "UTF-8"));
        resp.setHeader("Content-Disposition","attachment; filename=" + new String(strFileName.getBytes("UTF-8"), "UTF-8"));
        // 4 获取下载文件的输入流
        FileInputStream fis = new FileInputStream(strPath);
        // 5 创建缓冲区
        int length = 0;
        byte[] buffer = new byte[1024];
        // 6 获取OutputStream对象
        ServletOutputStream sos = resp.getOutputStream();
        // 7 将FileOutputStream流写入到缓冲区,使用OutputStream对象将缓冲区的内容输出到客户端
        while ((length = fis.read(buffer)) > 0 ) {
            sos.write(buffer, 0, length);
        }

        fis.close();
        sos.close();
    }

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

6.6.2 实现重定向

web资源B收到A的请求后,B会通知A去访问web资源C,这个过程就叫做重定向。常见的场景:用户登录

void sendRedirect(String var1) throws IOException;

Servlet

package net.xjbh.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 ServletRedirect extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("https://www.baidu.com");
    }

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

6.7 HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过HTTP协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest

  • 获取参数的方法
// 在接口ServletRequest中获取传递参数的四个方法
String getParameter(String var1); // 重点

String[] getParameterValues(String var1); // 重点

Enumeration<String> getParameterNames();

Map<String, String[]> getParameterMap();
  • 简单登录

    JSP

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登陆</title>
    </head>
    <body>
    <div>
        <form action="${pageContext.request.contextPath}/login" method="post">
            <table>
                <tr>
                    <td>账号:</td>
                    <td><input type="text" name="userName"></td>
                </tr>
                <tr>
                    <td>密码:</td>
                    <td><input type="password" name="passWord"></td>
                </tr>
                <tr>
                    <td colspan="2"><input type="submit" name="login" value="登陆"></td>
                </tr>
            </table>
        </form>
    </div>
    </body>
    </html>
    

    Servlet

    package com.xjbh.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 LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 解决参数中文乱码
            req.setCharacterEncoding("UTF-8");
            String strUserName = req.getParameter("userName");
            String strPassWord = req.getParameter("passWord");
            System.out.println("============华丽的分割线==========");
            System.out.println("UserName:" + strUserName);
            System.out.println("PassWord:" + strPassWord);
            System.out.println("============华丽的分割线==========");
            resp.setContentType("text/html;charset=UTF-8");
            // 请求转发(URL不发生改变,请求转发用相对路径)
            // req.getRequestDispatcher("/success.jsp").forward(req, resp);
            // 页面重定向(URL发生改变,页面重定向用绝对路径)
            resp.sendRedirect(req.getContextPath() + "/success.jsp");
        }
    }
    

    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">
    
        <servlet>
            <servlet-name>loginServlet</servlet-name>
            <servlet-class>com.xjbh.servlet.LoginServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>loginServlet</servlet-name>
            <url-pattern>/login</url-pattern>
        </servlet-mapping>
    </web-app>
    

7. CookieSession

7.1 HTTP会话

在计算机术语中,会话是指一个终端用户与交互系统进行通讯的过程,比如从输入账户密码进入操作系统到退出操作系统就是一个会话过程。会话较多用于网络上,TCP的三次握手就创建了一个会话,TCP关闭连接就是关闭会话。

7.2 保存会话的两种技术

客户端技术(请求与相应)

  • 常用方法

    // 获取Cookie数组
    Cookie[] cookies = request.getCookies();
    
    // 创建一个Cookie
    Cookie cookieLastTime = new Cookie("lastTime", Long.toString(System.currentTimeMillis()));
    
    // 获取Cookie中的Key
    String key = cookie.getName();
    
    // 获取Cookie中的Value
    String key = cookie.getValue();
    
    // 设置Cookie的有效期
    cookie.setMaxAge(24*60*60);
    
    // 相应给客户端Cookie
    response.addCookie(cookieLastTime);
    
  • 细节问题

    • 一个Cookie只能保存一个信息
    • 一个web站点可以给浏览器发送多个Cookie,最多存放20个Cookie
    • 浏览器的Cookie上限为300个
    • Cookie的大小上限为4KB
  • 删除Cookie

    • 不设置有效期,则关闭浏览器自动失效
    • 设置有效期为0
  • 例子

    package net.xjbh.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 CookieServlet01 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 解决中文乱码
            resp.setContentType("text/html;charset=UTF-8");
            req.setCharacterEncoding("UTF-8");
    
            // 获取一个打印输出流
            PrintWriter pw = resp.getWriter();
    
            // 从Request中获取Cookie的数组
            Cookie[] cookies = req.getCookies();
    
            // 便利Cookie数组中是否存在lastTime的Cookie,如果有则获得并打印它的值
            if (cookies.length > 0) {
                for (int i = 0; i < cookies.length; i++) {
                    Cookie cookie = cookies[i];
                    if (cookie.getName().equals("lastTime")) {
                        pw.write("您上一次访问本站的时间:" + new Date(Long.parseLong(cookie.getValue())).toLocaleString());
                    }
                }
            } else {
                pw.write("这是您第一次访问本站");
            }
    
            // 创建一个Key Value的Cookie
            Cookie cookieLastTime = new Cookie("lastTime", Long.toString(System.currentTimeMillis()));
    
            // 把创建好的Cookie添加到Response中
            resp.addCookie(cookieLastTime);
    
            pw.close();
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doGet(req, resp);
        }
    }
    
  • 编码与解码

    • 编码

      URLEncoder.encode("你好,世界!", "UTF-8");
      
    • 解码

      URLDecoder.decode("你好,世界!", "UTF-8");
      

7.2.2 *Session

服务端技术,利用这个技术可以保存用户的会话信息

什么是Session

  • 服务器会给每一个用户(浏览器)创建一个Session对象
  • 一个Session独占一个浏览器,只要浏览器没有关闭,则Session就一直存在
  • 用户登录之后,整个网站都可以访问

Session常用方法

// 获得一个Session
HttpSession session = request.getSession();

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

// Session中存入对象
Person setPerson = new Person("迪丽热巴", 18);
session.setAttribute("Person", setPerson);

// 获取Session中的对象
Person getPerson = (Person) session.getAttribute("Person");

// 判断Session是否为新创建
boolean isNew = session.isNew();

// 注销Session
session.invalidate();

Session自动失效在web.xml文件中配置

<session-config>
    <!-- 以分钟为单位自动失效 -->
    <session-timeout>15</session-timeout>
</session-config>

8. JSP

8.1 什么是JSP

JSP(全称JavaServer Pages)是由Sun Microsystems公司主导创建的一种动态网页技术标准。JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTMLXML或其他格式文档的Web网页,然后返回给请求者。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。

8.2 JSP工作原理

  • 代码层面没有任何问题

  • 服务器内部工作

    Tomcat中有一个work目录

    IDEA中使用Tomcat的会在IDEATomcat中生产一个work目录

  • 浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet

  • JSP在运行时会转换为Java类继承了HttpServlet,所以JSP本质就是Servlet

  • JSP的几个内置对象

    final javax.servlet.jsp.PageContext pageContext;
    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;
    

8.3 JSP基础语法

8.3.1 JSP表达式

语法

<%= 变量或者表达式 %>

举例

<%= new java.util.Date() %>

8.3.2 JSP脚本片段

语法

<% 脚本片段 %>

举例

<%
	int sum = 0;
	for (int i = 0; i <= 10; i++) {
        sum += i;
    }
	out.println(sum);
%>

8.3.3 JSP申明

语法

<%! 申明片段 %>

举例

<%!
    static {
    	System.out.println("Hello, World!");
	}
	
	public void methodInit() {
        System.out.println("method Init!");
    }
%>

注意:JSP申明片段生成在Java类中,而其它则生成在_JspServices方法中!

8.3.4 JSP注释

语法

<%-- 注释 --%>

注意:JSP的注释不会在客户端显示,而HTML的注释则会在客户端显示!

8.4 九大内置对象及作用域

  • [PageContext] pageContext:存储数据
  • [HttpServletRequest] Request:存储数据
  • [HttpServletResponse] Response
  • [HttpSession] Session:存储数据
  • [ServletContext] Application:存储数据
  • [ServletConfig] config
  • [JspWriter] out
  • [Object] page:几乎不使用,可以不了解
  • [ServletException] exception
/* 
 * 储存的数据只在一个页面中有效
**/
pageContext.setAttribute("Name1", "ArtherLee1");

/* 
 * 储存的数据只在一个请求中有效,请求转发会携带此数据
 * 产生的数据,用户使用完后就没有作用,例如:新闻
**/
Request.setAttribute("Name2", "ArtherLee2");

/* 
 * 储存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
 * 产生的数据,用户使用完后还需要继续使用,例如:购物车
**/
Session.setAttribute("Name3", "ArtherLee3");

/* 
 * 储存的数据只在服务器中有效,从打开服务器到关闭服务器
 * 产生的数据,一个用户使用完后,其它用户还能继续使用,例如:聊天数据
**/
Application.setAttribute("Name4", "ArtherLee4");

8.5 JSP标签、JSTL标签、EL表达式

8.5.1 Maven项目依赖:

<!-- 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>

8.5.2 EL表达式:

语法如下:

${  }
  • 获取数据
  • 执行运算
  • 获取web开发的常用对象
  • 调用Java方法

8.5.3 JSP标签

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="ArtherLee"/>
    <jsp:param name="age" value="18"/>
</jsp:forward>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
name:<%=request.getParameter("name")%>
<br/>
age:<%=request.getParameter("age")%>
</body>
</html>

8.5.4 JSTL标签

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

JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。

根据JSTL标签所提供的功能,可以将其分为5个类别

  • JSTL库安装

    Apache Tomcat安装JSTL 库步骤如下:

    Apache的标准标签库中下载的二进包(jakarta-taglibs-standard-current.zip)。

    下载 jakarta-taglibs-standard-1.1.2.zip 包并解压,将 jakarta-taglibs-standard-1.1.2/lib/ 下的两个 jar 文件:standard.jarjstl.jar 文件拷贝到 /WEB-INF/lib/ 下。

    将 tld 下的需要引入的 tld 文件复制到 WEB-INF 目录下。

    接下来我们在 web.xml 文件中添加以下配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4" 
        xmlns="http://java.sun.com/xml/ns/j2ee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
            http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <jsp-config>
        <taglib>
        <taglib-uri>http://java.sun.com/jsp/jstl/fmt</taglib-uri>
        <taglib-location>/WEB-INF/fmt.tld</taglib-location>
        </taglib>
        <taglib>
        <taglib-uri>http://java.sun.com/jsp/jstl/fmt-rt</taglib-uri>
        <taglib-location>/WEB-INF/fmt-rt.tld</taglib-location>
        </taglib>
        <taglib>
        <taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
        <taglib-location>/WEB-INF/c.tld</taglib-location>
        </taglib>
        <taglib>
        <taglib-uri>http://java.sun.com/jsp/jstl/core-rt</taglib-uri>
        <taglib-location>/WEB-INF/c-rt.tld</taglib-location>
        </taglib>
        <taglib>
        <taglib-uri>http://java.sun.com/jsp/jstl/sql</taglib-uri>
        <taglib-location>/WEB-INF/sql.tld</taglib-location>
        </taglib>
        <taglib>
        <taglib-uri>http://java.sun.com/jsp/jstl/sql-rt</taglib-uri>
        <taglib-location>/WEB-INF/sql-rt.tld</taglib-location>
        </taglib>
        <taglib>
        <taglib-uri>http://java.sun.com/jsp/jstl/x</taglib-uri>
        <taglib-location>/WEB-INF/x.tld</taglib-location>
        </taglib>
        <taglib>
        <taglib-uri>http://java.sun.com/jsp/jstl/x-rt</taglib-uri>
        <taglib-location>/WEB-INF/x-rt.tld</taglib-location>
        </taglib>
        </jsp-config>
    </web-app>
    
  • 核心标签

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
  • 格式化标签

    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    
  • SQL 标签

    <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
    
  • XML 标签

    <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
    
  • JSTL 函数

    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
    

9. JavaBean

9.1 JavaBean有特定的写法:一般用来和数据库的字段做映射

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

9.2 ORM(Object Relational Mapping)对象关系映射

  • 数据库表名 --> 类名
  • 表字段 --> 类属性
  • 表行记录 --> 对象

假设在数据库中有一张Person表,表结构如下:

id name age
1 迪丽热巴 18
2 古力娜扎 20
3 马尔扎哈 1000

生成的对应JavaBean

public class Person {
    private int id;
    private String name;
    private int age;

    public Person() {
    }

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

    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;
    }

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

10. MVC三层架构

10.1 MVC三层架构介绍:

  • Model模型:为用户提供使用界面,与用户直接进行交互

    • 数据承载Bean:实体类,专门用户承载业务数据的,如StudentUser
    • 业务处理Bean:指ServiceDao对象,专门用于处理用户提交请求
  • View视图:承载数据,并对用户提交请求进行计算的模块

  • Controller控制器:用于将用户请求转发给相应的Model进行处理,并根据Model的计算结果向用户提供相应响应

10.2 MVC 架构程序的工作流程

10.2.1 用户通过View页面向服务端提出请求,可以是表单请求、超链接请求、AJAX请求等

10.2.2 服务端Controller控制器接收到请求后对请求进行解析,找到相应的Model对用户请求进行处理

10.2.3 Model处理后,将处理结果再交给Controller

10.2.4 Controller在接到处理结果后,根据处理结果找到要作为向客户端发回的响应View页面。页面经渲染(数据填充)后,再发送给客户端

10.3 MVC与三层架构的关系

MVC与三层架构的关系

11. Filter过滤器

Filter:过滤器能够对目标资源的请求和响应进行截取。

11.1 Filter过滤器开发步骤

11.1.1 导包

<dependencies>
    <!-- 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>
    <!-- JSP 依赖 -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
    </dependency>
    <!-- Servlet 依赖 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
</dependencies>

11.1.2 编写过滤器

编写一个Java类实现javax.servlet.Filter接口

package com.artherlee.filter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class CharcterEncodingFilter implements Filter {

    /**
     * 销毁,web服务器在停止的时候会做销毁处理
     */
    public void destroy() {
        System.out.println("CharcterEncodingFilter销毁...");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        // 让我们的请求继续往下执行,如果不写,程序到这里就将被拦截停止
        chain.doFilter(req, resp);
    }

    /**
     * 初始化,web服务器在启动的时候会做初始化
     * @param config
     * @throws ServletException
     */
    public void init(FilterConfig config) throws ServletException {
        System.out.println("CharcterEncodingFilter初始化...");
    }

}

11.1.3 配置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">

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

    <filter>
        <filter-name>CharcterEncodingFilter</filter-name>
        <filter-class>com.artherlee.filter.CharcterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharcterEncodingFilter</filter-name>
        <url-pattern>/servlets/*</url-pattern>
    </filter-mapping>
</web-app>

11.1.4 编写servlet

package com.artherlee.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 HelloServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("你好,世界!");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

11.2 Filter权限拦截实例

要求:用户登录之后才能访问主页,用户注销后则不能访问;

JSP+Servlet+Filter实现;

  • JSP页面

    Login.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登陆</title>
    </head>
    <body>
        <form action="/servlet/LoginServlet" method="POST">
            用户名:<input type="text" name="userName">
            <br/>
            <input type="radio" name="vip" value="VIP1" checked="checked">VIP1
            <input type="radio" name="vip" value="VIP2">VIP2
            <input type="radio" name="vip" VALUE="VIP3">VIP3
            <br/>
            <input type="submit" value="登陆">
        </form>
    </body>
    </html>
    

    /system/Index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>主页</title>
      </head>
      <body>
      <h1>${sessionScope.SESSION_USER.userName},欢迎来到主页,您当前的VIP级别为:${sessionScope.SESSION_USER.vipLevel}</h1>
      <h3><a href="/servlet/LogoutServlet">注销用户</a></h3>
      </body>
    </html>
    

    /error/ErrorPage500.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>错误500</title>
    </head>
    <body>
    <h1>当前用户不存在或者没有权限访问</h1>
    <h3><a href="/servlet/LogoutServlet">返回登陆页面</a></h3>
    </body>
    </html>
    
  • 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">
    
        <!-- 配置Servlet以及映射 -->
        <servlet>
            <servlet-name>LoginServlet</servlet-name>
            <servlet-class>com.artherlee.servlet.login.LoginServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>LoginServlet</servlet-name>
            <url-pattern>/servlet/LoginServlet</url-pattern>
        </servlet-mapping>
        <servlet>
            <servlet-name>LogoutServlet</servlet-name>
            <servlet-class>com.artherlee.servlet.login.LogoutServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>LogoutServlet</servlet-name>
            <url-pattern>/servlet/LogoutServlet</url-pattern>
        </servlet-mapping>
    
        <!-- 配置Filter以及映射 -->
        <filter>
            <filter-name>CharcterEncodingFilter</filter-name>
            <filter-class>com.artherlee.filter.CharcterEncodingFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>CharcterEncodingFilter</filter-name>
            <url-pattern>/</url-pattern>
        </filter-mapping>
        <filter>
            <filter-name>LoginFilter</filter-name>
            <filter-class>com.artherlee.filter.LoginFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>LoginFilter</filter-name>
            <url-pattern>/system/*</url-pattern>
        </filter-mapping>
    </web-app>
    
  • pom.xml页面

    <?xml version="1.0" encoding="UTF-8"?>
    <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>org.example</groupId>
        <artifactId>RuleFilterTest</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <!-- 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>
            <!-- JSP 依赖 -->
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.1</version>
            </dependency>
            <!-- Servlet 依赖 -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
            </dependency>
        </dependencies>
    </project>
    
  • Java

    User实体类

    package com.artherlee.entity;
    
    public class User {
        private String userName;
        private VipLevel vipLevel;
    
        public User() {
        }
    
        public User(String userName, VipLevel vipLevel) {
            this.userName = userName;
            this.vipLevel = vipLevel;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public VipLevel getVipLevel() {
            return vipLevel;
        }
    
        public void setVipLevel(VipLevel vipLevel) {
            this.vipLevel = vipLevel;
        }
    
        @Override
        public String toString() {
            return "Users{" +
                    "userName='" + userName + '\'' +
                    ", vipLevel=" + vipLevel +
                    '}';
        }
    }
    

    VipLevel枚举类

    package com.artherlee.entity;
    
    public enum VipLevel {
        VIP1,
        VIP2,
        VIP3
    }
    

    util工具类

    package com.artherlee.util;
    
    public class Constant {
        public static final String SESSION_USER = "SESSION_USER";
    }
    
  • Servlet

    LoginServlet登陆

    package com.artherlee.servlet.login;
    
    import com.artherlee.entity.User;
    import com.artherlee.entity.VipLevel;
    import com.artherlee.util.Constant;
    
    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 LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String userName = req.getParameter("userName");
            String vip = req.getParameter("vip");
    
            if (userName.equals("admin")) {
                User user = new User();
                user.setUserName(userName);
                if (vip.equals("VIP1")) {
                    user.setVipLevel(VipLevel.VIP1);
                } else if (vip.equals("VIP2")) {
                    user.setVipLevel(VipLevel.VIP2);
                } else if (vip.equals("VIP3")) {
                    user.setVipLevel(VipLevel.VIP3);
                }
    
                req.getSession().setAttribute(Constant.SESSION_USER, user);
                resp.sendRedirect("/system/Index.jsp");
            } else {
                resp.sendRedirect("/error/ErrorPage500.jsp");
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doGet(req, resp);
        }
    }
    

    LogoutServlet登出

    package com.artherlee.servlet.login;
    
    import com.artherlee.entity.User;
    import com.artherlee.util.Constant;
    
    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 LogoutServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            User user = (User) req.getSession().getAttribute(Constant.SESSION_USER);
            if (user == null) {
                resp.sendRedirect("/error/ErrorPage500.jsp");
            } else {
                req.getSession().removeAttribute(Constant.SESSION_USER);
                resp.sendRedirect("/Login.jsp");
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doGet(req, resp);
        }
    }
    
  • Filter过滤器类

    CharcterEncodingFilter字符编码过滤器

    package com.artherlee.filter;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import java.io.IOException;
    
    public class CharcterEncodingFilter implements Filter {
    
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            servletRequest.setCharacterEncoding("UTF-8");
            servletResponse.setContentType("text/html;charset=UTF-8");
    
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        public void destroy() {
    
        }
    }
    

    LoginFilter登陆过滤器

    package com.artherlee.filter;
    
    import com.artherlee.util.Constant;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class LoginFilter implements Filter {
    
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) servletRequest;
            HttpServletResponse resp = (HttpServletResponse) servletResponse;
    
            if (req.getSession().getAttribute(Constant.SESSION_USER) == null) {
                resp.sendRedirect("/error/ErrorPage500.jsp");
            }
            filterChain.doFilter(req, resp);
        }
    
        public void destroy() {
    
        }
    }
    
posted @ 2021-11-11 10:10  爱Ni说不出口  阅读(10)  评论(0编辑  收藏  举报