JavaWeb

JavaWeb

1、基本概念

1.1、前言

web开发:

  • web,网页的意思
  • 静态web
    • html,css
    • 提供给所有人看的数据始终不会发生改变!
  • 动态web
    • 几乎是所有的网站
    • 提供给所有人看的数据始终会发生变化,每个人在不同的事件,不同的地点看到的信息各不相同!
    • 技术栈:Servlet/JSP,ASP,PHP

在java中,动态web资源开发的技术统称为javaweb;

1.2、web应用程序

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

  • a.htnl、b.html…多个web资源,这些web资源可以被外界访问,对外界提供服务;
  • 能访问到的任何一个页面或者资源,都存在于这和世界的某一角落的计算机上。
  • URL(统一资源定位系统)
  • 这个统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat:服务器
  • 一个web应用由多部分组成(静态web,动态web)
    • html、css、js
    • jsp、servlet
    • java程序
    • jar包
    • 配置文件(Properties)

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

1.3、静态web

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

客户端→Network(网络)Request(请求)→webService(服务器)→index.html

index.html→webService(服务器)→Network(网络)Response(响应)→客户端

  • 静态web存在的缺点
    • web页面无法动态更新,所有用户看到都是同一个页面
      • 轮播图,点击特效,伪动态
      • javaScript【实际开发中,用的最多】
      • VBScript
    • 它无法和数据库交互(数据无法持久化,用户无法交互)

1.4、动态web

页面会动态展示:web的页面展示的效果因人而异(就是每个人看到的不一样);

客户端→Network(网络)Request(请求)→WebServerPlugin(服务器过滤)→JSP/Servlet(动态web资源)→数据库

数据库→JSP/Servlet(动态web资源)→WebServer(服务器)→Network(网络)Response(相应)→客户端

缺点:假如服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布

优点:

  • web页面可以动态更新,所有用户看到都不是同一个页面
  • 它可以和数据库交互(数据持久化:注册,商品信息,用户信息…)

2、web服务器

2.1、技术讲解

ASP:

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

PHP:

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

JSP/Servlet:

B/S:浏览和服务器

C/S:客户端和服务器

  • sun公司主推的B/S框架
  • 基于java语言的(所有的大公司,或者一些开源的组件,都使用java写的)
  • 可以承载三高问题带来的影响;(高并发、高可用、高性能)
  • 语法像ASP,ASP–>JSP,加强市场强度;

2.2、web服务器

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

IIS

微软的;ASP…,Windows中自带的

Tomcat

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

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。

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

3、Tomcat

3.1、Tomcat启动和配置

文件夹作用:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w6Gq9ZUO-1609049829982)(javaWeb.assets/image-20200902185549868.png)]

启动、关闭 Tomcat

启动:双击bin文件夹里的startup.bat文件

关闭:直接关闭窗口,或者双击bin文件夹里的shutdown.bat

访问测试:

http://localhost:8080/

3.2、配置

用记事本或者notepad++打开conf文件夹里面的server.xml文件 (服务器核心文件)

可以配置启动的端口号

  • tomcat的默认端口号为:8080
  • mysql:3306
  • http:80
  • https:443
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

可以配置主机的名称

  • 默认的主机名为:localhost–>127.0.0.1
  • 默认网站应用存放的位置为:webapps
  <Host name="www.hcx.com"  appBase="webapps"
        unpackWARs="true" autoDeploy="true">

面试题:

请你谈谈网站是如何进行访问的!

  1. 输入一个域名,然后回车

  2. 检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;

    1. 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问

      127.0.0.1       www.hcx.com
      
    2. 没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;

3.3、发布一个web网站

  • 将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了

网站应该有的结构

--webapps:Tomcat服务器的web目录
    -ROOT:网站的目录名
    	-WEB-INF:放网站程序的
    		-classes:java程序
    		-lib:web应用所依赖的jar包
    		-web.xml:网站配置文件
    	-index.html:默认的首页
    	-static:静态资源文件
    		-css
    			-style.css
    		-js

4、HTTP

4.1、什么是HPPT

http(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII码形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使得开发和部署是那么的直截了当

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

https:安全的

  • 443端口

4.2、两个时代

  • http1.0

    • HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
  • http2.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	//远程
Referrer Policy: no-referrer-when-downgrade //(不需要理) 协议 能访问到什么东西
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9    //语言
Cache-Control: max-age=0
Connection: keep-alive
Cookie: BAIDUID=B257AB32FA5096DED39AB27BB1842941:FG=1; BIDUPSID=B257AB32FA5096DED39AB27BB1842941; PSTM=1557061881; BD_UPN=12314753; BDUSS=EwcHhjZ1BOcmwzd3pjM1dVRXBzb2tiQ3ZoNWlRa1h-OVdGN2VMc2tKeWhJVDFmSVFBQUFBJCQAAAAAAAAAAAEAAACRFiB9ufZrYWlfMTIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKGUFV-hlBVfdW; BDUSS_BFESS=EwcHhjZ1BOcmwzd3pjM1dVRXBzb2tiQ3ZoNWlRa1h-OVdGN2VMc2tKeWhJVDFmSVFBQUFBJCQAAAAAAAAAAAEAAACRFiB9ufZrYWlfMTIzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKGUFV-hlBVfdW; BDSFRCVID=goPOJexroG3op3ors_THUEzA2eKKvV3TDYLE3ONZ67Yl5X-VN4vIEG0Pt8lgCZu-2ZlgogKK0gOTH6KF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tb4OVC0aJII3JJ7GMboHq4D_MfOteR3yb6n03RA8Kb7VbIbHyUnkbfJBDGrh2f6L-juO-IboQl50fP04yP5xjJK7yajK2b_eLb6t-nRMtDQMJRc5hUrpQT8r0PFOK5OibCu8_Iojab3vOpoTXpO1hMAzBN5thURB2DkO-4bCWJ5TMl5jDh3Mb6ksDMDtqjtDtRFqVCKKf-TWKRnP5PQ_2-F_hxtfJK62aJ0f5-5vWJ5TMC_wBpoWLnDXXnQmKqQ4MjvfoDotKMTxShPC-tnt5PDXKH0OJMrnXaRRBIop3l02VMO9e-t2ynLVKxr7BPRMW23G0h7mWnRdsxA45J7cM4IseboJLfT-0bc4KKJxbnLWeIJIjjC-jTvBDG_eq-JQ2C7WsJjs24ThD6rnhPF3bP4rXP6-hnjy3b7yQIOO-tOrShnaQJ6ND4LUypjpJh3RymJ4oh7kyDLboJ4GWKc4X60BytoxJpOJfIJM5McaHCoADb3vbURvD--g3-AqBM5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIE3-oJqC-MMD3P; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BD_HOME=1; delPer=0; BD_CK_SAM=1; PSINO=6; __yjsv5_shitong=1.0_7_15d8bf5e19c2a45a2a0b6aa1c47c499e541e_300_1599014527339_180.139.215.126_ecafdfe8; H_PS_PSSID=7541_32606_1447_32572_7543_31660_32045_26350; BDRCVFR[feWj1Vr5u3D]=mk3SLVN4HKm; B64_BOT=1; COOKIE_SESSION=889_0_9_7_2_1_0_0_8_1_0_1_67962_0_0_0_1599018101_0_1599094305%7C9%23342469_4_1598688469%7C3
Host: www.baidu.com
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36
1、请求行
  • 请求行中的请求方式:GET
  • 请求方式:Get,Post,HEAD,DELETE,PUT,TRACT…
    • get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
    • post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效
2、消息头
Accept:  //告诉浏览器,它所支持的数据类型
Accept-Encoding:	//支持哪种编码格式  GBK  UTF-8  GB2312  ISO8859-1
Accept-Language:	//告诉浏览器,它的语言环境
Cache-Control:		//缓存控制
Connection:			//告诉浏览器,请求完成是断开还是保持连接
Host:		//主机..../.

4.4、Http响应

  • 服务器—响应—客户端

百度:

Request Headers

Bdpagetype: 2
Bdqid: 0x8d2ef67f000020bc
Cache-Control: private   //缓存控制
Connection: keep-alive	//连接
Content-Encoding: gzip	//编码
Content-Type: text/html;charset=utf-8 //类型
Date: Thu, 03 Sep 2020 03:09:13 GMT
Expires: Thu, 03 Sep 2020 03:09:12 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=447; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=7541_32606_1447_32572_7543_31660_32045_26350; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1599102553038957517810173339633597817020
Transfer-Encoding: chunked
X-Ua-Compatible: IE=Edge,chrome=1
1、响应体
Accept:  //告诉浏览器,它所支持的数据类型
Accept-Encoding:	//支持哪种编码格式  GBK  UTF-8  GB2312  ISO8859-1
Accept-Language:	//告诉浏览器,它的语言环境
Cache-Control:		//缓存控制
Connection:			//告诉浏览器,请求完成是断开还是保持连接
Host:		//主机..../.
Refresh:	//告诉客户端,多久刷新一次
Location:	//让网页重新定位
2、响应状态码

在访问网站的时候,不管是正常访问页面还是不能正常访问页面,服务器都会给访问的客户端返回一个状态码。平常工作中更是会经常遇到一些常见的状态码。

状态分为五大类:

  1. 1XX 指定客户端应相应的某些动作,代表请求已被接受,需要继续处理。由于 HTTP/1.0 协议中没有定义任何 1xx 状态码,所以除非在某些试验条件下,服务器禁止向此类客户端发送 1xx 响应。

  2. 2XX 代表请求已成功被服务器接收、理解、并接受。这系列中最常见的有200、201状态码。

  3. 3XX 代表需要客户端采取进一步的操作才能完成请求,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的 Location 域中指明。这系列中最常见的有301、302状态码。

  4. 4XX 表示请求错误。代表了客户端看起来可能发生了错误,妨碍了服务器的处理。常见有:401、404状态码。

  5. 5XX 代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。常见有500、503状态码。

面试题:

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

域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户

5、Maven

我为什么要学习这个技术?

  1. javaweb开发中,需要使用大量的jar包,我们要手动去导入(麻烦);

  2. 如何能够让一个东西自动帮我导入和配置这个jar包。

    由此,Maven诞生了

5.1、Maven项目架构管理工具

我们目前用来就是方便导入jar包的!

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

  • 有约束,不要去违反。

Maven会规定好你该如何去编写我们的java代码,必须要按照这个规范来;

5.2、下载安装Maven

去Maven官网下载 点击Download 然后下载 .zip后缀的

下载完成后,解压即可

建议:电脑上的所有环境都放在一个文件夹下,方便管理

5.3、配置环境变量

在我们的系统环境变量中

配置如下:

  • M2_HOME maven目录下的bin目录
  • MAVEN_HOME maven的目录
  • 在系统的path中配置 %MAVEN_HOME%\bin

测试Maven是否安装成功,保证必须配置完毕!

​ mvn -version

5.4、阿里云镜像

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

在maven conf文件夹里面打开settings.xml文件,然后在 里面加入下面的阿里云镜像文件

	<mirror>
  	<id>alimaven</id>
  	<mirrorOf>central</mirrorOf>
  	<name>aliyun maven</name>
  	<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
	</mirror>

5.5、本地仓库

在本地的仓库,远程仓库;

建立一个本地仓库:localRepository

<localRepository>D:/idea2020/IntelliJ IDEA 2020.1/plugins/MavenRepository</localRepository>

5.6、在IDEA中使用Maven

  1. 启动IDEA
  2. 创建一个Maven项目。勾选Create from archetype 就可以使用Maven的模板 在选择下面的maven-archetype-webapp

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tcp5hMfq-1609049829989)(javaWeb.assets/maven2-1599118081935.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HU1UXyvP-1609049829991)(javaWeb.assets/maven-1599118075629.png)]

  1. IDEA中的Maven设置

    要注意的是,idea创建成功后要去看看maven的配置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6yCUnLU-1609049829995)(javaWeb.assets/image-20200903155255891.png)]

    1. 到这里。Maven在IDEA的配置和使用就OK了

5.7、创建一个普通的Maven项目

跟上面差不多一样,只是不需要勾Create from archetype模板

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4lErncbB-1609049829997)(javaWeb.assets/image-20200903172736455.png)]

这个只有在web应用下才有

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9WXg53qv-1609049829999)(javaWeb.assets/image-20200903172955785.png)]

5.8、标记文件夹功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dRyeU8dw-1609049830001)(javaWeb.assets/image-20200903173752839.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pV4ONEim-1609049830002)(javaWeb.assets/image-20200903173843230.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SsFHPe6B-1609049830004)(javaWeb.assets/image-20200903174605883.png)]

5.9、在IDEA中配置Tomcat

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wGyuJ3kG-1609049830005)(javaWeb.assets/image-20200903175134258.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JbbiTvD2-1609049830007)(javaWeb.assets/image-20200903175558751.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XztrT3g3-1609049830007)(javaWeb.assets/image-20200904085155672.png)]

解决警告问题

必须要的配置:为什么会出现这个问题:我们访问一个网站,需要指定一个文件夹名字;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jHZ1Kt34-1609049830008)(javaWeb.assets/image-20200904085713391.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k8guCE9c-1609049830011)(javaWeb.assets/image-20200904090911172.png)]

5.10、pom文件

pom.xml是Maven的核心配置文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L0pPKIfh-1609049830013)(javaWeb.assets/image-20200904092218689.png)]

<?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,组id、项目名称、版本-->
  <groupId>com.kuang</groupId>
  <artifactId>javaweb-01-maven03</artifactId>
  <version>1.0-SNAPSHOT</version>
<!--项目的打包方式 jar:java应用  mar:javaweb应用  -->
  <packaging>war</packaging>

  <name>javaweb-01-maven03 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.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

<!--项目依赖-->
  <dependencies>
<!--    具体依赖的jar包配置文件-->
              <!--Maven的高级之处在于,他会帮你导入这个jar包所依赖的其他jar-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
<!--项目构建用的东西-->
  <build>
    <finalName>javaweb-01-maven03</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由于他的约定大于配置,

我们之后可能会遇到我们写的配置文件,无法被导出或者生效问题,解决方案:

<!--在build中配置resources,来防止我们资源导出失败的问题-->
    <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>

6、Servlet

6.1、Servlet简介

  • Servlet就是sun公司开发动态web的一门技术

  • Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:

    • 编写一个类,实现Servlet接口
    • 把开发好的Java类部署到web服务器中。

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

6.2、HelloServlet

Servlet接口Sun公司有两个默认的实现类:HttpServlet、GenericServlet

  1. 创建一个Maven项目,删除掉里面的src目录,然后就成了一个干净的父工程。尽量都把依赖导入父工程,这样 “子工程” 就不需要在重复的导入了

  2. 关于Maven父子工程的理解:

    父项目中会有

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

    子项目中会有

      <groupId>com.kuang</groupId>
      <artifactId>servlet-01</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    

    父项目中的java子项目可以直接使用

  3. Maven环境优化

    1. 修改web.xml为最新的(参考Tomcat里面的web文件)
    2. 将maven的结构搭建完整(java包、resource包)
  4. 编写一个Servlet程序

    1. 编写一个普通类

    2. 实现Servlet接口,这里我们直接继承HttpServlet

      package com.kuang.servlet;
      
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      import java.io.PrintWriter;
      
      public class HelloServlet extends HttpServlet {
      //    由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑都一样
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              PrintWriter writer = resp.getWriter();//响应流
              writer.print("Hello,Servlet");
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req,resp);
          }
      }
      
      
  5. 编写Servlet的映射

    为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径;

        <!--    web.xml中是配置我们web的核心应用-->
        <!--注册servlet-->
        <servlet>
            <servlet-name>helloServlet</servlet-name>
            <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
        </servlet>
        <!--    一个Servlet对应一个Mapping:映射-->
        <servlet-mapping>
            <servlet-name>helloServlet</servlet-name>
    <!--        请求路径-->
            <url-pattern>/xun</url-pattern>
        </servlet-mapping>
    
  6. 配置Tomcat

    在上面5.9那里有详细 注意:配置发布的路径就可以了

6.3、Mapping问题

  1. 一个Servlet可以指定一个映射路径

    <!--  Servlet的请求路径-->
      <servlet-mapping>
    <!--    要跟上面的对应-->
        <servlet-name>hello</servlet-name>
    <!--    请求路径-->
        <url-pattern>/hello</url-pattern>
      </servlet-mapping>
    
  2. 一个Servlet可以指定多个映射路径

    <!--  Servlet的请求路径-->
      <servlet-mapping>
    <!--    要跟上面的对应-->
        <servlet-name>hello</servlet-name>
    <!--    请求路径-->
        <url-pattern>/hello</url-pattern>
      </servlet-mapping>
       <servlet-mapping>
           <servlet-name>hello</servlet-name>
           <url-pattern>/hello/hello</url-pattern>
       </servlet-mapping>
        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/hello/hello2</url-pattern>
        </servlet-mapping>
        
    
  3. 一个Servlet可以指定通用映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
    
  4. 默认请求路径

    <!--默认请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
  5. 制定一些后缀或者前缀等等…

    <!--    可以自定义后缀实现请求映射-->
    <!--    注意点:*前面不能加项目的映射路径-->
        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>*.hcx</url-pattern>
        </servlet-mapping>
    
  6. 优先级问题
    指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;

    <!--    404-->
        <servlet>
            <servlet-name>error</servlet-name>
            <servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
        </servlet> 
        <servlet-mapping>
            <servlet-name>error</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    

6.4、ServletContext

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

1、共享数据

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

package com.kuang.servlet;

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

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = "大锤";
        context.setAttribute("username",username);
        System.out.println("hello");
    }
}

package com.kuang.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 GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String) context.getAttribute("username");

        resp.setContentType("/text/html");//设置类容类型
        resp.setCharacterEncoding("utf-8");//设置字符编码
        resp.getWriter().print("名字"+username);//显示到前端页面
    }

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

<?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>hello</servlet-name>
    <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>hander</servlet-name>
    <servlet-class>com.kuang.servlet.GetServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>hander</servlet-name>
    <url-pattern>/caodan</url-pattern>
  </servlet-mapping>
</web-app>

测试访问结果:访问hello的时候会得到一个姓名对象,但是没有结果;访问caodan的时候会得到一个姓名的结果

2、获取初始化参数
  <context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
  </context-param>

  <servlet>
    <servlet-name>gp</servlet-name>
    <servlet-class>com.kuang.servlet.ServletDemo03</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>gp</servlet-name>
    <url-pattern>/GP</url-pattern>
  </servlet-mapping>
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String url = context.getInitParameter("url");//获取初始化参数
        resp.getWriter().print(url);
    }
3、请求转发
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入了ServletDemo04");
        ServletContext context = this.getServletContext();
       // RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //获取转发的请求路径
       // requestDispatcher.forward(req,resp);  //调用forward实现请求转发
        context.getRequestDispatcher("/gp").forward(req,resp);
    }

虽然访问的是自己的地址,但是输出的是转发的结果

4、读取资源文件

Properties

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

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

思路:需要一个文件流

username=root
password=123456
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/kuang/servlet/cc.properties");  //获取资源流
    Properties prop = new Properties(); //属性
    prop.load(is); //属性加载
    String username = prop.getProperty("username");
    String password = prop.getProperty("password");
    resp.getWriter().print(username+":"+password);
}

测试即可

6.5、HttpServletResponse

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

  • 如果要获取客户端请求过来的参数:找HttpServletResquest

  • 如果要给客户端响应一些信息:找HttpServletResponse

1、简单分类

负责向浏览器发送数据的方法

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);
2、常见应用
  1. 向浏览器输出信息(上面有)

  2. 下载文件

    1. 要获取下载文件的路径

    2. 下载的文件名是啥

    3. 设置想办法让浏览器能够支持下载我们需要的东西

    4. 获取下载文件的输入流

    5. 创建缓冲区

    6. 获取OutputStream对象

    7. 将FileOutputStream流写入buffer缓冲区

    8. 使用OutputStream将缓冲区中的数据输出到客户端!

      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //1. 要获取下载文件的路径
          String realPath ="D:\\idea2020\\xiangMu\\JavaWeb\\javaweb-02-servlet\\response\\target\\classes\\1.png";
          System.out.println("下载文件路径"+realPath);
          //2. 下载的文件名是啥?
          String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
          //3. 设置想方法让浏览器能够支持(Content-Disposition)下载我们需要的东西
          resp.setHeader("Content-Disposition","attachment;filename="+fileName);
          //4. 获取下载文件的输入流
          FileInputStream in = new FileInputStream(realPath);
          //5. 创建缓冲区
          int len = 0;
          byte[] buffer = new byte[1024];
          //6. 获取OutputStream对象
          ServletOutputStream out = resp.getOutputStream();
          //7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
          while ((len=in.read(buffer))>0){
                  out.write(buffer,0,len);
          }
          //关闭资源
          in.close();
          out.close();
      }
      
3、验证码实现

验证码怎么来的?

  • 前端实现(js判断)

  • 后端实现,需要用到java图片类

        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //如何让浏览器3秒自动刷新一次;
            resp.setHeader("refresh","3");
            //在内存中创建一个图片
            BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
            //得到图片
            Graphics2D g = (Graphics2D)image.getGraphics();//笔
            //设置图片的背景颜色
            g.setColor(Color.white);
            g.fillRect(0,0,80,20);
            //给图片写数据
            g.setColor(Color.BLUE);
            g.setFont(new Font(null,Font.BOLD,20));
            g.drawString(makeNum(),0,20);
            //告诉浏览器,这个请求用图片的方式打开
            resp.setContentType("image/jpg");
            //网站存在缓存,不让浏览器缓存
            resp.setDateHeader("expires",-1);
            resp.setHeader("Cache-Control","no-cache");
            resp.setHeader("Pragma","no-cache");
    
            //把图片写给浏览器
            ImageIO.write(image,"jpg",resp.getOutputStream());
        }
        private String makeNum(){
            Random random = new Random();
            String num = random.nextInt(9999999)+"";
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < 7-num.length() ; i++){
                sb.append("0");
            }
            num = sb.toString()+num;
            return num;
        }
    
    
        <servlet>
            <servlet-name>ImageServlet</servlet-name>
            <servlet-class>com.kuang.servlet.ImageServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>ImageServlet</servlet-name>
            <url-pattern>/ImageServlet</url-pattern>
        </servlet-mapping>
    
4、实现重定向

一个web资源收到客户端请求后,他会通知客户端去访问另外一个web资源,这个过程叫重定向

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TSUhithh-1609049830014)(javaWeb.assets/image-20200908100750928.png)]

常见场景:

  • 用户登录
 void sendRedirect(String var1) throws IOException;

测试:


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
        resp.setHeader("Location","/r/img");
        resp.setStatus(302);
        */
        resp.sendRedirect("/r/img");//重定向
    }

面试题:请你聊聊重定向和转发的区别?

相同点

  • 页面都会实现跳转

不同点

  • 请求转发的时候,url不会产生变化
  • 重定向时候,url地址栏会发生变化

6.6、HttpServletRquest

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

1、获取参数、请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   //后台接收中文乱码问题
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String[] hobbys = req.getParameterValues("hobbys");
    System.out.println("====================================");
    System.out.println(username);
    System.out.println(password);
    System.out.println(Arrays.toString(hobbys));
    System.out.println("====================================");
    //通过请求转发
    //这里的 / 代表当前的web应用
    req.getRequestDispatcher("/success.jsp").forward(req,resp);
}

面试题:请你聊聊重定向和转发的区别?

相同点

  • 页面都会实现跳转

不同点

  • 请求转发的时候,url不会产生变化 307
  • 重定向时候,url地址栏会发生变化 302
新建完一个Maven项目后要做的步骤
  1. 新建包【java (放代码)、resource (放资源文件)】然后标记相应的功能

  2. 把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">
    </web-app>
    
    
  3. 导入相应的pom.xml包 由于是Servlet所以导入Servlet相应的包

        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
        </dependency>
    
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.2.1-b03</version>
        </dependency>
    

7、Cookie、Session

7.1、会话

会话:用户打开一个浏览器,点击了很多链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话

**有状态的会话:**一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过。称之为有状态会话;

你怎么证明你是某某某学校的学生?

你 学校

  1. 发票 学校给你发票
  2. 学校登记 学校标记你来过

一个网站,怎么证明你来过?

客户端 服务端

  1. 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了; cookie
  2. 服务器登记你来过了,下次你来的时候接着匹配你;seesion

7.2、保存会话的两种技术

cookie
  • 客户端技术(响应,请求)
session
  • 服务器技术,利用这个技术,可以保存用户的会话信息?我们可以把信息或者数据放在Session中!

常见:网站登录之后,你下次不用在登录了,第二次访问直接就自动登录上去了

7.3、Cookie

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HbxaUgwR-1609049830016)(javaWeb.assets/image-20200910114415703.png)]

从请求中拿到cookie信息
服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得cookie  客户端给参数请求服务器 然后服务器拿到参数
cookie.getName()  //获得cookie中的key
cookie.getValue()	//获得cookie中的value
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookei,第一个是名字
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie);  //响应给客户端一个cookie
一个cookie是否存在上线!
  • 一个Cookie只能保存一个信息;
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;
  • Cookie大小有限制4kb;
  • 300个cookie浏览器上限
删除Cookie;
  • 不设置有效期,关闭浏览器,自动失效
  • 设置有效期时间为0;
编码解码:
//编码、解码
URLEncoder.encode("哈哈哈","utf-8")
URLDecoder.decode(cookie.getValue(),"UTF-8")
    
            //解决中文乱码
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

7.4、Session(重点)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gcadWLC-1609049830018)(javaWeb.assets/image-20200910114526997.png)]

什么是Session:
  • 服务器会给每一个用户(浏览器)创建一个Seesion对象;
  • 一个Seesion独占一个浏览器,只要浏览器没有关闭,这个Session就存在
  • 用户登录之后,整个网站他都可以访问! 保存用户的信息;保存购物车的信息…
Session和cookie的区别:
  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务创建
使用场景:
  • 保存一个登录用户的信息
  • 购物车信息
  • 在整个网站中经常使用的数据,我们将它保存在Session中;
创建Session及存入数据
    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");
        //通过req创建得到Session
        HttpSession session = req.getSession();
        //给Session中存东西,可以单独存值,也可以把值存入对象。然后通过对象拿到数据
        session.setAttribute("name",new Person("侵权",2));
        //获取Session的ID
        String sessionID = session.getId();
        //判断Session是不是新创建
        if (session.isNew()){//返回一个布尔值
            resp.getWriter().write("session创建成功,ID:"+sessionID);
        }else{
            resp.getWriter().write("session已经在服务器中存在了,ID"+sessionID);
        }
    }
获取Session里的属性
    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");

        HttpSession session = req.getSession();//通过req创建Session
        Person person = (Person) session.getAttribute("name"); //获取存进来的name属性
        resp.getWriter().write("name="+person.getName()+",age="+person.getAge()); //在网页显示存储的数据
        System.out.println(person.toString());//在后台显示存储的数据
    }
注销Session(有两种)
  1. 手动注销
    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");

        HttpSession session = req.getSession();
        String SessionId = session.getId();
        resp.getWriter().write("已移除当前Session:"+ SessionId);

        req.removeAttribute("name"); //移除
        session.invalidate(); //手动注销Session
    }
  1. 会话自动过期
<!--    设置Session的失效时间-->
    <session-config>
<!--        1分钟后Session自动失效,以分钟为准-->
        <session-timeout>1</session-timeout>
    </session-config>

8、JSP

8.1、什么是JSP

java Server Pages:java服务器端页面,也和Servlet一样,用于动态web技术

最大的特点:

  • 写JSP就像在写HTML
  • 区别:
    • HTML只给用户提供静态的数据
    • JSP页面中可以嵌入java代码,为用户提供动态数据;

8.2、JSP原理

运行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2xaRzrLd-1609049830019)(javaWeb.assets/image-20201128100651054.png)]

在JSP页面中;

只要是java代码就会原封不动的输出

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

out.write("<html>")

这样的格式,输出到前端

8.3、JSP基础语法

任何语言都有自己的语法,Java中有,JSP作为java技术的一种应用,它拥有一些自己扩充的语法(了解知道即可),java所有语法都支持

JSP表达式
  JSP表达式
  作用:用来将程序的输出,输出到客户端
  <%= 变量或者表达式%>


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

jsp脚本片段
<%-- jsp脚本片段--%>

  <%
    int sum = 0;
    for (int i = 0; i < 100; i++) {
      sum+=i;
    }
    out.println("<h1>Sum="+sum+"</h1>");
  %>
脚本片段再实现
<%
  String aa = "hello";
  out.println(aa);
%>
<p>得得得运行</p>
<%
  int i = 5;
  out.println(i);
%>

<%
  for (int i1 = 0; i1 < 5; i1++) {

%>
<h1>hhh<%=i1 %></h1>
<% } %>
JSP声明
<%!
  static {
    System.out.println("Loading Servlet");
  }

  private int glibalVar = 0;

  public void kuang(){
    System.out.println("进入了方法kuang");
  }
%>

JSP声明:会被编译到JSP生成的java类中!其他的,就会被生成到**_jspServlet方法中**!

在JSP。嵌入Java代码即可!

<%%>         <!--jsp脚本片段-->
<%=%>		<!--JSP表达式-->
<%!%>		<!--JSP声明 全局-->

<%--注释--%>

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

8.4、JSP指令

<%@page args.... %>

<%--@include会将两个页面合二为一--%>
<%@include file="页面1"%>
	<% int i = 10; %>
<%@include file="页面2"%>
<!--当在一个页面里面定义int i = 10; 然后又在@include里面定义 int i = 10;就会报错,栈溢出-->

  拼接页面 就是让两个页面在一个页面中展示
<%--jsp标签  jsp::include:拼接页面,本质上还是那个数--%>
<jsp:include page="页面1">
    <% int i = 10; %>
<jsp:include page="页面2">    
    <!--当在一个页面里面定义int i = 10; 然后又在 include 里面定义 int i = 10;不会报错,因为他们是不一样的存储空间-->

8.5、定义错误页面

可以在当前页面指定错误页面

<%@ page errorPage="error/500.jsp" %>

也可以在配置文件里面定义(推荐)

<!--报err的时候根据状态码进入到状态码所对应的页面-->
<error-page>
    <error-code>404</error-code>
    <location>/error/404.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/error/500.jsp</location>
</error-page>

8.6、9大内置对象

  • PageContext 页面上下文 作用:存东西
  • Request 请求 作用:存东西
  • Response 响应
  • Session 会话 作用:存东西
  • Application 【ServletContext】 应用 作用:存东西
  • config 【ServletConfig】 配置
  • out 输出
  • page 页
  • exception 异常
<%--内置对象--%>
<%
    //存
    pageContext.setAttribute("name1","大锤1号");//保存的数据只在一个页面中有效
    request.setAttribute("name2","大锤2号");   //保存的数据只在一次请求中有效,请求转发会携带这个数据
    session.setAttribute("name3","大锤3号");   //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    application.setAttribute("name4","大锤4号");   //保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>

<%
    //都可以通过.getAttribute来取,但是现在尝试下寻找的方式来取
    //从pageContext取出,我们通过寻找的方式来
    //从底层到高层(作用域):page->request->session->application

	//双亲委派机制:如果要去寻找一个类,先在上面找,要是找不到在一层一层的向下找,要是还找不到就告诉你 class notfoot
    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");
%>

<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<%--<h3> ${name5} </h3>  用这个的话会过滤空值--%>
<h3><%=name5%></h3>  <%--用这个的话不会过滤空值,会输出null--%>

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻 ;用户看完就没用

session:客户端向服务器发送请求,产生的数据,用户看完一会还有用,比如:购物车

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可以使用,比如:聊天数据

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

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

EL表达式: ${ }

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象
JSP标签
<%--jsp:include page--%>   <%--拼接--%>

<%--相当于:http//localhost:8080/jsptag.jsp?【name=dachui】 【&age=15】--%>
<jsp:forward page="jsptag2.jsp">  <%--转发页面--%>
    <jsp:param name="name" value="dachui"/>  <%--转发的时候携带参数--%>
    <jsp:param name="age" value="15"/>
</jsp:forward>

<%--取出参数--%>
姓名:<%=request.getParameter("name")%>
年龄:<%=request.getParameter("age")%>
JSTL表达式

JSTL标签库的使用就是为了弥补HTML标签的不足;他自定义许多标签,可以供我们使用,标签的功能和java代码一样

核心标签(掌握部分)

格式化标签

SQL标签

XML标签

有上面这4个标签 用的时候可以去菜鸟教程里面搜索使用

JSTL标签库使用步骤

  • 引入对应的taglib
  • 使用其中的方法
  • 在Tomcat中也需要引入jstl的包,否则会报错:jstl解析错误

c:if

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

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

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

c:choose c:when

<body>
<%-- 用于保存数据 var:存储信息的变量 scope:var属性的作用域 value:要存储的值 --%>
<c:set var="shujv" scope="session" value="55"/>

<%-- 本身只当做<c:when>和<c:otherwise>的父标签 --%>
<c:choose>
    <%-- <c:choose>的子标签,用来判断条件是否成立  test:条件 --%>
    <c:when test="${shujv>=90}">
        优秀
    </c:when>
    <c:when test="${shujv>=70}">
        良好
    </c:when>
    <c:when test="${shujv>=60}">
        及格
    </c:when>
    <c:when test="${shujv<=60}">
        不及格
    </c:when>
</c:choose>

</body>

c:forEach

<body>

<%
    ArrayList<String> people = new ArrayList<>();
    people.add(0,"张三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"赵六");
    request.setAttribute("list",people);  //放置people里面的值到list名字里面
%>
<%-- forEach 基础迭代标签,接受多种集合类型 --%>
<c:forEach var="shujv" items="${list}">
   <%-- out 用于在JSP中显示数据,就像<%= ... >--%>
    <c:out value="${shujv}"/><br>
</c:forEach>
<%--
var :代表当前条目的变量名称
items :要被循环的信息
begin :开始的元素(0=第一个元素,1=第二个元素)
end :最后一个元素(0=第一个元素,1=第二个元素)
step :每一次迭代的步长
--%>
<c:forEach var="shujv" items="${list}" begin="1" end="3" step="2" >
    <c:out value="${shujv}"/>
</c:forEach>

</body>

9、JavaBean

实体类

JavaBean有特定的写法:

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

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

ORM:对象关系映射

  • 表->类 一张表 对应 一个类
  • 字段->属性 一个字段 对应 一个属性
  • 行记录->对象 一行记录 对应 一个对象

people表

idnameageregion
1张三15广东
2李四45北京
3王五32上海

对应 类

class people {
    private int id;
    private String name;
    private int age;
    private String region;
}

class A{
    new people(1,"张三",15,"广东");
    new people(2,"李四",45,"北京");
    new people(3,"王五",32,"上海");
}

10、MVC三层架构

什么是MVC:Model(模型) view(视图) Controller(控制器)

10.1、早些年

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgCoGtNN-1609049830021)(javaWeb.assets/image-20201204130458436.png)]

用户直接访问控制层,控制层就可以直接操作数据库;

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码

10.2、MVC三层架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U82uLazy-1609049830023)(javaWeb.assets/image-20201204131902496.png)]

Model

  • 业务处理:业务逻辑(Service)
  • 数据持久化:CRUD(Dao)

View

  • 展示数据
  • 提供链接发起Servlet请求(a、form、img…)

Controller(Servlet)

  • 接收用户的请求:(req:请求参数、Session信息…)

  • 交给业务层处理对应的代码

  • 控制视图的跳转

    登录—>接收用户的登录请求—>处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)—>Dao层查询用户名和密码是否正确—>数据库

    下面是自我理解

/* 用户通过-->(view视图层)点击操作 发送请求(里面携带参数)-->{ Controller(Servlet控制层)接收用户的请求及发来的参数 }-->{ Model(service业务层)拿到传递过来的参数-->
(Dao层数据持久化)拿到传递过来的参数跟写好的sql语句 传递进写好的工具类-->调用写好的工具类(里面有连接数据库的方法以及增删改查的方法) }-->连接上数据库-->{ Model 调用了工具类的查询方法,返回一个结果集 -->(Dao)拿到结果集,然后对数据进行操作,放到一个结果集里面,返回出去 -->(service业务层)拿到返回过来的结果集,放到一个变量里,再把变量返回出去 } -->{ Controller (Servlet控制层)拿到返回过来的结果集后 对结果集进行一些判断操作,返回给视图层数据} -->(view 视图层)拿到控制层过来的数据,显示给用户看 */

11、Filter(过滤器) 重点

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

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQlxIJBR-1609049830025)(javaWeb.assets/image-20201204135240154.png)]

Filter开发步骤:

  1. pom导入包

  2. 编写过滤器

    1. 导包不要错,导入javax.servlet下的包

    2. 实现Filter接口,重写对应的方法即可

      package com.kuang.filter;
      
      import javax.servlet.*;
      import java.io.IOException;
      
      public class CharacterEncodingFilter implements Filter {
          //初始化:web服务器启动,就已经初始化了,随时等待过滤对象出现
          public void init(FilterConfig filterConfig) throws ServletException {
              System.out.println("CharacterEncodingFilter初始化");
          }
          /*
          chain 链
          过滤中的所有代码,再过滤待定请求的时候都会执行
          必须要让过滤器继续同行
              chain.doFilter(request,response)
           */
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
              request.setCharacterEncoding("utf-16");
              response.setCharacterEncoding("utf-16");
              response.setContentType("text/html;charset=UTF-8");
      
              System.out.println("CharacterEncodingFilter过滤前");
              chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
              System.out.println("CharacterEncodingFilter过滤后");
          }
          //销毁:web服务器关闭的时候,过滤会销毁
          public void destroy() {
              System.out.println("CharacterEncodingFilter销毁");
          }
      }
      
      
    3. 在web.xml中配置Filter

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

12、监听器

实现一个监听器的接口,(有n种)

  1. 编写一个监听器

    实现监听器的接口

    package com.kuang.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    public class OnlineCountListener implements HttpSessionListener {
        //创建session监听; 看你的一举一动
        //一旦创建Session就会触发一次这个事件
        public void sessionCreated(HttpSessionEvent se) {
            ServletContext ctx = se.getSession().getServletContext();
            System.out.println(se.getSession().getId());
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
            if (onlineCount == null){
                onlineCount = new Integer(1);
            }else{
                int count = onlineCount.intValue();
                onlineCount = new Integer(count+1);
            }
            ctx.setAttribute("OnlineCount",onlineCount);
        }
        //销毁session监听
        //一旦销毁session就会触发一次这个事件
        public void sessionDestroyed(HttpSessionEvent se) {
            ServletContext ctx = se.getSession().getServletContext();
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
            if (onlineCount == null){
                onlineCount = new Integer(0);
            }else{
                int count = onlineCount.intValue();
                onlineCount = new Integer(count-1);
            }
            ctx.setAttribute("OnlineCount",onlineCount);
        }
        /*
            Session销毁:
            1.手动销毁 getSession().invalidate();
            2.自动销毁 web.xml文件里面配置失效时间
        */
    }
    
    
  2. web.xml中注册监听器

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

13、过滤器、监听器常见应用

监听器:GUI编程中经常使用 GUI:图形界面编程

过滤器: 例子:用户登录之后才能进入主页!用户销毁后不能进入主页了!

  1. 用户登录之后,向Session中放入用户的数据

  2. 进入主页的时候判断用户是否已经登录;要求:在过滤器中实现!

        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;  //需要转换后才能获取到Session
            HttpServletResponse response = (HttpServletResponse)  servletResponse;
    
            if (request.getSession().getAttribute(Constant.USER_SESSION)==null){  
                response.sendRedirect("/error.jsp");  //获取Session里面的信息是否为空,为空就跳转到重定向的页面
            }
            filterChain.doFilter(servletRequest,servletResponse);
        }
    

14、JDBC

什么是JDBC:java连接数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-witx7aIo-1609049830026)(javaWeb.assets/image-20201205093035056.png)]

需要jar包支持:

  • java.sql
  • javax.sql
  • mysql-connector-java

编写好sql语句并插入数据

CREATE TABLE users(
    id INT PRIMARY KEY,
    `name` VARCHAR(40),
    `password` VARCHAR(40),
    email VARCHAR(60),
    birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','zs@qq.com','2000-02-02');

导入数据库依赖

<!--        mysql的驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>

IDEA中连接数据库

JDBC固定步骤

1.加载驱动

2.连接数据库,代表数据库

3.向数据库发送SQL的对象Statement prepareStatement :CRUD

4.编写SQL

5.执行SQL

6.关闭资源

package com.kuang.test;

import java.sql.*;

public class TestJdbc {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC";
        String username = "root";
        String password = "123456";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url,username,password);

        //3.向数据库发送SQL的对象Statement prepareStatement :CRUD
        Statement statement = connection.createStatement();
        //4.编写SQL
        String sql = "select * from users";

        //5.执行查询SQL,返回一个ResultSet:结果集
        ResultSet rs = statement.executeQuery(sql);

        while (rs.next()){
            System.out.println("id"+rs.getObject("id"));
            System.out.println("name"+rs.getObject("name"));
            System.out.println("password"+rs.getObject("password"));
            System.out.println("email"+rs.getObject("email"));
            System.out.println("birthday"+rs.getObject("birthday"));
        }

        //6.关闭资源
        rs.close();
        statement.close();
        connection.close();
    }
}

预编译SQL
package com.kuang.test;

import java.sql.*;

public class TestJdbc2 {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC";
        String username = "root";
        String password = "123456";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url,username,password);

        //3.编写SQL
        String sql ="insert into users(id, name, password, email, birthday) VALUE (?,?,?,?,?)";

        //4.预编译  的sql在后面执行sql的时候不用要,直接执行就可以了
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
            //写入value值每个占位符的内容
        preparedStatement.setInt(1,7);
        preparedStatement.setString(2,"卢九");
        preparedStatement.setString(3,"123456");
        preparedStatement.setString(4,"lj@qq.com");
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));

        //5.执行SQL
        int i = preparedStatement.executeUpdate();

        if (i>0){
            System.out.println("插入成功");
        }

        //6.关闭资源
        preparedStatement.close();
        connection.close();
    }
}

事务

要么都成功,要么都失败!

ACID原则:保证数据的安全

开启事务
事务提交  commit()
事务回滚  rollback()
关闭事务

junit单元测试

依赖

<!--        单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>

简单使用

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行

    @Test
    public void test(){
        System.out.println("输出");
    }

创建好数据库表以及添加响应数据后就可以写事务了:取钱事务,如果有一方在转账的期间出现错误,则会回滚

package com.kuang.test;


import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TestJdbc3 {

    @Test
    public void test(){
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC";
        String username = "root";
        String password = "123456";

        Connection connection = null;

        try {
            //1.加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.连接数据库,代表数据库
             connection = DriverManager.getConnection(url,username,password);
             //3.通知事务开启 ,false 开启
            connection.setAutoCommit(false);
            //编写sql语句事务
            String sql1 = "update account set money = money-100 where name = 'A'";
            connection.prepareStatement(sql1).executeUpdate();
            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();

            //4.以上两条都执行成功了就提交事务
            connection.commit();
            System.out.println("success");

        }catch (Exception e){
            try {
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值