Javaweb笔记(Tomcat、Maven使用方法、servlet、简单MVC架构)
1.基本概念
1.1 前言
-
静态Web:
-
提供给所有人看数据不会发生变化
-
HTML,CSS
-
-
动态Web:
-
几乎所有网站
-
有数据交互,登录账号密码,网站访问人数等
-
技术栈:Servlet/JSP,ASP,PHP
-
在Java中,动态web资源开发的技术统称为JavaWeb
1.2 web应用程序
Web 应用程序:可以提供浏览器访问的程序;
- a.html. b.htm.....多个web资源,这些web资源可以被外界访问,对外界提供服务
- 能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。
- URL
- 这个统一的web资源会被放在同一个文件夹下,Web 应用程序 —> Tomcat:服务器
- 一个 Web 应用由多部分组成(静态Web、动态Web)
- HTML,CSS,JavaScript
- JSP,Servlet
- Java 程序
- jar 包
- 配置文件 (Properties)
web应用程序编写完毕后,若想提供给外界访问,需要一个服务器来统一管理
1.3 静态web
- *.htm, *.html:网页后缀,如果服务器尚一致存在这些东西,就可以直接进行读取
- 静态web存在的缺点
- web页面无法动态更新,所有用户看到的都是同一个页面
- 轮播图,点击特效:伪动态
- JavaScript(实际开发中用的最多)
- VBScript
- 无法和数据库交互:数据无法持久化,用户无法交互
- web页面无法动态更新,所有用户看到的都是同一个页面
1.4 动态web
页面会动态展示:web展现的效果因人而异
缺点:
- 加入服务器的动态web资源出现了错误,需要重写后台程序,重新发布
- 停机维护
优点:
- web页面可以动更新,所有用户看到的不是同一个页面
- 可以和数据库交互:数据持久化(注册,商品信息,用户信息……)
2. web服务器
2.1 技术讲解
ASP:
- 微软:国内最早流行的是ASP
- 在HTML中嵌入了VB的脚本,ASP+COM
- 在ASP开发中,基本一个页面都有几千行的业务代,业务乱
- 维护成本高
- C#
- IIS
php
- php开发速度快,功能强大,跨平台,代码简单(70%的网站使用,WP)
- 无法承载大访问量的情况(局限性)
JSP/Servlet:
B/S:浏览和服务器
C/S:客户端和服务器
- sun公司主推的B/S架构
- 基于Java语言:大部分公司和开源组件使用java
- 可以承载三高(高并发、高可用、高性能)问题带来的影响
- 语法像ASP,便于转语言,加强市场强度
2.2 web服务器
服务器是一种被动操作,用来处理用户的一些请求和给用户一些响应信息
IIS
- 微软的,ASP中,Windows中自带
Tomcat
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目。
Tomcat 技术先进、性能稳定,而且免费。
轻量级服务器,初学javaweb的最佳选择。
实际上运行JSP页面和Servlet。
(工作3-5年后尝试手写Tomcat服务器)
3. Tomcat
3.1 安装
3.2 Tomcat的配置和启动
文件夹作用:
启动、关闭Tomcat
启动:startup.bat
关闭:关闭窗口,shutdown.bat
3.3 配置
服务器配置核心文件: server.xml
-
可以配置启动的端口号
-
Tomcat的默认端口号为:8080
-
mysql:3306
-
http:80
-
https:443
-
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
- 配置主机的名称
- 默认主机名为:localhost -> 127.0.0.1
- 默认网站应用存放的位置:webapps
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
面试题:网站如何访问
- 在浏览器输入一个域名,回车;
- 本机查看 C:\Windows\System32\drivers\etc\hosts 配置文件是否有相应域名的映射。
- 有,则直接映射到对应的 IP 地址,进行访问。
- 无,则去 DNS 服务器上查找对应的 IP,找到就返回相应的 IP,找不到就不返回。
3.4 发布一个web网站
- 在webapps目录下,放入自己写的网站
- 访问文件名
网站应有结构
--webapps :Tomcat服务器的web目录
-ROOT
-JavaWebTest :网站的目录名
- WEB-INF
-classes : java程序
-lib:web应用所依赖的jar包
-web.xml :网站配置文件
- index.html 默认的首页
- static :存放资源文件
-css
-style.css
-js
-img
-.....
4. HTTP
4.1 HTTP简介
HTTP(hypertext transport protocol) 超文本传输协议。一个简单的请求-响应协议,常运行在TCP上。
- 文本 :HTML,字符串…
- 超文本:图片,音乐,视频,定位,地图…
- 80 端口
Https:安全的
HTTPS(Hyper Text Transfer Protocol over SecureSocket Layer):是以安全为目标的 HTTP 通道,在 HTTP 的基础上通过传输加密和身份认证保证了传输过程的安全性。HTTPS 在HTTP 的基础下加入SSL 层,HTTPS 的安全基础是 SSL。
- 443端口
4.2 两个时代
- HTTP 1.0:
- HTTP/1.0:客户端与 Web 服务器连接后,只能获得一个Wen 资源,然后就断开连接。加入某个页面有多个图片资源需要加载,那么需要连接多次,影响服务器和客户端的性能。
- HTTP 2.0:
- HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源。
4.3 Http请求
- 客户端 - 发送请求 - 服务器
百度为例:
Request URL:https://www.baidu.com/ 请求地址
Request Method:GET get方法/post方法
Status Code:200 OK 状态码:200
Remote Address:14.215.177.39:443 远程地址
Accept:text/html 类型
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,delete,put,tract
- get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全但高效
- post:请求能够携带的参数没限制,大小没限制,不会在浏览器的URL地址栏显示数据内容,安全但不高效
2. 消息头
Accept:支持的数据类型
Accept-Encoding:支持那种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:语言环境
Cache-Control:缓存控制
Connection:请求完成后是断开还是保持链接
HOST: 主机
4.4 Http响应
- 服务器 - 响应 - 客户端
百度为例:
Cache-Control:private 缓存控制
Connection:Keep-Alive 连接
Content-Encoding:gzip 编码
Content-Type:text/html 类型
1. 响应体
Accept:支持的数据类型
Accept-Encoding:支持那种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:语言环境
Cache-Control:缓存控制
Connection:请求完成后是断开还是保持链接
HOST: 主机
Refresh: 告诉客户端,多久刷新一次
Location: 让网页重新定位
2. 响应状态码(重要)
- 200:请求响应成功
- 3**:请求重新定向
- 重定向:重新到指定的新位置
- 4**:找不到资源, 404
- 资源不存在
- 5**:服务器代码错误
- 500
- 502:网关错误
常见面试题:
当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?
5. Maven
为什么学习Maven?
- 在 JavaWeb 开发中,需要使用大量的 jar 包,我们手动去导入;
- 如何能够让一个东西自动帮我导入和配置这个jar包。
Maven是一种架构管理工具
5.1 Maven架构管理工具
用于方便导入jar包
核心思想:约定大于配置
- 有约束,不要去违反
- Maven 会规定好你该如何去编写我们的 Java 代码,必须要按照这个规范来;
5.2 下载和安装,配置环境变量
5.2.1 安装
apache官网,解压到Environment
5.2.2 配置环境变量
在我们的系统环境变量中配置如下配置:
- M2_HOME:maven目录下的bin目录
- MAVEN_HOME:maven的目录
- 在系统的path中配置MAVEN_HOME
测试是否安装成功。
5.2.3 阿里云镜像
- 镜像:mirrors
- 作用:加速下载
- 国内建议使用阿里云
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
5.2.4 本地仓库
建立一个本地仓库: localRepository
<localRepository>D:\Environment\apache-maven-3.8.5\maven-repo</localRepository>
5.3 IDEA中使用Maven
在Maven的版本不同,可能会与idea版本产生一些冲突(建议使用3.6.1)
- 启动IDEA
- 创建项目
-
等待项目初始化完毕
点击右下角的Enable Auto-Import
等到出现 BUILD SUCCESS ,项目搭建成功
-
观察Maven仓库的变化
-
IDEA中的Maven设置
注意在自动生成框架时关注Maven的设置是否出错
5.4 创建普通Maven项目
普通的Maven项目:
web项目:
5.5 标记文件夹功能
方法1:
方法2:
5.6 在IDEA中配置Tomcat
- 点击右上角的选择
- 在弹出的页面中新建Tomcat Server - local
-
解决警告问题
必须要的配置:为什么会有这个问题:我们访问一个网站,需要指定一个文件夹名字
- 运行
5.7 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.chachan53</groupId>
<artifactId>javaweb_01_maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!--
项目的打包方式
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>
maven存在的问题
由于maven的约定大于配置,可能碰到配置文件无法被导出或生效的问题
解决方案:在build中配置resources
<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.8 IDEA操作
查看jar包依赖树
5.9 Maven仓库的使用
查看源码导入的jar包名称,搜索,导入pom
6. Servlet
6.1 Servlet简介
Servlet 就是 Sun 公司开发动态 Web 的一门技术
Sun 在这些 API (Application Programming Interface,应用程序接口)中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
- 编写一个类,实现Servlet接口。
- 把开发好的Java类部署到web服务器中。
把实现了 Servlet 接口的 Java 程序叫做,Servlet
6.2 HelloServlet
Serlvet 接口 Sun 公司有两个默认的实现类:HttpServlet,GenericServlet
-
构建一个普通的Maven项目,删掉src目录,学习在项目里建Moudel。这个空工程是Macen的主工程
-
在主工程中建立Moudel,其中:
- 父项目有
<modules> <module>servlet_01</module> </modules>
- 子项目有
<parent> <artifactId>javaweb_02_servlet</artifactId> <groupId>com.chachan53</groupId> <version>1.0-SNAPSHOT</version> </parent>
父项目中的java子项目可以直接使用
son extends father
-
Maven环境优化
- 修改web.xml为最新的(Tomcat - conf - web.xml)
- 将maven的结构搭建完整(注意要将java文件夹进行标记,否则无法创建java class文件
-
编写一个Servlet程序
package com.chachan53.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
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);
}
}
- 编写Servlet的映射
映射原因:虽然是Java 程序,但是要通过浏览器访问,而浏览器需要连接 Web 服务器,所以我们需要在Web 服务中注册我们写的 Servlet,并提供一个浏览器能够访问的路径
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.cha.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 配置Tomcat
注意:配置项目发布的路径
- 启动测试
6.3 Servlet原理
Servlet 是由 Web 服务器调用,Web 服务器在收到浏览器请求之后,会:
写的实现类,重写方法:
- 接收并处理请求
- 给出响应的信息
6.4 Mapping
一个 Servlet 可以指定一个映射路径
<!--servlet的请求路径-->
<!--localhost:8080/servlet_01/hello-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern> <!--指定请求路径-->
</servlet-mapping>
指定多个映射路径
<!--servlet的请求路径-->
<!--localhost:8080/servlet_01/hello-->
<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>/hello/*</url-pattern>
</servlet-mapping>
默认请求路径(少用,会删去首页)
<!--默认请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
自定义后缀:*
签名不能加项目映射的路径
<!--自定义后缀实现请求映射
注意:*前面不能加项目映射的路径
hello/sdhjfs.hello3
-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.hello3</url-pattern>
</servlet-mapping>
优先级问题
指定的固有的映射路径优先级最高,找不到返回默认映射
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.cha.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet的请求路径-->
<!--localhost:8080/servlet_01/hello-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!--404-->
<!--设置默认请求路径-->
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.cha.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
ErrorServlet
public class ErrorServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
//or
// resp.setContentType("test/html");
// resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.print("<h1>404</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.5 ServletContext
Web 容器在启动的时候,它会为每个 Web 程序都创建一个对应的ServletContext
对象,它代表了当前的 Web 应用
1. 共享数据:(尽量少用该方法
在一个Servlet中保存在数据,能在另一个Servlet中获得
设置数据的类:
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter() 初始化参数
//this.getServletConfig() Servlet配置
//this.getServletContext() Servlet上下文
ServletContext context = this.getServletContext();
String username = "cha"; //数据
context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username.值 username
}
}
读取数据的类:
(运行时会下载文件,为什么?)
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext(); //与HelloServlet中公用一个对象
String username = (String) context.getAttribute("username");
resp.setContentType("test/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
在web.xml中设置映射:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.cha.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>com.cha.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
测试访问结果:
- 先访问hello,设置username
- 访问getc,获得username
2. 获取初始化参数
- 参数配置
<!--配置初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
- 设置映射
<servlet>
<servlet-name>gi</servlet-name>
<servlet-class>com.cha.servlet.GetInit</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gi</servlet-name>
<url-pattern>/gi</url-pattern>
</servlet-mapping>
- 获取参数类
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
3. 请求转发
请求转发时,设置的路径会获得请求转发的地址
请求转发示意图
- 设置映射
<servlet>
<servlet-name>d4</servlet-name>
<servlet-class>com.cha.servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>d4</servlet-name>
<url-pattern>/d4</url-pattern>
</servlet-mapping>
- 设置转发类
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入Demo04");
// RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gi"); //转发的请求路径
// requestDispatcher.forward(req, resp); //调用forward实现转发
context.getRequestDispatcher("/gi").forward(req, resp);
}
4. 读取资源文件
Properties类的使用
- 在 java 目录下新建 properties
- 在 resources 目录下新建 properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath(类路径)
使用文件流:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); //最开始的/代表当前文件夹
Properties properties = new Properties();
properties.load(is);
String username = properties.getProperty("username");
String pwd = properties.getProperty("password");
resp.getWriter().print(username + ":" + pwd);
}
读取内容:
username=cha
password=123456
6.6 HttpServletResponse
Web 服务器接收到客户端的 http 请求,针对这个请求,分别创建一个代表请求的 HttpServletRequest
对象,代表响应的一个 HttpServletResponse
- 如果想要获取客户端请求过来的参数:
HttpServletRequest
- 如果要给客户端响应一些信息:
HttpServletResponse
1. 方法简单分类
- 向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
- 向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
- 响应的状态码
int SC_OK = 200;
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_NOT_FOUND = 404;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_BAD_GATEWAY = 502;
2. 常见应用
- 向浏览器输出消息
- 下载文件
- 获取路径
- 获得文件名
- 让浏览器支持下载
- 获取下载文件的输入流
- 创建缓冲区
- 获取
OutputStream
对象 - 将
FileOutputStream
刘写入buffer
缓冲区 - 使用
OutputStream
将缓冲区中的数据输出到客户端
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取路径,使用绝对路径
String realPath = "F:\\java_code\\JavaWeb\\javaweb_02_servlet\\response\\src\\main\\resources\\buffer.txt";
System.out.println("下载路径:"+realPath);
// 2. 获得文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);// 获取最后一个/后面的字段
// 3. 让浏览器支持(Content-Disposition)下载; URLEncoder实现中文下载
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
// 4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
// 5. 创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6. 获取`OutputStream`对象
ServletOutputStream out = resp.getOutputStream();
// 7. 将`FileOutputStream`刘写入`buffer`缓冲区,使用 `OutputStream` 将缓冲区中的数据输出到客户端
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
// 关闭
in.close();
out.close();
}
3. 验证码:生成随机数字
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 让浏览器自动刷新
resp.setHeader("refresh", "3");
// 在内存中创建图片
BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_3BYTE_BGR);
// 得到图片
Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics(); // 画笔,绘制颜色
// 设置图片的背景颜色
graphics.setColor(Color.lightGray);
graphics.fillRect(0,0,80,20);
// 给图片写数据
graphics.setColor(Color.BLUE);
graphics.setFont(new Font(null, Font.BOLD,20));
graphics.drawString(makeNum(),0,20);
// 告诉浏览器,该请求用图片打开
resp.setContentType("image/jpg/jpeg");
// 网站存在缓存,不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
// 把图片写给浏览器
ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
}
// 生成随机数
private String makeNum(){
Random random = new Random();
String num = random.nextInt(9999999) + "";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 7-num.length(); i++) {
buffer.append("0");
}
num = buffer.toString() + num;
return num;
}
4. 重定向
重定向:Web 资源 B 收到客户端 A 请求后,通知 A 访问另一个 Web 资源 C
常见场景:用户登录
示意图:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 重定向
/*
resp.setHeader("Location","/r/img");
resp.setStatus(302);
*/
resp.sendRedirect("/r/img");
}
面试题:重定向与转发的区别?锚点
-
相同点:
- 页面都会实现跳转
-
不同点:
- 请求转发的时候,URL 不会发生变化;307
- 重定向时候,URL 地址栏会发生变化; 302
简单获取登录数据
注意导入jsp对应的包
- 修改首页
<%--这里提交的路径,需要寻找到项目的路径--%>
<%--${pageContext.request.contextPath}代表当前的项目--%>
<form action="${pageContext.request.contextPath}/login" method="get">
用户名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
<input type="submit">
</form>
- 实现后跳转页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Success</h1>
</body>
- 实现数据获取和重定向
@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("/r/success.jsp");
}
6.7 HttpServletRequest
HttpServletRequest
代表客户端的请求,用户通过 HTTP 协议访问服务器,HTTP 请求中的所有信息会被封装到 HttpServletRequest
,通过这个HttpServletRequest
的方法,获得客户端的所有信息
获取前端传递的参数 和 请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobby");
System.out.println("=====================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
System.out.println("=====================");
// 通过请求转发
// 这里的/代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
面试题:重定向与转发的区别?
7. cookie(不怎么使用)
8. Session(重点)
8.1会话
会话:用户打开一个浏览器,点击了很多超链接,访问多个 Web 资源,关闭浏览器,这个过程可以称之为会话;
有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话;
- 你能怎么证明你是学生?
你 | 学校 |
---|---|
发票 | 学校开的发票 |
学校的登记 | 学校给你的校牌 |
- 一个网站,怎么证明你来过?
客户端 服务端
服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了; cookie
客户端:服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了; cookie
服务端:服务器登记你来过了,下次你来的时候我来匹配你; seesion
8.2 保存会话的两种技术
cookie
- 客户端技术(响应,请求)
session
- 服务器技术,利用这个技术,可以保存用户的会话信息?可将信息或数据放在 session 中
8.3 session
什么是 Session ?
- 服务器会给每一个用户(浏览器)创建一个 Session 对象;
- 一个 Session 独占一个浏览器,只要浏览器没有关闭,这个 Session 就存在;
- 用户登录之后,整个网站它都可以访问!-> 保存用户的信息;保存购物车的信息…
Session 和 cookie 的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)
- Session把用户的数据写到用户独占Session中,服务器端保存 (保存重要的信息,减少服务器资源的浪费)
- Session 对象由服务创建;
cookie:
session:
使用场景:
- 保存一个登录用户的信息;
- 购物车信息;
- 在整个网站中经常会使用的数据,我们将它保存在 Session 中;
会话自动过期:web.xml配置
9. JSP
9.1 什么是JSP
Java Server Pages : Java服务器端页面,也和Servlet一样,用于动态Web技术!
最大的特点:写JSP就像在写HTML
区别:
- HTML只给用户提供静态的数据
- JSP 页面中可以嵌入Java 代码,为用户提供动态数据;
9.2 JSP原理
服务器内部工作:
Tomcat 中有一个 work 工作目录;
IDEA 中使用 Tomcat 的会在 IDEA 中 Tomcat 中生产一个 work 目录
页面转变成了 Java 程序
浏览器向服务器发送请求,不管访问什么资源,起始都是在访问 Servlet !
JSP 最终也会被转换成一个 Java 类!
JSP 本质上就是一个 Servlet
在JSP页面中
- 只要是 JAVA代码就会原封不动的输出;
- 如果是HTML代码,就会被转换为以下格式,输出到前端
out.write("<html>\r\n");
10. JavaBean
11. MVC三层架构
什么是 MVC : Model View Controller 模型、视图、控制器
11.1 原始架构
用户直接访问控制层,控制层就可以直接操作数据库;
servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
程序猿调用
|
JDBC
|
Mysql Oracle SqlServer ....
11.2 MVC三层架构
- Model
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD
- View
- 展示数据
- 提供链接发起 Servlet 请求(a,form,img…)
- Controller (Servlet)
- 接收用户的请求:(req:请求参数、Session 信息…)
- 交给业务层处理对应的代码
- 控制试图的跳转
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库