一、基本概念
1.1、前言
web 开发:
-
web,网页的意思,如www.baidu.com
-
静态web
- html,css
- 提供给所有人看的数据始终不会发生变化
-
动态web
- 淘宝,几乎所有的网站
- 提供给所有人的看的数据会发生变化,每个人在不太时间不同地点看的东西是不同的
- 技术栈:Servlet/JSP,ASP,PHP
javaweb:用java开发web
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:
- *.html这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接读取,需要网络
-
静态web存在的缺点:
- Web页面无法动态更新,所有用户看到都是同一个页面
- 轮播图,点击特效:伪动态
- JavaScript [实际开发中,它用的最多]
- VBScript(Microsoft开发的)
- Web页面无法动态更新,所有用户看到都是同一个页面
-
- 它无法和数据库交互(数据无法持久化,用户无法交互)
1.4、动态web
- 页面会动态展示,“web的页面展示的效果因人而异”;
-
缺点:
- 加入服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布即停机维护;
-
优点:
- Web页面可以动态更新,所有用户看到都不是同一个页面
- 它可以与数据库交互(数据持久化:注册,商品信息,用户信息…)
二 、web服务器
2.1、技术讲解
-
ASP:
- 微软:国内最早流行的就是ASP
- 在HTML中嵌入了VB的脚本
- 在ASP开发中,基本一个页面都有几千行的业务代码,页面极其紊乱
- 维护成本高!
-
php:
- PHP开发速度很快,功能很强大,跨平台,代码很简单
- 无法承载大访问量的情况(局限性)
-
JSP / Servlet:
- B/S:浏览和服务器
- C/S:客户端和服务器
- sun公司主推B/S架构
- 基于java语言
- 可以承受三高带来的影响(高并发,高性能,高可用)
- 语法像ASP,便于ASP->JSP
2.2、web服务器
-
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息;
-
IIS
- 微软的(windos自带)
-
Tomcat
- Tomcat是Apache 软件基金会(Apache Software Foundation) 的 jakarta 项目中的一个核心项目,最新的 Servlet 和 JSP 规范总是能在 Tomcat 中得到体现,因为 Tomcat 技术先进、性能稳定,而且免费,因而深受Java爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
- Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。对于一个Java初学web的人来说,它是最佳的选择
- Tomcat 实际上运行JSP页面和Servlet。
三、Tomcat
3.1、Tomcat安装
略。
3.2、Tomcat启动和配置
- 文件夹作用:
3.2、配置
-
可以配置启动的端口号
-
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.ytf.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
但是还要去本机的C:\Windows\System32\drivers\etc目录下去修改hosts配置文件,加上图中的一行代码
-
然后重启tomcat就可以了
在浏览器中输入 http://www.ytf.com:8080/就可以了
3.3 面试题:
-
问:谈谈网站是如何进行访问的
-
答:
-
1.输入一个域名;回车
-
2.检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射
- 1.有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问127.0.0.1 www.ytf.com
- 2.没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;
3.4、发布一个网站
--webapps :Tomcat服务器的web目录 -ROOT -kuangstudy :网站的目录名 - WEB-INF -classes : java程序 -lib:web应用所依赖的jar包 -web.xml :网站配置文件 - index.html 默认的首页 - static -css -style.css -js -img -.....
-
四、HTTP
4.1、概念
http (超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。
-
文本:html,字符串,…
-
超文本:超文本(Hypertext)是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本
-
端口:80
-
https:安全
4.2、两个时代
- http 1.0
- HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接,需要重新发起请求
- http 2.0
- HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源
4.3、Http请求
- 客户端-发请求(Request)-服务器
Request URL: https://www.baidu.com/?tn=40020637_14_oem_dg 请求地址
Request Method: GET get方法/post方法
Status Code: 200 OK 状态码:200
Remote Address: 14.215.177.38:443 远程地址
4.3.1、请求行
- 请求方式:Get,Post,HEAD,DELETE,PUT,TRACT…
- get:请求能够携带的参数比较少,大小有限制(取决于浏览器地址栏的长度),会在浏览器的URL地址栏显示数据内容,不安全,但高效。
- post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,高效。
4.3.2 消息头
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language: zh-CN,zh;q=0.9 告诉浏览器,它的语言环境
Cache-Control: max-age=0 缓存控制
Connection: keep-alive 告诉服务器,请求完成是断开还是保持连接
HOST:主机
4.4、Http响应
-
服务器—响应—客户端
Cache-Control: private 缓存控制 Connection: keep-alive 连接 Content-Encoding: gzip 编码 Content-Type: text/html;charset=utf-8 类型
4.4.1、响应体
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language: zh-CN,zh;q=0.9 告诉浏览器,它的语言环境
Cache-Control: max-age=0 缓存控制
Connection: keep-alive 告诉浏览器,请求完成是断开还是保持连接
HOST:主机
Refresh:告诉客户端,多久刷新一次
Location:让网页重新定位
4.4.2响应状态码
- 200 :请求响应成功
- 3xx:请求重定向
- 4xx:找不到资源 404
- 5xx:服务器代码错误500
- 502:网关错误
常见面试题:
当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?
五、Maven
我为什么要学习这个技术
- 在Javaweb开发中,需要使用大量的jar包,我们手动去导入;
- 需要一个东西自动帮我导入和配置这个jar包。
- 故。Maven由此而生
5.1、Maven项目架构管理工具
目前用来就是方便导入jar包的!
核心思想:约定大于配置!
-
有约束,不要去违反
Maven会规定好你该如何去编写我们Java代码,必须要按照这个规范来;
5.1.1、Maven的配置
- 下载Maven
- 创建Maven本地仓库文件夹
- 打开conf文件夹下的settings.xml
//配置本地仓库
<localRepository>D:\apache-maven-3.8.1\maven-repo</localRepository>
//配置阿里云镜像
<mirror>
<id>alimaven</id>
<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
- 在电脑上配置下环境变量
- Path中
- 至此Maven配置完毕
5.2 IDEA中使用Maven
- 创建一个MavenWeb项目
5.3 创建一个普通的Maven项目
- 直接next即可
5.3.1、在Mavenweb项目中添加 java文件夹和resources文件夹(绿色的java文件夹目前用不到)
- 新版idea在scr下创建文件夹会有提示 不用手动标记文件夹了
5.4 配置Tomcat
- 解决警告问题
为什么会有这个问题:我们访问一个网站,需要指定一个文件夹名字
5.5 pom文件
- pom.xml是Maven的核心文件
<?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>
<!--这里就是我们刚才配置的GAV-->
<groupId>com.kuang</groupId>
<artifactId>javaweb-01-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!--Package:项目的打包方式
jar:java应用
war:JavaWeb应用
-->
<packaging>war</packaging>
<name>javaweb-01-maven Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<!--配置-->
<properties>
<!--项目的默认构建编码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--编码版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!--项目依赖-->
<dependencies>
<!--具体依赖的jar包配置文件-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--项目构建用的东西(可以删除)-->
<build>
<finalName>javaweb-01-maven</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
-
将目前用不到的功能删除还剩下面代码
如果要复制到别的项目中注意代码中项目组和项目名字的修改
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.yuan</groupId> <artifactId>javaweb-01-maven</artifactId> <version>1.0-SNAPSHOT</version> <!-- 打包方式 --> <packaging>war</packaging> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> </dependencies> </project>
-
maven由于他的约定大于配置,我们之后可能遇到:我们写的配置文件,无法被导出或者生效的问题,解决方案如下:
<!--在build中配置resources,来防止我们资源导出失败的问题(pom.xml中)--> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
5.6 更新web.xml
-
Tomcat给出的默认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" > </web-app>
-
< web-app>标签的metadata-complete属性
metadata-complete属性表示部署时当前的配置是否完全,值为true,表示完全,只会应用web.xml的配置,而不会去扫描类似@WebServlet,@WebFilter,@WebListener等注解和web-frame.xml配置。默认值是metadata-complete=false,即不完全,会对项目中类进行扫描,是否有相关的注解配置,同时也会加载web-frame.xml等插件配置。
-
结论:本意是元数据书否完全(web.xml中),如果需要注解方式定义组件时,显然必须设置为false,也就是默认值
5.7 小结
创建MavenWeb项目流程
-
创建时候选择Maven-Web模板
-
将main文件夹添加完整
-
更新web.xml
-
在pom.xml添加所需依赖。(删除一些用不上的插件)
-
配置Tomcat
六、Servlet
6.1 什么是Servlet?
- Servlet本质是Java类实现Servlet接口。Servlet由服务器(Tomcat)调用,运行在服务器端。
6.2 为什么要用到Servlet?、
- 我们编写java程序想要在网上实现 聊天、发帖、这样一些的交互功能,普通的java技术是非常难完成的。sun公司就提供了Servlet这种技术供我们使用。
6.3 编写一个Servlet程序
- 创建一个类实现Servlet接口
-
有5个方法要实现
- init(初始化)
- getServletConfig(Servlet配置)
- service(服务)
- getServletInfo(Servlet信息)
- destroy(销毁)
-
编写Servlet映射(在web.xml中)
为什么需要映射:我们写的是 Java 程序,但是要通过浏览器访问,而浏览器需要连接 Web 服务器,所以我们需要再 Web 服务中注册我们写的 Servlet,还需给他一个浏览器能够访问的路径;
<servlet>
<servlet-name>HelloServlet</servlet-name> 名字随便取 但要和servlet-mapping 名字保持一致
<servlet-class>com.yuan.Servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/c2</url-pattern>
</servlet-mapping>
6.4 Servlet生命周期
- 加载Servlet。当Tomcat第一次访问Servlet时,Tomcat会负责创建Servlet实例。
- 初始化。当Servlet被实例化后,Tomcat会调用init()方法初始化这个对象。
- 处理服务。当浏览器访问Servlet的时候,Servlet实例会调用service()这个方法处理请求。
- 销毁。当Tomcat关闭时,Servlet会调用destroy()这个方法,一个Servlet如果长时间不使用,也会被Tomcat自动销毁。
- 卸载。当Servlet调用完destroy()这个方法后,等待垃圾回收。如果有需要再次使用这个Servlet,会重新调用init方法进行初始化操作。
简单总结:
- 只要访问Servlet,service()就会被调用。
- init()方法只要第一次访问Servlet的时候才会被调用。
- destroy()方法只有在Tomcat关闭时候才会被调用。
6.5 继承HttpServlet编写Servlet程序
-
在上面我们实现Servlet接口,要实现5个方法这样太麻烦了
-
而HttpServlet类已经实现了Servlet的所有方法,编写Servlet只需继承HttpServlet,重写你需要的方法即可,并且它在原有的Servlet接口上添加了一些HTTP协议处理办法,它比Servlet接口的功能更加强大。
-
类图
-
一般开发中我们重写doGet和doPost方法
-
由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_get_not_supported"); if (protocol.endsWith("1.1")) { resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); } else { resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); } } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_post_not_supported"); if (protocol.endsWith("1.1")) { resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); } else { resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); } }
- 演示在doPost调用doGet方法
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); PrintWriter out = resp.getWriter(); out.println("<h1>Hello 你好World!</h1>"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
6.5.1 Servlet原理
- 浏览器向web容器发送请求,web容器生成两个对象 Request和Response
- web容器将请求封装到Request中
- service处理请求后将信息封装到Response,web容器读取Response信息返回给浏览器
6.6 Maven父子项目
- 父子模板优点:字模板可以使用父模板的依赖
6.6.1 Maven父子项目的使用
-
建立一个空的Maven项目作为父项目
-
删除父项目里面的src目录
-
更新父项目Web.xml
-
在父项目用Maven添加相关依赖
-
父项目创建完毕
-
用MavenWeb模板创建字项目(子项目)
-
观察父项目pom.xml会有
<modules> <module>servlet01</module> </modules>
-
手动在子项目pom.xml中添加以下代码(如要复制注意更换groupId和artifactId)
<parent> <groupId>org.example</groupId> <artifactId>javaweb-02-servlet</artifactId> <version>1.0-SNAPSHOT</version> </parent>
- 更新子项目Web.xml
- 将子项目文件夹补充完成(在子项目src下添加java和resource文件夹(并标记))
- 配置Tomcat
- 一个父子项目创建完毕(父项目可以有多个子项目)
- 如果有多个子项目注意重新打包Tomcat
-
6.7 Mapping问题
-
每次写完Servlet都要写映射
为什么需要映射:我们写的是 Java 程序,但是要通过浏览器访问,而浏览器需要连接 Web 服务器,所以我们需要再 Web 服务中注册我们写的 Servlet,还需给他一个浏览器能够访问的路径;
-
一个Servlet可以指定一个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
一个Servlet指定多个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello3</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello4</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello5</url-pattern> </servlet-mapping>
-
一个Servlet可以指定通用的映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
-
默认请求路径
<!--默认请求路径(不建议这么写这么写会覆盖index.jsp)--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
-
指定后缀
<!--可以自定义后缀实现请求映射 注意点,*前面不能加项目映射的路径 hello/sajdlkajda.qinjiang --> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.qinjiang</url-pattern> </servlet-mapping>
-
多个映射路径优先级问题
- 指定了固有的映射路径优先级最高,如果找不到就会走通用的处理请求;
6.8 ServletContext
Web 容器在启动的时候,它会为每个 Web 程序都创建一个对应的 ServletContext 对象,它代表了当前的 Web 应用.
-
ServletContext 有什么用?
-
- ServletContext既然代表着当前web站点,那么所有Servlet都共享着一个ServletContext对象,所有Servlet之间可以通过ServletContext实现共享数据。
- ServletConfig获取的是配置的是单个Servlet的参数信息,ServletContext可以获取的是配置整个web站点的参数信息。
- 利用ServletContext读取web站点的资源文件
- 实现Servlet的转发【用ServletContext转发不多,主要用request转发】
- 因为ServletContext代表着整个web应用,使用ServletContext会消耗大量的资源,而request对象会随着请求的结束而结束,资源会被回收。使用request域进行Servlet之间的通讯在开发中是非常频繁的。
-
共享数据
ServletContext对象可以被称之为域对象
到这里可能有一个疑问,域对象是什么呢?其实域对象可以简单理解成一个容器【类似于Map集合】
实现Servlet之间通讯就要用到ServletContext的setAttribute(String name,Object obj)方法,
第一个参数是关键字,第二个参数是你要存储的对象package com.yuan.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 test01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { servletContext.setAttribute("name1","袁腾飞1"); servletContext.setAttribute("name2","袁腾飞2"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
package com.yuan.servlet; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class test02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); ServletContext servletContext = this.getServletContext(); String name1 =(String) servletContext.getAttribute("name1"); String name2 =(String) servletContext.getAttribute("name2"); PrintWriter out = resp.getWriter(); out.println("name1:"+name1); out.println("<br/>"); out.println("name2:"+name2); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
编写Servlet映射
<servlet> <servlet-name>test01</servlet-name> <servlet-class>com.yuan.servlet.test01</servlet-class> </servlet> <servlet-mapping> <servlet-name>test01</servlet-name> <url-pattern>/c2</url-pattern> </servlet-mapping> <servlet> <servlet-name>test02</servlet-name> <servlet-class>com.yuan.servlet.test02</servlet-class> </servlet> <servlet-mapping> <servlet-name>test02</servlet-name> <url-pattern>/c3</url-pattern> </servlet-mapping>
-
测试访问结果
-
先访问c3 直接取看能取到什么
-
-
再访问c2 进行赋值
-
-
访问c3 取出值
-
-
-
-
获得初始化参数
<!-- 配置全局参数在web.xml--> <context-param> <param-name>url</param-name> <param-value>url=jdbc:mysql://localhost:3306/ytf_db02?characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true </param-value> </context-param>
ServletContext servletContext = this.getServletContext(); String url = servletContext.getInitParameter("url"); resp.getWriter().println(url);
-
请求转发(服务器内部资源跳转,地址url不会改变)
resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); ServletContext servletContext = this.getServletContext(); resp.getWriter().println("请求转发"); // RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/c1"); // requestDispatcher.forward(req, resp); //连在一起写 servletContext.getRequestDispatcher("/c1").forward(req, resp);
-
请求转发:A访问B,B将请求转发到C,C响应给B,B响应给A 。C设不设置编码无所谓,主要是B要设置编码,因为B要返回给页面,页面是UTF8编码,Tomcat是ISO8859-1编码。请求转发是服务器内部资源的调用,一次请求。
-
重定向:A访问B,B说你去找C,A去访问C 。地址url会改变 C要设置编码,B无所谓。重定向是浏览器重新发起请求
-
转发可以携带参数,重定向不能携带参数。
-
读取配置文件 建议与一文读懂java相对路径一起食用
Properties properties = new Properties(); InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); properties.load(is); String name = properties.getProperty("username"); String pwd = properties.getProperty("password"); resp.getWriter().println("name="+name); resp.getWriter().println("pwd="+pwd);
- 由于Maven约定大于配置配置文件要写在resources文件夹下 ,写在java文件夹下就不会导出
- 写在java文件夹可以看出资源没有被导出
- 如果想要导出在pom.xml加以下代码可以解决这个问题
<!--在build中配置resources,来防止我们资源导出失败的问题(pom.xml中)-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
6.9 HttpServletResponse
- 利用 HttpServletResponse手写下载文件
- 思路分析
-
- 要获取下载文件的路径
-
- 下载的文件名是啥?
-
- 设置想办法让浏览器能够支持下载我们需要的东西
-
- 获取下载文件的输入流
-
- 创建缓冲区
-
- 获取OutputStream对象
-
- 将FileOutputStream流写入到bufer缓冲区
-
- 使用OutputStream将缓冲区中的数据输出到客户端!
-
- 关闭流
-
- 思路分析
// 获取文件下载路径
String filePath = this.getServletContext().getRealPath("WEB-INF/classes/1.png");
//获取文件下载名称截取最后一个/的索引+1 到最后就是文件名称
String fileName = filePath.substring(filePath.lastIndexOf("\\") + 1);
//设置浏览器消息头
resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);
int len = 0;
//创建缓冲区
byte[] bytes = new byte[1024];
ServletOutputStream outputStream = resp.getOutputStream();
FileInputStream fileInputStream = new FileInputStream(filePath);
while ((len = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
//关闭IO流
fileInputStream.close();
outputStream.close();
- filePath.lastIndexOf(“\\”) 这个里面只能是两个反斜杠进行转义表示一个\ 而不能用一个正斜杠
- 因为filePath是个字符串打印出来效果是D:\tomcat-8.5\webapps\c4\WEB-INF\classes\1.png
- 如果用正斜杠在字符串中找不到,返回一个-1
- 在java一般在文件IO流写路径使用正斜杠代替磁盘中的反斜杠
- 而这个是进行字符串截取用/会找不到
//中文文件名URLEncoder.encode编码,否则可能有乱码
resp.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8"));
- 重定向
//重定向要带项目的虚拟映射路径
resp.sendRedirect("/c3/c1");
6.10HttpServletRequest
-
HttpServletRequest 代表客户端的请求,用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到 HttpServletRequest,通过这个 HttpServletRequest 的方法,获得客户端的所有信息
-
获取参数
-
请求转发
-
获得输入流(用的少)
演示获取参数信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/c5" method="get" >
用户名:<input type="text" name="username">
<br>
密 码:<input type="password" name="password">
<br>
爱 好:
<input type="checkbox" name="hobbies" value="唱歌">唱歌
<input type="checkbox" name="hobbies" value="跳舞">跳舞
<input type="checkbox" name="hobbies" value="代码">代码
<br>
<input type="submit">
</form>
</body>
</html>
package com.yuan.Test;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class test05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
String username = req.getParameter("username");
String pwd = req.getParameter("password");
resp.getWriter().println(username);
resp.getWriter().println(pwd);
String[] hobbies = req.getParameterValues("hobbies");
resp.getWriter().println(Arrays.toString(hobbies));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.11 简单总结一下Request和Response的应用
HttpServletRequest:
- 获取参数
- 请求转发
- cookies
- session
- 获得输入流(用的少)
- …
HttpServletResponse:
-
获得输出流(响应内容)
-
重定向
-
…
七、Cookie和Session
7.1 Cookie
==Cookie 是一小段的文本信息(key-value格式)。==客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨别用户状态。
- cookie(客户端技术)机制
- 当用户第一次访问并登陆一个网站的时候,cookie的设置以及发送会经历以下4个步骤:
- 客户端发送一个请求到服务器
- 服务器发送一个HttpServletResponse响应到客户端,其中包含Set-Cookie的头部
- 客户端保存cookie,之后向服务器发送请求时,HttpResponse请求中会包含一个Cookie的头部
- 服务器返回响应数据
- cookie的常用方法
方法 | 说明 |
---|---|
Cookie(String name,String value) | 构造器 |
setValue/getValue | 设置值/取出值 |
setMaxAge/getMaxAge | 生命周期 |
Cookie[] cookies = req.getCookies(); //获得Cookies
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
-
测试:
package com.yuan.Cookie; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class Cookie01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置编码 resp.setContentType("text/html;charset=utf-8"); //获得Cookie Cookie[] cookies = req.getCookies(); if (cookies != null) { resp.getWriter().println("cookies is not null"); //换行 resp.getWriter().println("<br>"); for (int i = 0; i < cookies.length; i++) { if (cookies[i].getName().equals("LastloginTime")){ long time = Long.parseLong(cookies[i].getValue()); Date date = new Date(time); // SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // String format = simpleDateFormat.format(date); //转换时间格式 resp.getWriter().println(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(date)); } } } else { resp.getWriter().println("这是第一次访问本站"); } //创建cookie Cookie cookie = new Cookie("LastloginTime", System.currentTimeMillis() + ""); //将cookie添加到浏览器 resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
7.1.1 cookie有效期
Cookie的有效期是通过setMaxAge()来设置的
-
如果MaxAge为正数,浏览器会把Cookie写到硬盘中,只要还在MaxAge秒之前,登陆网站时该Cookie就有效
-
如果MaxAge为负数,Cookie是临时性的,仅在本浏览器内有效,关闭浏览器Cookie就失效了,Cookie不会写到硬盘中。Cookie默认值就是-1。
-
如果MaxAge为0,则表示删除该Cookie。Cookie机制没有提供删除Cookie对应的方法,把MaxAge设置为0等同于删除Cookie.
-
删除cookie方式:
- 不设置有效期,关闭浏览器自动失效
- 再创建一个Servlet,new一个cookie将之前的cookie覆盖,设置cookie的有效时间为0
package com.yuan.Cookie;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Cookie02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie = new Cookie("LastloginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(0);
//将cookie添加到浏览器
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7.12cookie细节
-
一个cookie只能保存一个信息
-
一个 Web 站点可以给浏览器发送多个 Cookie,最多存放 20 个 cookie;
-
cookie 大小有限制 4kb;
-
300 个 cookie 浏览器上限
-
cookie的不可跨域性:当我访问baidu的时候,浏览器只会把baidu颁发给Cookie带过去,而不会带上google的Cookie.
-
cookie一般对整个web项目都可以使用
7.2 Session
Session是服务器为了记录用户状态而创建的一个特殊的对象。不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。
- 客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是Session。
客户端浏览器再次访问时,只需要从该Session中查找该客户的状态就可以了。
-
当多个客户端执行程序时,服务器会保存多个客户端的Session。
-
获取Session的时候也不需要声明获取谁的Session。
Session的创建机制:
- 当浏览器第一次访问服务器时,服务器创建一个session对象(该对象有一个唯一的id,一般称之为sessionId)。
- 服务器会将sessionId以cookie的方式发送给浏览器。
- 当浏览器再次访问服务器时,会将sessionId发送给服务器。
- 服务器依据sessionId就可以找到对应的session对象。
Session特点
-
服务器会给每个==用户(浏览器)==创建一个Session对象
package com.yuan.Session; import javax.servlet.ServletException; import javax.servlet.http.*; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class Session03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); HttpSession session = req.getSession(); String sessionid = session.getId(); resp.getWriter().println("sessionid是:"+sessionid); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
Session可以进行共享数据
package com.yuan.Session;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Session01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
HttpSession session = req.getSession();
session.setAttribute("name","张三");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.yuan.Session;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Session02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
HttpSession session = req.getSession();
String name = (String) session.getAttribute("name");
resp.getWriter().println(name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- SevletContext可以跨用户(浏览器)共享数据
- Session只能在当前用户(浏览器)共享数据
Session的注销(Session注销后,浏览器会立刻创建一个新的)方式:
-
session.invalidate();
-
<!--在web.xml中设置--> <session-config> <!--设置session失效时间 以分钟为单位--> <session-timeout>1</session-timeout> </session-config>
cookie和session的异同:
- 都是用来跟踪浏览器用户身份的会话方式
- cookie保存在客户端
- session保存在服务端
- session更加安全(cookie在客户端容易被篡改)
- session会比较占用服务器性能,当访问增多时应用cookie