完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习

JavaWeb

java Web

前端–>Mysql

IDEA版本2020.1.2

1.基本概念

1.1前言

web开发:

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

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

1.2、Web应用程序

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

  • a.html、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、这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取,通络。
    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第1张图片

  • 静态Web存在的缺点

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

1.4、动态Web

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

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第2张图片

缺点:

  • 假如服务器的动态Web资源出现错误,我们需要重新编写我们的后台程序,重新发布
    • 停机维护

优点:

  • Web页面可以动态更新,所有用户看到的都不是同一个页面

  • 它可以和数据库交互(数据无法持久化:注册,商品信息)

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第3张图片

分析原理、看源码

2、Web服务器

2.1、编程软件

ASP:

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

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 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。

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

(可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。)

Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。

工作3-5年后,可以尝试手写Tomcat服务器;

下载tomcat:

  1. 安装 or 解压
  2. 了解配置文件及目录结构
  3. 这个东西的作用

3、Tomcat

3.1、安装Tomcat

Tomcat官方链接:https://tomcat.apache.org/

下载:

Tomcat安装包

Tomcat压缩包

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第4张图片

3.2、Tomcat启动和配置

  • 各文件夹的功能与作用:

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第5张图片

  • 启动,关闭Tomcat
  1. 打开下载解压的apache-tomcat-9.0.46

  2. 进入bin目录

  3. 找到startup.bat开启服务器,找到shutdown.bat关闭服务器

    在这里插入图片描述

  • 网站访问 http://localhost:8080/

可能遇到的问题:

  1. Java环境变量没有配置
  2. 闪退问题:需要配置兼容性
  3. 乱码问题:配置文件中设置

3.3、配置

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第6张图片

server.xml文件:服务器的核心配置文件

  • 可以配置启动的端口号:
    在这里插入图片描述

    • tomcat默认端口号:8080
    • mysql默认端口号:3306
    • http默认端口号:80
    • https默认端口号:443
  • 可以配置主机的名称:在这里插入图片描述

    • 默认的主机名为:localhost–>127.0.0.1
    • 默认网站应用存放的位置为:webapps

    高难度面试题:

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

    1. 输入一个域名+enter
    2. 检查本机的:C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名的映射
      1. 有:直接返回对应的ip的地址,这个地址中,有我们需要访问的web程序,可以直接访问
        完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第7张图片

      2. 没有:去DNS服务器上找(全世界的域名都在这里管理),找到的话就返回,找不到就返回找不到

    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第8张图片

  1. 可以配置一下环境变量(可选性)

3.4、发布一个web网站

不会就先模仿

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

网站应该有的结构:

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

4、HTTP

4.1、什么是Http

超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。

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

Https:s代表安全的

  • 默认端口号:443

4.2、两个时代

  • http1.0
    • HTTP/1.0:客户端可以与web服务器连接,之后只能获得一个web资源,断开连接
  • http2.0
    • HTTP/1.1:客户端可以与web服务器连接,可以获得多个web资源

4.3、Http请求

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

百度:

Request URL: https://www.baidu.com/  请求地址
Request Method: GET        get方法/post方法
Status Code: 200 OK        状态码:200
Remote(远程) Address: 36.152.44.95:443     
Accept: text/htmlapplication/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9  语言
Cache-Control: max-age=0 
Connection: keep-alive 

1、请求行

  • 请求行中的请求方式:GET
  • 请求方式: GET,POST,HEAD,DELEFE,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响应

  • 服务器 —响应(Response)—> 客户端

百度:

Cache-Control: private  缓存控制
Connection: keep-alive  连接
Content-Encoding: gzip  编码
Content-Type: text/html;charset=utf-8   类型

1、响应体

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

2、响应状态码(重点)

200: 请求响应成功

3×:请求重定向

  • 重定向:你重新到我给你的新位置去;

4××: 找不到资源

  • 资源不存在

5××: 服务器代码错误 500 502:网关错误

面试题:

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

5、Maven

启动Tomcat,进入网站链接:http://localhost:8080/examples/servlets/,代码案例

为什么要学习这个技术?

  1. 在javaweb开发中,需要使用大量的jar包,我们需要手动去导入。
  2. 如何能够让一个东西自动帮我们导入和配置这个jar包。

由此,Maven诞生了!

5.1、Maven项目架构管理工具

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

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

  • 有约束,不要去违反。

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

5.2、下载安装Maven

官网:https://maven.apache.org/

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第9张图片

下载完成后解压即可

5.3、配置环境变量

在我们的系统环境变量中

配置如下配置:

  • M2_HOME maven目录下的bin目录:D:\Maven\apache-maven-3.6.1\bin
  • MAVEN_HOME maven目录:D:\Maven\apache-maven-3.6.1
  • path目录中新建配置:%MAVEN_HOME%\bin
  • 打开命令窗口输入mvn -version测试配置是否完成。

5.4、阿里云镜像

修改镜像:在maven的conf文件夹下的settings.xml中进行配置

  • 镜像:mirrors
    • 作用:加速我们的下载
  • 国内建议使用阿里云镜像
<mirror>
    <id>nexus-aliyunid>
    <mirrorOf>*,!jeecg,!jeecg-snapshotsmirrorOf>
    <name>Nexus aliyunname>
    <url>http://maven.aliyun.com/nexus/content/groups/publicurl>
 mirror>

5.5、修改本地仓库

本地的仓库,远程仓库

修改仓库:在maven的conf文件夹下的settings.xml中进行配置

**建立本地仓库:**localRepository

<localRepository>D:\Maven\apache-maven-3.6.1\maven-repolocalRepository>

5.6、在Idea中使用Maven

  1. 打开IDEA

  2. 创建一个Maven项目

    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第10张图片
    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第11张图片
    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第12张图片
    在这里插入图片描述

  3. 等待项目初始化完毕
    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第13张图片

出现BUILD SUCCESS 下载成功

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第14张图片

  1. 观察maven仓库中多了什么

  2. IDEA中的Maven设置

​ IDEA项目创建成功后,看一眼Maven的配置(防止IDEA默认将本地仓库等换成Idea自己的)

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第15张图片

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第16张图片

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

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

  1. 新建项目
    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第17张图片

  2. 以下步骤和上次一样。

最终得到的项目结构:
完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第18张图片

之前的项目结构:完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第19张图片

5.8、标记文件夹功能

方法一:

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第20张图片

方法二:完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第21张图片
完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第22张图片

5.9、在IDEA中配置Tomcat

第一步:完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第23张图片

第二步:
完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第24张图片

第三步:完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第25张图片

解决警告问题:

为什么会有这个问题:我们访问一个网站,需要指定一个文件夹的名字;

必须要有的配置:完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第26张图片
完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第27张图片

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第28张图片

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第29张图片

  • 不写:默认访问路径为localhost:8080

  • 写了一个/yang:默认访问路径为localhost:8080/yang

这个过程叫做:虚拟路径映射

最后:启动Tomcat

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第30张图片

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第31张图片
关于Tomcat启动乱码问题:

  • 在tomcat Server中设置 VM options , 值为 -Dfile.encoding=UTF-8 ,(显然没生效)

    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第32张图片

  • 在setting中的 File encodings 中设置编码格式,发现这是设置页面编码格式的,(显然也没生效)

    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第33张图片

  • 在java Complier中设置Additional command line parameters的值,-encoding=UTF-8,(显然还没生效)

    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第34张图片

  • 在bin中设置idea.exe.vmoptions和idea64.exe.vmoptions中的参数,同时增加-Dfile.encoding=UTF-8,据说有些人保存后重启就可以了,(显然我这边还是没生效)

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第35张图片

  • 在tomcat \bin目录下的catalina.bat文件中加入 -Dfile.encoding=UTF-8,(显然还不生效)

  • 在 tomcat / conf 目录下,设置 logging.properties ,增加参数 java.util.logging.ConsoleHandler.encoding = GBK,重启后终于可以了
    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第36张图片

5.10、pom文件

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

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第37张图片

代码




<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.0modelVersion>

  
  <groupId>com.yanggroupId>
  <artifactId>javaweb-01-mavenartifactId>
  <version>1.0-SNAPSHOTversion>
  
  <packaging>warpackaging>

  
  <properties>
    
    <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    
    <maven.compiler.source>1.7maven.compiler.source>
    <maven.compiler.target>1.7maven.compiler.target>
  properties>

  
  <dependencies>
    
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>4.11version>
    dependency>
  dependencies>

  
  <build>
    <finalName>javaweb-01-mavenfinalName>
    <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-clean-pluginartifactId>
          <version>3.1.0version>
        plugin>
        
        <plugin>
          <artifactId>maven-resources-pluginartifactId>
          <version>3.0.2version>
        plugin>
        <plugin>
          <artifactId>maven-compiler-pluginartifactId>
          <version>3.8.0version>
        plugin>
        <plugin>
          <artifactId>maven-surefire-pluginartifactId>
          <version>2.22.1version>
        plugin>
        <plugin>
          <artifactId>maven-war-pluginartifactId>
          <version>3.2.2version>
        plugin>
        <plugin>
          <artifactId>maven-install-pluginartifactId>
          <version>2.5.2version>
        plugin>
        <plugin>
          <artifactId>maven-deploy-pluginartifactId>
          <version>2.8.2version>
        plugin>
      plugins>
    pluginManagement>
  build>
project>

创建一个空项目的Maven,自己配置Maven的pom.xml文件

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第38张图片

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

build中配置resources,来防止我们资源导出失败的问题


    <build>
        <resources>
            <resource>
                <directory>src/main/javadirectory>
                <includes>
                    <include>**/*.propertiesinclude>
                    <include>**/*.xmlinclude>
                includes>
                <filtering>falsefiltering>
            resource>
            <resource>
                <directory>src/main/resourcesdirectory>
                <includes>
                    <include>**/*.propertiesinclude>
                    <include>**/*.xmlinclude>
                includes>
                <filtering>falsefiltering>
            resource>
        resources>
    build>

5.11、Idea操作

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第39张图片
完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第40张图片

5.12、解决遇到的问题

  1. Maven:无法导入

    • 解决方法:降级maven
  2. Tomcat闪退

    • jdk版本/系统环境配置
  3. IDEA每次都要重复配置Maven

    • 在IDEA中的全局默认配置中去配置
  4. Maven项目中Tomcat无法配置

  5. maven默认web项目中的web.xml版本问题

    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第41张图片

    • 替换为webapp4.0版本,和Tomcat的webapps/ROOT/WEB-INF里面的web.xml文件里的一致

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

5.13、Maven仓库的使用

Maven仓库网站链接:https://mvnrepository.com/

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第42张图片

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第43张图片

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第44张图片

<dependency>
  <groupId>javax.servletgroupId>
  <artifactId>javax.servlet-apiartifactId>
  <version>4.0.1version>
  
  <scope>providedscope>
dependency>

6、Servlet

6.1、Servlet简介

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

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

6.2、HelloServlet

Servlet接口在Sun有两个默认的实现类:HttpServletGenericServlet

  1. 构建一个空的Maven项目,删掉src目录,以后我们的学习就在这项目里面建立moudle,这个空的工程就是Maven的主工程

  2. 在主工程中导入依赖,其他的子工程就会有相应的依赖

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

    父项目中会有Moudle

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

    子项目中会有Parent

    <parent>
        <artifactId>javaweb-02-ServletartifactId>
        <groupId>com.yanggroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    

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

    son extends father
    
  4. Maven环境优化

    1. 修改web.xml为最新的
    2. 将Maven结构搭建完整
  5. 编写一个Servlet程序

    1. 编写一个普通类HelloServlet
    2. 实现Servlet接口,这里我们直接继承HttpServlet实现类
    public class HelloServlet extends HttpServlet {
        
        //由于get或post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样。
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            
            //ServletOutputStream outputStream = resp.getOutputStream();
            PrintWriter writer = resp.getWriter();//响应流
            writer.print("Hello Servlet");
            
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  6. 编写Servlet的映射

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

    在web.xml中进行web应用的核心编写

    
    <servlet>
        <servlet-name>Hello Servletservlet-name>
        <servlet-class>com.yang.Servlet.HelloServletservlet-class>
    servlet>
    
    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>/hellourl-pattern>
    servlet-mapping>
    
  7. 配置Tomcat

    注意:配置项目发布的路径。

  8. 启动测试

6.3、Servlet原理

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

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第45张图片

6.4、Mapping问题

HelloServlet类处理请求,发送响应,代码的编写

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);
    }
}
  1. 一个Servlet请求可以指定一个映射路径

    
    <servlet>
        <servlet-name>Hello Servletservlet-name>
        <servlet-class>com.yang.Servlet.HelloServletservlet-class>
    servlet>
    
    
    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>/hellourl-pattern>
    servlet-mapping>
    
  2. 一个Servlet请求可以指定多个映射路径

    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>/hellourl-pattern>
    servlet-mapping>
    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>/hello2url-pattern>
    servlet-mapping>
    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>/hello3url-pattern>
    servlet-mapping>
    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>/hello4url-pattern>
    servlet-mapping>
    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>/hello5url-pattern>
    servlet-mapping>
    
  3. 一个Servlet请求可以指定通用映射路径

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

    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>/*url-pattern>
    servlet-mapping>
    
  5. 指定一些后缀或者前缀等等…

    
    
    <servlet-mapping>
        <servlet-name>Hello Servletservlet-name>
        <url-pattern>*.yangqiurl-pattern>
    servlet-mapping>
    
  6. 优先级问题

    指定了固有的mapping映射路径优先级最高,如果找不到就会走默认的处理请求;

  7. 映射路径404问题

    web.xml映射Servlet

    
    <servlet>
        <servlet-name>errorservlet-name>
        <servlet-class>com.yang.Servlet.ErrorServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>errorservlet-name>
        <url-pattern>/*url-pattern>
    servlet-mapping>
    

    ErrorServlet代码的编写

    public class ErrorServlet extends HelloServlet{
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            resp.setContentType("text/html");
            resp.setCharacterEncoding("utf-8");
            PrintWriter writer = resp.getWriter();
            writer.print("

    你访问的页面不存在,请重新输入!

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

6.5、ServletContext

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

父项目中创建一个note.md文件,方便之后子工程web.xml编代码用,里面输入代码:

web.xml
```xml





```
  • 新建一个普通的Moudle命名servlet-02
  • Tomcat选择servlet-02
  • 创建相应的结构
  • 创建类HelloServlet和web.xml映射

6.5.1、共享数据

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

    放置ServletContext内容的类

    public class HelloServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            /*HelloServlet父类HttpServlet中的各种方法:
            *   this.getInitParameter(); 初始化参数
                this.getServletConfig(); Servlet配置
                this.getServletContext(); Servlet上下文
            *   ...*/
    		//this.getServletContext()转发
            ServletContext context = this.getServletContext();
            String username = "扬启";
    
            context.setAttribute("username",username); //将一个数据保存在了ServletContext中 ,名字为:username , 值为:username
        }
    }
    

    读取ServletContext内容的类

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

    设置web.xml的映射

    
    <servlet>
        <servlet-name>ServletContextservlet-name>
        <servlet-class>com.yang.Servlet.GetServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>ServletContextservlet-name>
        <url-pattern>/contexturl-pattern>
    servlet-mapping>
    
  • 先在浏览器上访问hello,将username内容放到ServletContext中

  • 再访问context,将username内容读取出来

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第46张图片

6.5.2、获取初始化参数

配置相关的映射来获取初始化参数


<context-param>
    <param-name>urlparam-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis?param-value>
context-param>

<servlet>
    <servlet-name>getParameterservlet-name>
    <servlet-class>com.yang.Servlet.ServletDemo03servlet-class>
servlet>
<servlet-mapping>
    <servlet-name>getParameterservlet-name>
    <url-pattern>/getpurl-pattern>
servlet-mapping>

创建一个新的类ServletDemo03,进行使用初始化参数

public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String url = context.getInitParameter("url");

        resp.getWriter().print(url);
    }
}

6.5.3、请求转发(RequestDispatcher)

创建一个类ServletDemo04,进行请求转发

public class ServletDemo04 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/getp"); //转发的路径

        requestDispatcher.forward(req,resp); //调用forward()进行请求转发
    }
}

在web.xml中进行相关的映射


<servlet>
    <servlet-name>requestDispatcherservlet-name>
    <servlet-class>com.yang.Servlet.ServletDemo04servlet-class>
servlet>
<servlet-mapping>
    <servlet-name>requestDispatcherservlet-name>
    <url-pattern>/getrequestDurl-pattern>
servlet-mapping>

结果:

在浏览器getrequestD中显示的getp的页面

6.5.4、读取资源文件

Properties:

  • 在resources目录下新建一个Properties
  • 在java目录下新建一个Properties

发现:都被打包到了同一个路径下–>classes,我们俗称这个路径为类路径classpath;

思路:需要一个文件流

db.properties

username=root
password=123456

代码

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

        InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");//把资源当成一个流  /代表当前路径

        Properties prop = new Properties();
        prop.load(stream);  //加载流
        String user = prop.getProperty("username"); //设置属性
        String pwd = prop.getProperty("password");

        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().println("账号:"+user+"密码:"+pwd);
    }
}

访问测试接口。

6.6、HttpServletResponse

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

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

6.6.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);

	...

响应的状态码

    int SC_CONTINUE = 100;
    int SC_SWITCHING_PROTOCOLS = 101;
    int SC_OK = 200;
    int SC_CREATED = 201;
    int SC_ACCEPTED = 202;
    int SC_NON_AUTHORITATIVE_INFORMATION = 203;
    int SC_NO_CONTENT = 204;
    int SC_RESET_CONTENT = 205;
    int SC_PARTIAL_CONTENT = 206;
    int SC_MULTIPLE_CHOICES = 300;
    int SC_MOVED_PERMANENTLY = 301;
    int SC_MOVED_TEMPORARILY = 302;
    int SC_FOUND = 302;
    int SC_SEE_OTHER = 303;
    int SC_NOT_MODIFIED = 304;
    int SC_USE_PROXY = 305;
    int SC_TEMPORARY_REDIRECT = 307;
    int SC_BAD_REQUEST = 400;
    int SC_UNAUTHORIZED = 401;
    int SC_PAYMENT_REQUIRED = 402;
    int SC_FORBIDDEN = 403;
    int SC_NOT_FOUND = 404;
    int SC_METHOD_NOT_ALLOWED = 405;
    int SC_NOT_ACCEPTABLE = 406;
    int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
    int SC_REQUEST_TIMEOUT = 408;
    int SC_CONFLICT = 409;
    int SC_GONE = 410;
    int SC_LENGTH_REQUIRED = 411;
    int SC_PRECONDITION_FAILED = 412;
    int SC_REQUEST_ENTITY_TOO_LARGE = 413;
    int SC_REQUEST_URI_TOO_LONG = 414;
    int SC_UNSUPPORTED_MEDIA_TYPE = 415;
    int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
    int SC_EXPECTATION_FAILED = 417;
    int SC_INTERNAL_SERVER_ERROR = 500;
    int SC_NOT_IMPLEMENTED = 501;
    int SC_BAD_GATEWAY = 502;
    int SC_SERVICE_UNAVAILABLE = 503;
    int SC_GATEWAY_TIMEOUT = 504;
    int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

6.6.2、下载文件

  1. 向浏览器输出消息 (前面一直在讲,就不说了)
  2. 下载文件
    1. 要获取下载文件的路径。
    2. 下载的文件名是啥?
    3. 想办法设置让浏览器能够支持下载我们需要的东西。
    4. 获取下载文件的输入流。
    5. 创建缓冲区。
    6. 获取OutputStream对象。
    7. 将FileOutputStream流写入到buffer缓冲区。
    8. 使用OutputStream将缓冲区中的数据输出到客户端!
  • 创建一个新的Maven项目:response
  • 创建结构目录
  • 改变web.xml的代码为最新版
  • 创建包com.yang.servlet

创建一个类FileServlet

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

        //1.获取下载文件的路径
        //String realPath = this.getServletContext().getRealPath("/1.jpg");获取的Tomcat中Servlet下的路径
        String realPath = "D:\\IDEAStudy\\javaweb-02-Servlet\\response\\src\\main\\resources\\头像.jpg";
        System.out.println("下载文件的路径"+realPath);

        //2.下载的文件名是啥?
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);

        //3.想办法设置让浏览器支持(Content-Disposition)我们下载的东西,attachment:附件,
        //中文文件名用URLEncoding.encode编码,否则可能会乱码
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));

        //4.获取下载文件的输入流
        FileInputStream inputStream = new FileInputStream(realPath);

        //5.创建缓冲区
        int len = 10;
        byte[] buffer = new byte[1024];

        //6.获取OutputStream对象
        ServletOutputStream out = resp.getOutputStream();

        //7.将FileInputStream写入到buffer缓冲区,使用OutputStream将缓冲区内的数据写入到客户端!
        while ((len=inputStream.read(buffer))>0){
            out.write(buffer,0,len);
        }

        inputStream.close();
        out.close();
    }

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

注册Servlet

6.6.3、验证码功能

验证码怎么来的?

  • 前端实现
  • 后端实现,需要用到java的图片类,生成一个图片

新建一个类ImageServlet进行测试验证码图片

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

        //在内存中创建一个图片  宽:80,高:20
        BufferedImage Image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);

        //得到图片,创建画笔
        Graphics2D graphics =(Graphics2D) Image.getGraphics();

        //设置图片的背景颜色  从(0,0) 到(80,20)
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0,0,80,20); //填充颜色

        //给图片中写入数据
        graphics.setColor(Color.black);
        graphics.setFont(new Font(null,Font.BOLD,20));
        graphics.drawString(makeNum(),0,20); //画一个字符串

        //告诉浏览器以图片的方式打开
        resp.setContentType("image/jpeg");

        //浏览器中有缓存,不让浏览器缓存
        resp.setDateHeader("expires",-1); //-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)+""; //字符串
        //创建对象,填充数字不足的位置为0  ,stringBuffer:可变字符串
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < 7-num.length(); i++) {
            stringBuffer.append("0");
        }
        num = stringBuffer.toString()+num;
        return num;
    }

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

web.xml中编写注册一个新的Servlet

<servlet>
	<servlet-name>ImageServletservlet-name>
    <servlet-class>com.yang.Servlet.ImageServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>ImageServletservlet-name>
    <url-pattern>/imageurl-pattern>
servlet-mapping>

访问测试。

6.6.4、实现重定向

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第47张图片

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

常见场景:

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

测试:

新建一个类RedirectServlet

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

        resp.sendRedirect("/response/image"); //重定向

        /*
        * resp.sendRedirect("/response/image");可以拆分为:
        *   resp.setHeader("Location","/response/image");
        *   resp.setStatus(302);
        * */
    }

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

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

相同点:

  • 页面都会跳转

不同点:

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

6.6.5、测试登陆用户重定向

  • 新建一个类RedirectTest类
  • 在web.xml中进行RedirectTest类Servlet的注册
  • 在页面index.jsp中进行html代码编写
  • 新建一个页面success.jsp

新建一个RedirectTest类

public class RedirectLogin extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");

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

        //重定向,一定要注意路径问题,否则404
        resp.sendRedirect("/response/success.jsp");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

在web.xml中进行新的Servlet的注册

<servlet>
    <servlet-name>RedirectLoginservlet-name>
    <servlet-class>com.yang.servlet.RedirectLoginservlet-class>
servlet>
<servlet-mapping>
    <servlet-name>RedirectLoginservlet-name>
    <url-pattern>/loginurl-pattern>
servlet-mapping>

在index.jsp中进行编写代码


    
        

Hello World!

<%--这里提交的路径,需要寻找到项目的路径--%> <%-- ${pageContext.request.contextPath}:代表当前的项目 --%>
用户名:
密码:

导入jsp的包

<dependency>
	<groupId>javax.servlet.jspgroupId>
    <artifactId>javax.servlet.jsp-apiartifactId>
    <version>2.3.1version>
dependency>

新建一个success.jsp页面

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

    
        Title
    
    
        

Success

启动服务器进入login

6.7、HttpServletRequest

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

  • 创建一个新的Maven项目:request
  • 创建结构目录
  • 改变web.xml的代码为最新版
  • 将index.jsp删掉重新创建index.jsp
  • 创建包com.yang.servlet
  • 设置Tomcat对应的项目为request ,设置url访问路径为:/request

6.7.1、获取前端传递的参数 请求转发

获取参数方法:

  • getParameter(String s)
  • getParameterMap() 很少用
  • getParameterNames() 很少用
  • getParameterValues(String s)

包内新建一个类LoginServlet

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

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

        //解决乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        //接收处理参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobbies");

        System.out.println("======================");
        System.out.println(username);
        System.out.println(password);
        //输出数组:Arrays.toString(hobbies)
        System.out.println(Arrays.toString(hobbies));
        System.out.println("======================");

        //输出对应项目的路径
        System.out.println(req.getContextPath());

        //通过请求转发
        //这里的 / 代表当前web应用
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
    }
}

在web.xml中注册Servlet

<servlet>
    <servlet-name>LoginServletservlet-name>
    <servlet-class>com.yang.Servlet.LoginServletservlet-class>
servlet>
<servlet-mapping>
    <servlet-name>LoginServletservlet-name>
    <url-pattern>/loginurl-pattern>
servlet-mapping>

在index.jsp中编写代码

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


    index


登陆

<%-- 这里表单提交的方式:以post方式提交表单,提交到login页面--%>
用户名:
密码:
爱好:学习 旅游 听歌 打羽毛球 打网球

新建一个success.jsp页面

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

    
        登陆成功!
    
    
        

登陆成功!

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

相同点:

  • 页面都会跳转

不同点:

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

7、Cookie、Session

Cookie:饼干

Session:会话

  • 新建一个maven项目javaweb-session-cookie
  • 进行项目结构的创建
  • java包中新建包com.yang.servlet

7.1、会话

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

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

你能怎么证明你是大学学生?

你 学校

  1. 发票 学校给你发票 cookie方法
  2. 学校登记 学校标记你来过 session方法

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

客户端 服务器

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

7.2、保存会话的两种技术

cookie

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

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息?我们可以把信息数据放到session中!

常见场景:网站登录之后,你下次不用再登陆了,第二次访问直接就上去了!

7.3、Cookie

  1. 从请求中拿到cookie信息
  2. 服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得cookie
cookie.getName(); //获得cookie中的key
cookie.getValue();  //获得cookie中的value
new Cookie("lastLoginTime",System.currentTimeMills()+""); //新建一个cookie
cookie.setMaxAge(24*60*60);  //设置cookie的有效日期
resp.addCookie(cookie);  //响应给客户端一个cookie

包内新建类CookieDemo01

//保存上一次用户访问的时间
//服务器告诉你上一次你来的时间,把这个时间封装成信件,你下次来的时候带上,服务器就知道你来了
public class CookieDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


        //解决中文乱码问题
        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        PrintWriter out = resp.getWriter();

        //Cookie(服务器从客户端获取的),可能有多个
        Cookie[] cookies = req.getCookies();

        //判断Cookie是否存在
        if (cookies!=null){
            //如果存在就输出
            out.write("您上一次访问本网站的时间:");
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //判断cookie的名字是不是lastTime(获得cookie的值)
                if(cookie.getName().equals("lastTime")){
                    //获取cookie的值,转成长整形,获取时间戳
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastLoginTime);
                    //将时间转换成字符串,并输出
                    out.write(date.toLocaleString());
                }
            }
        }else{
            //如果不存在
//            URLEncoder.encode("欢迎第一次登陆本站!","utf-8");
//            out.print(URLDecoder.decode("欢迎第一次登陆本站!","utf-8"));
            out.write("欢迎第一次登陆本站!");
        }


        //服务器给客户端响应一个cookie,   System.currentTimeMillis() + ""转成字符串
        Cookie cookie = new Cookie("lastTime", System.currentTimeMillis() + "");
        //设置cookie的有效时间为1天
        cookie.setMaxAge(25*60*60);
        //服务器将cookie响应给客户端
        resp.addCookie(cookie);

    }

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

在web中进行CookieDemo01的Servlet注册与映射

<servlet>
    <servlet-name>CookieDemo01servlet-name>
    <servlet-class>com.yang.Servlet.CookieDemo01servlet-class>
servlet>
<servlet-mapping>
    <servlet-name>CookieDemo01servlet-name>
    <url-pattern>/cookie1url-pattern>
servlet-mapping>

cookie:一般保存在本地的 用户目录下 appdate;

一个网站cookie是否存在上限!聊聊细节问题

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

删除cookie:

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

删除cookie,设置时间为0,新建一个类CookieDemo02

public class CookieDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //服务器给客户端响应一个cookie,   System.currentTimeMillis() + ""转成字符串
        Cookie cookie = new Cookie("lastTime", System.currentTimeMillis() + "");
        //设置cookie的有效时间为1天
        cookie.setMaxAge(0);
        //服务器将cookie响应给客户端
        resp.addCookie(cookie);
    }

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

在web.xml中进行CookieDemo02的Servlet注册与映射

<servlet>
    <servlet-name>CookieDemo02servlet-name>
    <servlet-class>com.yang.Servlet.CookieDemo02servlet-class>
servlet>
<servlet-mapping>
    <servlet-name>CookieDemo02servlet-name>
    <url-pattern>/cookie2url-pattern>
servlet-mapping>

启动服务器,先访问cookie1创建cookie,在访问cookie2删除cookie,再访问cookie1确定cookie已经被删除

编码、解码问题

编码:URLEncoder.encode(“扬启”,“utf-8”);

解码:URLDecoder.decode(“值”,“UTF-8”);

7.4、Session(重点)

什么是Session:

  • 服务器会给每一个用户(浏览器)创建一个Session对象
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在。
  • 用户登录之后,整个网站它都可以访问! -->保存用户的信息,保存购物车的信息…

Session中的一些方法:

  • getCreationTime(); 获得创建时间
  • getId(); 获得唯一的标识符
  • getServletContext(); 获得web服务
  • getAttribute(String); 获得结点
  • setAttribute(String);
  • removeAttribute(String);
  • isNew(); 判断是不是新的
  • invalidate(); 注销

Session和Cookie的区别:

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

Session使用场景:

  • 保存一个登陆用户的信息
  • 购物车信息
  • 在整个网站中经常会使用的数据,我们将它保存在Session中

7.4.1、Session测试

新建一个SessionDemo01类来测试Session,并进行Servlet的注册与映射

SessionDemo01类

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

        //解决中文乱码问题
        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

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

        //给session中存入东西
        session.setAttribute("name","扬启");

        /*session创建的时候做了什么事情:
        *   Cookie cookie = new Cookie("key",value);
        *   resp.addCookie(cookie);
        * */

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

        //判断session是不是新创建的
        if (session.isNew()){
            resp.getWriter().write("session已经新建完成,id为:"+id);
        }else{
            resp.getWriter().write("session的id为:"+id);
        }
    }

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

web.xml

<servlet>
    <servlet-name>SessionDemo01servlet-name>
    <servlet-class>com.yang.Servlet.SessionDemo01servlet-class>
servlet>
<servlet-mapping>
    <servlet-name>SessionDemo01servlet-name>
    <url-pattern>/session1url-pattern>
servlet-mapping>

启动服务器,进行测试

7.4.2、创建一个Session,在另外一个Servlet中去取

取出一个字符串:

新建一个SessionDemo02类来取Session,并进行Servlet的注册与映射

SessionDemo02类

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

        //解决中文乱码问题
        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        //获取session
        HttpSession session = req.getSession();

        //得到另一个session的值
        String name =(String) session.getAttribute("name");

        System.out.println(name);
    }

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

web.xml

<servlet>
    <servlet-name>SessionDemo02servlet-name>
    <servlet-class>com.yang.Servlet.SessionDemo02servlet-class>
servlet>
<servlet-mapping>
    <servlet-name>SessionDemo02servlet-name>
    <url-pattern>/session2url-pattern>
servlet-mapping>

启动服务器,访问session2,输出结果为:null

启动服务器,先访问session1,再访问session2,输出结果为:扬启

取出一个对象:

  • 新建一个包pojo
  • 包内创建一个类Person

Person类

public class Person{
    private String name;
    private int age;
    
    public Person(){
    }
    
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name;
    }
    public String getAge(){
        return age;
    }
    public void setAge(int age){
        this.age = age;
    }
    
    @Override
    public String toString(){
        return "Person{"+"name'"+name+'\''+",age="+age+'}';
    }
    
}

修改SessionDemo01类

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

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

        //给session中存入东西
        session.setAttribute("name",new Person("扬启",22));

        /*session创建的时候做了什么事情:
         *   Cookie cookie = new Cookie("key",value);
         *   resp.addCookie(cookie);
         * */

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

        //判断session是不是新创建的
        if (session.isNew()){
            resp.getWriter().write("session已经新建完成,id为:"+id);
        }else{
            resp.getWriter().write("session的id为:"+id);
        }
    }

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

将SessionDemo02中的:String person = (String)session.setAttribute(“name”);

改为:Person person = (Person)session.setAttribute(“name”);

System.out.println(person.toString());

启动服务器,先访问session1,再访问session2,输出结果为:Person{name=‘扬启’,age=22}

7.4.3、注销Session【invalidate();】

新建一个类SessionDemo03

SessionDemo03类

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

        //解决中文乱码问题
        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        //获得session
        HttpSession session = req.getSession();

        //获取另一个session的值
        session.getAttribute("name");

        //移除name
        session.removeAttribute("name");

        //手动注销session
        //注销session,相当于关闭浏览器
        session.invalidate();
    }

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

web.xml

<servlet>
    <servlet-name>SessionDemo03servlet-name>
    <servlet-class>com.yang.Servlet.SessionDemo03servlet-class>
servlet>
<servlet-mapping>
    <servlet-name>SessionDemo03servlet-name>
    <url-pattern>/session3url-pattern>
servlet-mapping>

启动服务器,访问session1,再访问session3,再访问session2,结果报错:状态码500

启动服务器,访问session1,再访问session3,再访问session1,结果:sessionId发生改变

7.4.4、会话自动过期

设置Session默认的失效时间:

<servlet>...servlet>
<servlet-mapping>...servlet-mapping>


<session-config>       
	
    <session-timeout>15session-timeout>
session-config>

8、JSP

8.1、什么是JSP

JSP(Java Server Pages):Java服务器端页面,也是和Servlet一样,用于动态Web技术!

最大的特点:

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

8.2、JSP原理

思路:JSP到底怎么执行!

  • 代码层面没有任何问题

  • 服务器内部工作

    • tomcat中有一个work目录(服务器工作的目录)

    • Idea中使用Tomcat,会在Idea的tomcat中生成一个work目录

      完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第48张图片

      我的电脑地址:

      C:\Users\suma\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_javaweb-02-Servlet_2\work\Catalina\localhost\response\org\apache\jsp
      

      发现页面转变成了Java程序:

    完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第49张图片

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

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

JSP本质上就是一个Servlet!

//初始化
public void _jspInit(){
    
}

//销毁
public void _jspDestroy(){
    
}

//JSPService  请求服务
public void _jspService(HttpServletRequest request,HttpServletResponse response){
    
}
  1. 判断请求

  2. 内置一些对象

    final javax.servlet.jsp.PageContext pageContext; //页面上下文
    javax.Servlet.HttpSession session = null;		 //session
    final javax.servlet.ServletContext application;	 //applicationContext
    final javax.servlet.ServletConfig config;		 //config 配置
    final javax.jsp.JspWriter out = null;			 //out
    final java.lang.Object page = this;				 //page:当前页
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;
    HttpServletRequest request						 //请求
    HttpServletResponse response					 //响应
    
  3. 输出页面前增加的代码

    response.setContentType("text/html");			//设置响应的页面类型
    pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);
    _jspx_page_context = pageContext;
    application = pageContext.getServletContext();
    config = pageContext.getServletConfig();
    session = pageContext.getSession();
    out = pageContext.getOut();
    _jspx_out = out;
    
  4. 以上的这些对象我们可以直接在JSP页面中直接使用!

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第50张图片

example:

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

    
        登陆成功!
    
    
        
        <%
        	String name = "yangqi";
        %>
        
        name:<%=name%>
        
    

在JSP页面中:

只要是Java代码,就会原封不动的输出,如果是HTML代码,就会被转换成类似于:

out.write("name");

这样的格式,输出到前端。

8.3、JSP基础语法

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

  • 新建一个普通的Maven项目javaweb-jsp

  • 鼠标在项目,右键,选择Add Framework Suupport… 再选择Web Application --> 将普通的项目变成web项目

  • 导包

    <dependencies>
        
    	<dependency>
        	<groupId>javax.servletgroupId>
            <artifactId>servlet-apiartifactId>
            <version>2.5version>
        dependency>
        
    	<dependency>
        	<groupId>javax.servlet.jspgroupId>
            <artifactId>javax.servlet.jsp-apiartifactId>
            <version>2.3.3version>
        dependency>
        
    	<dependency>
        	<groupId>javax.servlet.jsp.jstlgroupId>
            <artifactId>jstl-apiartifactId>
            <version>1.2version>
        dependency>
        
    	<dependency>
        	<groupId>taglibsgroupId>
            <artifactId>standardartifactId>
            <version>1.1.2version>
        dependency>
    dependencies>
    
  • 配置tomcat

JSP表达式

<%--JSP表达式
    作用:用来将程序的输出,输出到客户端
    <%= 变量或者表达式%>
--%>
	<%= new java.util.Date()%>

jsp脚本片段

<%--jsp脚本片段--%>
<%
	int sum =0;
	for(int i=1;i<=100;i++){
        sum+=i;
    }
	out.println("

Sum="+sum+"

"); %>

脚本片段的再实现

<%
	int x =10;
	out.println(x);
%>

这是一个JSP文档

<% <%--int x =10;错误,变量名相同,不能重复定义--%> int y =10; out.println(y); %>
<%--在代码中嵌入HTML元素--%> <% for(int i=0;i<5;i++){ %>

Hello World!<%= i%>

<% } %>

JSP声明(全局):加一个==!==表示代码写进_jspService方法外面(会被编译到该**.jsp文件生成的java的类**中!)

<%--加一个!表示代码写进_jspService方法外面(会被编译到该.jsp文件生成的java的类中!)-%>
<%!
    static{
	    System.out.println("Loading Servlet!");
	}

	private int globalVar = 0;

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

EL表达式

${new java.util.Date()}

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

8.4、JSP指令

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

<%@ include file=""%>

1、<%@ page …%>

  1. 进入指定的错误页通过设置<%@ page %>
  • web目录下新建一个jsp–>index2.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    <%--定制错误页面--%>
    <%@ page errorPage="error/500.jsp" %>
    
    
        
            登陆成功!
        
        
            
            <%
            	int x = 1/0;
            %>
            
        
    
    
  • 在web目录下新建文件夹error 和img

  • error文件夹下新建500.jsp和404.jsp

    500.jsp

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

404.jsp

  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  
  
      404错误
  
  
  
  404
  
  
  
  • img文件夹下方一张500.png图片和一张404.png图片
  1. 进入指定错误页面通过配置web.xml

    
    <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">
    
        <error-page>
        	<error-code>404error-code>
            <location>/error/404.jsplocation>
        error-page>
        <error-page>
        	<error-code>500error-code>
            <location>/error/500.jsplocation>
        error-page>
    
    web-app>
    

2、<%@ include file=""%>

include(包含):可以用来提取公共页

  • 新建一个文件夹common

  • common中新建header.jsp文件和footer.jsp文件

    • header.jsp

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

      我是Header!

    • footer.jsp

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

      我是footer!

  • web文件夹中新建index3.jsp

    • <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      
      
          
              Title
          
          
              
              <%--@include会将两个页面合二为一--%>
              <%@ include file="common/header.jsp"%>
              

      我是网页主体!

      <%@ include file="common/footer.jsp"%> <%--jsp标签 jsp:include:拼接页面,本质还是三个 --%>

      我是网页主体!

web文件夹下的WEB-INF文件夹对用户不可见,客户端无法直接访问!通常放置一些重要的文件!

8.5、9大内置对象

九大内置对象包括:

  • PageContext(页面的上下文) 存东西
  • Request(请求) 存东西
  • Response(响应)
  • Session 存东西
  • Application 【ServletContext】 存东西
  • config【ServletConfig】
  • out
  • page 几乎不用
  • exception

web文件夹下新建一个pageContextDemo01.jsp

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


    内置对象



    <%--内置对象--%>
    <%
        //存数据
        pageContext.setAttribute("name1","扬启1");//保存的数据只在一个页面有效
        request.setAttribute("name2","扬启2");//保存的数据只在一个请求中有效,请求转发会携带该数据
        session.setAttribute("name3","扬启3");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
        application.setAttribute("name4","扬启4");//保存的数据服务器中有效,从打开服务器到关闭服务器
    %>
    <%--
        脚本片段中的代码,会被原封不动生成到.jsp.java中
        要求:这里面的代码,必须保证java语法的正确性
    --%>

    <%
        //从pageContext中取出数据,我们通过寻找的方式
        //从底层到高层(作用域):page-->request-->session-->application
        //JVM:双亲委派机制
        String name1 =(String) pageContext.findAttribute("name1");
        String name2 =(String) pageContext.findAttribute("name2");
        String name3 =(String) pageContext.findAttribute("name3");
        String name4 =(String) pageContext.findAttribute("name4");
        String name5 =(String) pageContext.findAttribute("name5"); //不存在为空
    %>

<%--使用EL表达式输出:${}等价于<%= %>--%>
    

取出的值为:


${name1} <%=name1%>

${name2}

${name3}

${name4}

<%=name5%>

<%--用EL表达式不存在的值自动过滤掉,使用<%=%>不会--%>

web文件夹下新建一个PageDemo02.jsp (name1、name2作用域太低,运行结果只能取出name3、name4、name5)

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

    
        内置对象
    
    
        
        <%--
    脚本片段中的代码,会被原封不动生成到.jsp.java中
    要求:这里面的代码,必须保证java语法的正确性
--%>

<%
    //从pageContext中取出数据,我们通过寻找的方式
    //从底层到高层(作用域):page-->request-->session-->application
    //JVM:双亲委派机制
    String name1 =(String) pageContext.findAttribute("name1");
    String name2 =(String) pageContext.findAttribute("name2");
    String name3 =(String) pageContext.findAttribute("name3");
    String name4 =(String) pageContext.findAttribute("name4");
    String name5 =(String) pageContext.findAttribute("name5"); //不存在为空
%>

<%--使用EL表达式输出:${}等价于<%= %>--%>

取出的值为:


${name1}

${name2}

${name3}

${name4}

<%=name5%>

<%--用EL表达式不存在的值自动过滤掉,使用<%=%>不会--%>

web文件夹下新建一个pageDemo03.jsp

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

    
        内置对象
    
    
        
        <%--
    		public static final int PAGE_SCOPE = 1;
        	public static final int REQUEST_SCOPE = 2;
        	public static final int SESSION_SCOPE = 3;
        	public static final int APPLICATION_SCOPE = 4;
    		//scope:作用域
    		public void setAttribute(String name,Object attribute, int scope){
    			switch(scope){
                    case 1:
                        this.mPage.put(name,attribute);
                        break;
                    case 2:
                        this.mRequest.put(name,attribute);
                        break;
                    case 3:
                        this.mSession.put(name,attribute);
                        break;
                    case 4:
                        this.mApp.put(name,attribute);
                        break;
                    default:
                        throw new IllegalArgumentException("Bad scope "+scope);
                }
			}
        --%>
        
        <%
        	pageContext.setAttribute("hello1","hello1",pageContext.SESSION_SCOPE);
        	//等价于session.setAttribute("hello1","hello1");
        %>
    

转发:

web文件夹下新建一个pageContextDemo02.jsp

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

    
        转发
    
    
        
        <%
        	pageContext.forward("/index.jsp");
        	request.getRequestDispatcher("index.jsp").forward(request,response);
        	//上面两个代码结果相同:转发
        	//在jsp中通常用pageContext.forward("index.jsp");
        %>
    

//存数据
pageContext.setAttribute("name1","扬启1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","扬启2号"); //保存的数据只在一个请求中有效,请求转发会携带这个数据
session.setAttribute("name3","扬启3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","扬启4号"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器

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

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

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

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

 
 <dependency>
 	<groupId>javax.servlet.jsp.jstlgroupId>
     <artifactId>jstl-apiartifactId>
     <version>1.2version>
 dependency>
 
 <dependency>
 	<groupId>taglibsgroupId>
     <artifactId>standardartifactId>
     <version>1.1.2version>
 dependency>

EL表达式: ${}

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象
  • 调用Java方法(一般不用)

JSP标签

web文件夹下新建jsp, jsptag.jsp和jsptag2.jsp

jsptag.jsp

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

    
        标签
    
    
        

1

<%--jsp:include--%> <%--转发的时候可以携带参数--%> <%-- http://localhost:8080/jsptag.jsp?name=yangqi&age=22--%>

jsptag2.jsp

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

    
        转发页面
    
    
        

2

<%--取出参数--%> 名字:<%=request.getParameter("name")%> 年龄:<%=request.getParameter("age")%>

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

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

JSTL标签:

  • 格式化标签

  • SQL标签

  • XML标签

  • 核心标签(掌握部分)

    • 必须引入JSTL核心标签库,我们才能使用JSTL标签 c代表core。

    • <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%--导入就能使用标签--%>
      
      标签 描述
      用于在JSP中显示数据,就像<%=…>
      用于保存数据
      用于删除数据
      与我们在一般程序中用的if一样
      本身只能当做的父标签
      的子标签,本身用来判断条件是否成立
      的子标签,接在之后,当判断为false时执行
      基础迭代标签,接受各种集合类型
      使用可选的查询参数来创造一个URL

JSTL标签库使用步骤:

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

标签的使用

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入jstl核心标签库,我们才能使用jstl核心标签库:core--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    核心标签



    

if测试

<%--EL表达式获取表单中的数据 ${param.参数名} --%>

<%--判断:如果用户名是管理员就登陆成功--%> <%--<%--%> <%-- if(request.getParameter("username").equals("admin")){--%> <%-- out.write("登陆成功!");--%> <%-- }--%> <%--%>--%> <%--test一定要带:表示条件--%>

标签的使用

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


    corewhen标签




<%--定义一个变量是score,值为85--%> 你的成绩为优秀! 你的成绩为良! 你的成绩为差! 查询错误!

标签的使用

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


    foreach标签



<%
    ArrayList people = new ArrayList<>();
    people.add(0,"张三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"赵六");
    people.add(4,"田七");
    request.setAttribute("list",people);
%>
<%--var:每一次遍历的变量
    items:要遍历的对象
--%>

    

<%--begin:从哪开始 end:从哪结束 step:步长 --%>

9、JavaBean

Bean:豆子

JavaBean:可以叫做实体类

JavaBean有特定的写法:

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

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

ORM:对象关系映射

  • 表–>类
  • 字段–>属性
  • 行–>对象
id name age address
1 扬启1 21 河南
2 扬启2 22 湖北
3 扬启3 23 武汉

表对应的字段

class Person{
    private int id;
    private String name;
    private int age;
    private String address;
}

idea连接数据库报错:Server returns invalid timezone. Need to set ‘serverTimezone’ property.

点击Set time zone[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5TkdM9P-1636973029636)(5、JavaWeb.assets/image-20211111161209640.png)]

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第51张图片

PS:
GMT(Greenwich Mean Time):格林威治标准时间
UTC:世界标准时间
CST(China Standard Time):中国标准时间

10、MVC三层架构

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

10.1、早些年的开发:

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第52张图片

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

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护     servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码。
    
架构:没有什么是加一层解决不了的。
程序员--->JDBC--->Mysql Oracle SqlServer...

10.2、MVC三层架构

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第53张图片
Model:

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

View:

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

Controller(Servlet):

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

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

  • 控制视图跳转

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

11、Filter(重点)

Shiro安全框架

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

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

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第54张图片

Filter开发步骤:

新建一个普通的maven项目javaweb-filter,add Framework Support一个web资源目录

配置Tomcat

新建包filter,filter内新建CharacterEncodingFilter的class文件

新建包servlet,servlet内新建ShowServlet的class文件

  1. 导包

  2. 编写过滤器

    1. 导包不要错

    在这里插入图片描述

    1. 编写过滤器,实现Filter接口,重写对应的方法即可
    public class CharacterEncodingFilter implements Filter {
        //初始化:web服务器启动就已经初始化了,随时等待监听,等待过滤对象出现!
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("CharacterEncodingFilter初始化!");
        }
    
        //Chain:链
        /*
        * 1.过滤中的所有代码,在过滤特定请求的时候都会执行
        * 2.必须要让过滤器继续通行
        *   chain.doFilter(request,response);*/
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            servletRequest.setCharacterEncoding("utf-8");
            servletResponse.setCharacterEncoding("utf-8");
            servletResponse.setContentType("text/html;charset=UTF-8");
    
            System.out.println("CharacterEncodingFilter执行前...");
            filterChain.doFilter(servletRequest,servletResponse); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
            System.out.println("CharacterEncodingFilter执行后...");
        }
        
        //销毁
        public void destroy() {
            System.out.println("CharacterEncodingFilter销毁!");
        }
    }
    
    1. 实现Servlet,编写对应的功能
    public class ShowServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        resp.setContentType("text/html");
    //        resp.setCharacterEncoding("utf-8");
    
            resp.getWriter().write("你好啊,世界!");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    1. web.xml文件的编写
    <servlet>
        <servlet-name>ShowServletservlet-name>
        <servlet-class>com.yang.servlet.ShowServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>ShowServletservlet-name>
        <url-pattern>/servlet/showurl-pattern>
    servlet-mapping>
    
    <servlet-mapping>
        <servlet-name>ShowServletservlet-name>
        <url-pattern>/showurl-pattern>
    servlet-mapping>
    
    <filter>
        <filter-name>CharacterEncodingFilterfilter-name>
        <filter-class>com.yang.filter.CharacterEncodingFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilterfilter-name>
        
        <url-pattern>/servlet/*url-pattern>
    filter-mapping>
    

12、监听器

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

新建包listener,listener下新建类OnlineCountListener

  1. 编写监听器

    实现监听器的接口

    //统计网站在线人数:统计session
    //listener监听:看你的一举一动
    public class OnlineCountListener implements HttpSessionListener {
    
        //创建session监听
        //一旦创建session就会触发一次这个事件
        public void sessionCreated(HttpSessionEvent se) {
            ServletContext servletContext = se.getSession().getServletContext();
    
            System.out.println(se.getSession().getId());
    
            Integer onlineCount =(Integer) servletContext.getAttribute("OnlineCount");
    
            if (onlineCount==null){
                //onlineCount为空变为1
                onlineCount = new Integer(1);
            }else {
                //将onlineCount转成int
                int count = onlineCount.intValue();
                //onlineCount原数值在加1
                onlineCount = new Integer(count+1);
            }
            servletContext.setAttribute("OnlineCount",onlineCount);
        }
    
        //销毁session监听
        //一旦销毁session就会触发一次这个事件
        public void sessionDestroyed(HttpSessionEvent se) {
            ServletContext servletContext = se.getSession().getServletContext();
            Integer onlineCount =(Integer) servletContext.getAttribute("OnlineCount");
    
            if (onlineCount==null){
                //onlineCount为空变为0
                onlineCount = new Integer(0);
            }else {
                //将onlineCount转成int
                int count = onlineCount.intValue();
                //onlineCount原数值再减1
                onlineCount = new Integer(count-1);
            }
            servletContext.setAttribute("OnlineCount",onlineCount);
        }
    
        /*session销毁:
        * 1.手动销毁 getSession().invalidate();
        * 2.自动销毁 在web中配置session自动销毁时间
        *          
                        1
                   
        * */
    }
    
  2. 在web.xml中注册监听器

    
        <listener>
            <listener-class>com.yang.listener.OnlineCountListenerlistener-class>
        listener>
    
  3. 看情况是否使用

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

包listener内新建类TestPanel

13.1、监听器在GUI(图形用户界面)编程中的运用

public class TestPanel{
    public static void main(String[] args) {
        final Frame frame = new Frame("Java监听器"); //新建一个窗体
        Panel panel = new Panel(null); //新建一个面板,布局方式为空

        //设置窗体布局方式
        frame.setLayout(null);
        //设置窗体位置与大小
        frame.setBounds(300,300,500,500);
        //设置窗体背景颜色
        frame.setBackground(new Color(0,0,255));

        //设置面板的位置与大小
        panel.setBounds(50,50,300,300);
        //设置面板背景色
        panel.setBackground(new Color(0,255,0));
        
        //将面板放到窗体中
        frame.add(panel);
        //设置窗体可见性
        frame.setVisible(true);
        //监听事件:关闭事件
        frame.addWindowListener(new WindowAdapter() {
            //适配器模式
            //关闭窗口
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}

监听器在GUI编程中经常运用

用户登陆之后才能进入主页!用户注销就不能进入主页了!

13.2、过滤器的常见应用

13.2.1、不含过滤器的登陆功能

  • 在web目录中新建一个sys目录,sys目录中新建jsp–>success.jsp
  • web目录下新建jsp–>Login.jsp、error.jsp
  • 在包servlet下新建类LoginServlet和类LogoutServlet
  • 新建一个包utils,包内新建类Constant

Login.jsp登陆页面的编写

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


    登陆用户



    

用户登陆



Constant提取常数类的编写

public class Constant {
    //将SESSION提取出来,提取成常量
    public final static String USER_SESSION="USER_SESSION";
}

LoginServlet功能的编写

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取前端请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        if(username.equals("admin")){ //登陆成功
            //在session中存一个常数
            req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
            //重定向
            resp.sendRedirect("/sys/success.jsp");
        }else{ //登陆失败
            resp.sendRedirect("/error.jsp");
        }
    }

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

success.jsp页面的编写

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


    主页



<%
    Object userSession = request.getSession().getAttribute("USER_SESSION");
    if (userSession==null){
        response.sendRedirect("/Login.jsp");
    }
%>

主页

注销

LogoutServlet注销功能的编写

public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object user_session = req.getSession().getAttribute("USER_SESSION");

        if (user_session!=null){
            //如果存在session,就移除session
            req.getSession().removeAttribute("USER_SESSION");
            resp.sendRedirect("/Login.jsp");
        }else {
            resp.sendRedirect("/Login.jsp");
        }
    }

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

error.jsp错误页面的编写

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


    错误



错误!

用户名或密码错误!

返回登录页面

web.xml注册

<servlet>
    <servlet-name>LoginServletservlet-name>
    <servlet-class>com.yang.servlet.LoginServletservlet-class>
servlet>
<servlet-mapping>
    <servlet-name>LoginServletservlet-name>
    <url-pattern>/servlet/loginurl-pattern>
servlet-mapping>

<servlet>
    <servlet-name>LogoutServletservlet-name>
    <servlet-class>com.yang.servlet.LogoutServletservlet-class>
servlet>
<servlet-mapping>
    <servlet-name>LogoutServletservlet-name>
    <url-pattern>/servlet/logouturl-pattern>
servlet-mapping>

13.2.2、含有过滤器的登录功能

  • 包filter内新建一个类SysFilter
  1. 用户登录之后,向session中放入用户的数据

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

    public class SysFilter implements Filter {
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
            //ServletRequest 不同于  HttpServletRequest
    
            //强制转换
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
    
            //获取session的值
            Object user_session = request.getSession().getAttribute(Constant.USER_SESSION);
    
            if (user_session==null){
                response.sendRedirect("/error.jsp");
            }
    
            //链子:继续往下走
            chain.doFilter(request,response);
        }
        public void destroy() {
        }
    }
    

14、JDBC

什么是JDBC(Java DataBase Connection):Java连接数据库!

需要jar包:

  • java.sql
  • javax.sql
  • mysql-connector-java…连接驱动(必须要导入)

实现环境搭建:

  • 创建数据库jdbc,数据库内新建表users
CREATE TABLE users (
	id INT PRIMARY KEY,
	`name` VARCHAR(50),
	`password` VARCHAR(30),
	email VARCHAR(50),
	birthday DATE
);

INSERT INTO users(id,`name`,`password`,email,birthday)
VALUE(1,'张三','123456','[email protected]','2020-01-01')
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUE(2,'李四','123123','[email protected]','2020-01-02')
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUE(3,'王五','123321','[email protected]','2020-01-03')

SELECT * from users;
  • 导入数据库依赖

    <dependencies>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.46version>
        dependency>
    dependencies>
    
  • idea连接数据库

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第55张图片

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第56张图片

完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习_第57张图片

  • 新建包com.yang.Test,包内新建类TestJdbc

    public class TestJdbc {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            //配置信息
            //useUnicode=true&characterEncoding=utf-8:解决中文乱码
            //useSSL=true:安全连接
            String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=true";
            String username = "root";
            String password = "123456";
    
            //1.加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.连接数据库,代表数据库         DriverManager:驱动管理
            Connection connection = DriverManager.getConnection(url, username, password);
            //3.向数据库发送sql对象:statement,用它来进行CRUD(增、删、改、查)
            //connection.prepareStatement(sql);预编译:放在后面
            Statement statement = connection.createStatement();
            //4.编写sql
            String sql = "select * from users;";
            //5.执行查询sql,返回一个resultset
            ResultSet resultSet = statement.executeQuery(sql);
    
            while (resultSet.next()){
                System.out.println("id="+resultSet.getObject("id"));
                System.out.println("name="+resultSet.getObject("name"));
                System.out.println("password="+resultSet.getObject("password"));
                System.out.println("email="+resultSet.getObject("email"));
                System.out.println("birthday="+resultSet.getObject("birthday"));
                System.out.println("==================================");
            }
    
            //6.关闭连接,释放资源,按照建立的后先顺序(一定要做,先开后关)
            resultSet.close();
            statement.close();
            connection.close();
        }
    }
    

预编译PreparedStatement:

public class TestJdbc2 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8:解决中文乱码
        //useSSL=true:安全连接
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=true";
        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) values(?,?,?,?,?)";
        String sql = "update users set name=? where id = 4";
        //4.预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        /*preparedStatement.setInt(1,4);//给第一个占位符? 的值赋值为1
        preparedStatement.setString(2,"moxi");
        preparedStatement.setString(3,"123456");
        preparedStatement.setString(4,"[email protected]");
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
*/
        preparedStatement.setString(1,"沫汐");
        //5.执行sql
        preparedStatement.executeUpdate();

        //6.关闭连接,释放资源
        preparedStatement.close();
        connection.close();
    }
}

JDBC固定步骤:

  1. 加载驱动
  2. 连接数据库
  3. 向数据库发送SQL的对象statement:执行CRUD
  4. 编写sql(根据业务,不同的sql)
  5. 执行sql
  6. 关闭连接

事务

事务:

要么都成功,要么都不成功!

ACID原则:保证数据的安全。

开启事务
事务提交	commit();
事务回滚	rollback();
关闭事务
    
 
    转账:
    A:1000
    B:1000
        
    A(900) --100-->  B(1100)

Junit单元测试:

依赖:


<dependency>
    <groupId>junitgroupId>
    <artifactId>junitartifactId>
    <version>4.12version>
dependency>

简单使用:@Test注解只有在方法上有效,加了这个注解的方法就可以单独执行

public class TestJdbc3 {
    @Test
    public void test(){
        System.out.println("Hello");
    }
}

成功:输出结果 失败:报错

数据库新建一个表,account,表内添加数据:

CREATE TABLE account(
	id INT PRIMARY KEY,
	`name` VARCHAR(30),
	money FLOAT
);

INSERT INTO account(id,`name`,money) VALUES(1,'A',1000),(2,'B',1000),(3,'C',1000)

数据库添加事务代码:

start transaction ; #开启事务

update account set money = money-100 where name = 'A';
update account set money = money+100 where name = 'B';

rollback ;

commit ;

包Test内新建一个类TestJdbc3

public class TestJdbc3 {

    @Test
    public void test() {
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=true";
        String username = "root";
        String password = "123456";
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            //1.加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.连接数据库,代表数据库
            connection = DriverManager.getConnection(url, username, password);
            //3.通知数据库开启事务   false开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money-100 where name = 'A'";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.executeUpdate();

            //制造错误
            //int i = 1/0;
            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();

            connection.commit(); //以上两条sql都执行成功了就提交事务
            
        } catch (Exception e) {
            //如果出现异常,就通知数据库回滚事务
            try {
                connection.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }finally {
            try {
                preparedStatement.close();
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

你可能感兴趣的:(服务器,session,cookie)