JavaWeb
1、基本概念
1.1、前言
web开发:
-
网页web
-
静态web:html,css,提供给所有人看的数据不会发生变化
-
动态web:每个人看到的数据始终会发生变化
- 技术栈:Servlet/JSP,ASP,PHP
-
-
在java中,动态web资源开发的技术统称为javaWeb
1.2、web应用程序
- 一个web应用由多部分组成(静态web,动态web)
- html,css,js
- jsp,servlet
- java程序
- jar包
- 配置文件(properties)
- web应用程序编写完毕后,若想提供给外界访问:需要一个服务器来统一管理
1.3、静态web
- index-html:网页的后缀,服务器上存在就可以直接进行读取
- 静态web存在的缺点
- web页面无法动态更新,所有用户看到都是同一个页面
- 轮播图,点击特效,伪动态
- JavaScript
- VBScript
- 无法和数据库交互(数据无法持久化,用户无法交互)
- web页面无法动态更新,所有用户看到都是同一个页面
1.4、动态web
页面动态展示
缺点:
- 假如服务器的动态web资源出现了错误,需要重新编写后台程序
- 停机维护
优点:
- web页面可以动态更新,所有用户看到都不是同一个页面
- 可以和数据库交互(JDBC)
2、web服务器
2.1、技术讲解
ASP:
- 微软:国内最早流行
- 在HTML中嵌入了VB的脚本,ASP+COM;
- 在ASP开发中,基本一个页面几千行代码,很混乱
- c#
- iis
PHP:
- PHP开发速度很快,功能很强大,跨平台,代码简单
- 无法承装大访问量的情况
JSP:
B/S:浏览器和服务器
C/S:客户端和服务器
- 本质是servlet
- Sun公司主推的B/S架构
- 基于java语言
- 承装(高并发、高可用、高性能)问题带来的影响
2.2、web服务器
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息
IIS:
- 微软的,ASP…windows中自带的
tomcat
java的根加载机制从rt.jar包来
3、Tomcat
3.1、Tomcat安装
-
startup.bat开启或者cmd下catalina.run,shutdown关闭或者直接关闭cmd
-
localhost:8080
-
可以再index.jsp下修改文档
-
域名重定向:将localhost改为www.liuxiang.com需要在windowsdrivers包下修改etc配置文件,添加一行,再到conf中服务器核心配置文件sever.xml文件下修改host:name和connector:端口号
面试题:
- 谈谈网站是如何访问的
- 输入一个域名,回车
- 检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有此域名的映射
- 有,就直接返回对应的ip地址
- 没有就去DNS解析服务器找,找到就返回,找不到就找不到网页
3.2、发布一个网站
-
将自己写的网站放到服务器中指定的web应用的文件夹下
-
localhost:8080/liustudy/:访问自己写的网址
-
localhost:8080/examples/:访问JSP源码
-
网站的结构:
-
webapps:tomcat服务器的web目录
-
ROOT
-
liustudy:网站的目录名
-
WEB-INF
-
classes:java程序
-
lib:web应用依赖的jar包
-
web.xml:网站配置文件
-
-
index.html 默认的首页
-
static
- css
- style.css
- js
- img
- css
-
-
-
4、Http协议
4.1、什么是http?
-
超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。
-
默认端口:http:80 https:443
4.2、两个时代
- http1.0
- http/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
- http2.0
- http/1.1:客户端可以与web服务器连接后,获得多个web资源
4.3、Http请求
- 客户端–发送端–服务器
请求 URL: https://www.baidu.com/
请求方法: GET
状态代码: 200 OK
远程地址: 14.215.177.39:443
引用站点策略: strict-origin-when-cross-origin
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cache-Control: max-age=0
Connection: keep-alive
1.请求行
- 请求方式:GET/POST,HEAD,DELETE,PUT,TRCAT…
- get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址显示数据内容,不安全,但高效
- post:请求携带的参数无限大,不会在URL地址显示数据内容,安全,不高效
2.消息头
Accept: 告诉浏览器支持的数据类型
Accept-Encoding: 支持的编码格式 GBK,UTF-8,GB2312
Accept-Language: 语言环境
Cache-Control: 缓存控制
Connection: 请求完成是断开还是保持连接
HOST:主机
4.4、Http响应
- 服务器–响应–客户端
Cache-Control: private //缓存控制
Connection: keep-alive //连接
Content-Encoding: gzip //编码
Content-Type: text/html;charset=utf-8 //类型
1.响应体
Accept: 告诉浏览器支持的数据类型
Accept-Encoding: 支持的编码格式 GBK,UTF-8,GB2312
Accept-Language: 语言环境
Cache-Control: 缓存控制
Connection: 请求完成是断开还是保持连接
HOST:主机
Reflush:告诉客户端多久刷新一次
Location:让网页重新定位
2.响应状态码
200 表示成功
3** 请求重定向 //重定向:重新到给定的新位置
404 找不到资源
4xx 资源不存在 //404
5xx 服务器代码错误 //500 502:网关错误
面试题:
当浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来经历了什么?
5、Maven
为什么要学习maven?
- 在javaweb开发中需要使用大量的jar包
- 让maven自动导入和配置jar包
5.1、Maven项目架构管理工具
Maven核心思想:约定大于配置
- 有约束,不要去违反
Maven会规定好如何去编写java代码,必须按这个规范来
5.2、下载安装Maven
Maven – Welcome to Apache Maven
- 配置环境变量
- M2_HOME maven目录下的bin目录
- MAVEN_HOME maven目录
- path下 %MAVEN_HOME%\bin
5.3、阿里云镜像
- 镜像mirrors作用:
- 作用:加速下载
- 国内使用阿里云
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
5.4、本地仓库
在本地仓库,远程仓库,建立一个本地仓库
<localRepository>D:\Environment\apache-maven-3.6.2\maven-repo</localRepository>
5.6、在IDEA中使用Maven
- 新建MavenWeb项目
- 观察仓库有了即可
5.7、maven中的IDEA设置
- 项目创建成功后看一下配置,改成对应的maven版本
- 自动导入源码
5.8、创建一个普通项目
- 不用勾选模板
5.9、在IDEA中标记源码目录和资源目录
5.10、在IDEA中配置Tomacat
- 选择本地Tomcat
- 会出现警告,新建一个
- 启动后出现的页面内容就是index.jsp中的内容
- Maven中的内容
5.11、POM文件
- 是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.liu</groupId>
<artifactId>javaweb-01-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!--
Package:项目的打包方式
jar:java应用
war:javaWeb应用
-->
<packaging>war</packaging>
<!--配置-->
<properties>
<!--项目的默认构建编码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 编码版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!--项目依赖-->
<dependencies>
<!-- 具体依赖的jar包依赖文件-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--项目构建东西-->
<build>
<finalName>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由于约定大于配置,会出现写的配置文件无法导出或者生效的问题,解决方案:
<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.12、相关问题
-
如果没有生成iml文件,解决方案:
- 在主文件下点open in termial
- 控制台输入:mvn idea:module
- 回车
-
IDEA中每次重复配置Maven
- 在IDEA中的全局默认配置中去配置
- maven默认web项目中的web.xml版本问题
- 替换为tomcat中xml.web文件
<?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_3_1.xsd"
version="3.1"
metadata-complete="true">
</web-app>
-
maven仓库的使用,https://mvnrepository.com/
-
编写代码时看tomcat中的servlet examples中的例子
-
去tomcat的lib目录下找相关maven仓库中对应的jar包
- 比如Servlet对应:servlet-api.jar,选择最多人使用的或者最新的
- 直接在pom文件中添加依赖,点击maven刷新即可
-
每次在生成子项目的时候,需要手动加上父标签,再刷新maven
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.liu</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
6、Servlet
6.1、Servlet简介
- sun公司开发动态web的一门技术
- 提供了一个接口:Servlet
- 编写一个类实现Servlet接口
- 把开发好的java类部署到web服务器中
- HttpServlet继承了GenericServlet,G实现了(implement)Servlet
- 自己写的类只需要继承HttpServlet即可
6.2、HelloServlet
- 构建一个项目,删除src目录,再new一个module,这个空的工程就是主工程
- 父项目中会多一个module
<modules>
<module>servlet-01</module>
</modules>
- 子项目中如果没有自动生成< parent>标签,手动添加GAV
<!--父标签,自然是父项目的一些信息-->
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.liu</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
-
父项目中的java子项目可以直接使用
-
Maven环境搭建
- 修改web.xml为最新的
- 将maven的结构搭建完整
-
编写一个servlet程序
- 编写一个普通类
- 实现Servlet接口,继承HttpServlet接口
package com.liu.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 {
super.doPost(req, resp);
}
}
-
编写Servlet的映射
-
在web.xml文件里映射
-
为什么需要映射:
-
写的JAVA程序要通过浏览器访问,而浏览器需要连接web服务器,所以需要在web服务中注册写的servlet,还需要给他一个浏览器能够访问的路径
-
<!--注册servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.liu.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
-
配置Tomcat
-
启动测试,在后面输入hello名,即可调用HelloServlet类里的方法
6.2.1、问题
- 在target目录下没有生成class文件导致报http500错误
- 解决方案:
- 先在setting里面将编译器改为8
- 在project structure里project中的output改为空
-
将Artifacts中的show content of elements全部勾选上,再将Available Elements右键put into out root
-
然后点apply后重启tomcat即可生成class文件
6.3、源码分析
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
-
GenericServlet implements Servlet
-
重写了方法,但对请求和响应没有做任何处理
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
- HttpServlet extends GenericServlet
- 如果是get,就调用get方法,是head,put…就调用各自的方法,但这些方法不是我们需要的,就需要在自己写的类中重写方法
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
6.3、Servlet原理
servlet是由Web服务器调用,web服务器在收到浏览器请求后,会:
6.4、Mapping问题
- 一个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>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<!--均可以访问servlet-->
<url-pattern>/hello2</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>
- 自定义后缀实现请求映射
<!--*前面不能加任何东西-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.liuxiang</url-pattern>
</servlet-mapping>
-
优先级问题:
指定了固有的映射路径优先级最高,找不到就走默认的处理请求
6.5、将常用的每次都做的操作代码放到一个文件中
6.6、新建一个工程
- 在父工程下新建一个子工程,然后在子工程里加入父标签,更新maven
- 在web.xml文件里更新版本代码
- 在main文件下新建java和resources文件
- 在java文件里新建.class文件
- 在web.xml文件里注册servlet
- 在tomcat里将deployment里的旧工程去掉再添加新工程,不去掉的话会打包所有工程,用哪个就打包哪个
6.7.ServletContext
web容器在启动的时候,会为每个web程序都创建一个对应的ServletContext对象,它代表当前的web应用
相关应用:
1.共享数据
我在这个Servlet中保存的数据,可以在另外一个Servlet中拿到
- 先创建一个放置数据的类
package com.liu.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter(); 初始化参数
//this.getServletConfig(); servlet配置
//this.getServletContext(); servlet上下文
ServletContext context = this.getServletContext();
String username = "刘想";//数据
context.setAttribute("username",username);//将一个数据保存在ServletContext中,名字为username,值为username
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
- 配置web.xml
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.liu.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.liu.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
- 再创建一个接受数据的类
package com.liu.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");//需要将object类型转换为String类型,方便程序识别
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
2.获取参数
<!--配置web应用的初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>getp</servlet-name>
<servlet-class>com.liu.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getp</servlet-name>
<url-pattern>/getp</url-pattern>
</servlet-mapping>
package com.liu.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 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);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.请求转发RequestDispatcher
-
请求转发:A告诉B要取资源,B去找C拿
-
重定向:A告诉B要取资源,B告诉A去找C拿
-
请求的是sd4路径,走的却是getp路径
<servlet>
<servlet-name>sd4</servlet-name>
<servlet-class>com.liu.servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd4</servlet-name>
<url-pattern>/sd4</url-pattern>
</servlet-mapping>
package com.liu.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 ServletDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入转发方法");
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/getp").forward(req,resp);//转发到请求路径
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
4.读取资源文件
-
classpath:类路径,配置文件会生生成在target目录下的classes文件
-
需要在当前文件的pom.xml文件下配置,才会输出java目录下的配置文件
-
而在resources目录下的配置文件会直接在target目录下生成
-
通过一个流写入地址即可读取
<servlet>
<servlet-name>db</servlet-name>
<servlet-class>com.liu.servlet.ServletDemo05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>db</servlet-name>
<url-pattern>/db</url-pattern>
</servlet-mapping>
package com.liu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/dbcp.properties");
Properties properties = new Properties();
properties.load(is);
String user = properties.getProperty("username");
String pwd = properties.getProperty("password");
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
6.8、HttpServletResponse
web服务器接收客户端的http请求,针对这个请求,分别创建一个代表请求的
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);
响应的状态码
200 表示成功
3** 请求重定向 //重定向:重新到给定的新位置
404 找不到资源
4xx 资源不存在 //404
5xx 服务器代码错误 //500 502:网关错误
2.常见应用
1.向浏览器输出信息
2.下载文件
- 要获取下载文件的路径
- 下载的文件名是什么
- 设置浏览器能够支持下载我们需要的东西
- 获取下载文件的输入流
resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(filename,"UTF-8"));
- 创建缓冲区
- 获取OutputStream对象
- 将fileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
- 关闭流
package com.liu.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//- 要获取下载文件的路径
String realPath = "D:\\代码\\java基础\\JavaWeb\\javaweb-02-servlet\\response\\target\\classes\\1.png";
System.out.println("下载的路径为:"+realPath);
//- 下载的文件名是什么
String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);
//- 设置浏览器能够支持下载我们需要的东西
resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(filename,"UTF-8"));
//- 获取下载文件的输入流
FileInputStream fis = new FileInputStream(realPath);
//- 创建缓冲区
byte[] buffer = new byte[1024];
int len = 0;
//- 获取OutputStream对象
ServletOutputStream os = resp.getOutputStream();
//- 将fileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
while (fis.read(buffer) != -1){
os.write(buffer,0,len);
}
//- 关闭流
os.close();
fis.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.验证码功能
- 前端实现
- 后端实现,用到java的图片类 BufferedImage
package com.liu.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器3s自动刷新一次,响应可以设置前端一切东西
resp.setHeader("Refresh","3");
//在内存中创建一个图片
BufferedImage bufferedImage = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
//设置图片的背景颜色
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//给图片写数据
g.setColor(Color.BLUE);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告诉浏览器这个请求用图片方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,不让网站缓存
resp.setDateHeader("Expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片写给浏览器
ImageIO.write(bufferedImage,"jpg",resp.getOutputStream());
}
//生成随机数,保证生成7位数
private String makeNum(){
Random random = new Random();
String number = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-number.length(); i++) {
sb.append("0");
}
number = sb.toString() + number;
return number;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
4.实现重定向(重点)
客户端A向web资源B请求,B要客户端A去找web资源C,成为重定向
常见常见:
- 用户登录
//resp.setHeader("Location","/response_war/image");
//resp.setStatus(302);
resp.sendRedirect("/response_war/image");
面试题:重定向和转发的区别?
相同点:页面都会跳转
不同点:请求转发url不会发生变化 307,重定向url会发生变化 302
- 练习:从jsp跳转到另外一个jsp页面
<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径需要寻找到项目的路径--%>
<%--${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>
</body>
</html>
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理请求
String username = req.getParameter("username");
String pwd = req.getParameter("password");
System.out.println(username+":"+pwd);
//重定向要加上完整路径
resp.sendRedirect("/response_war/success.jsp");
}
6.9、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息
方法:
1、获取前端传递的参数
2、请求转发
<%--
Created by IntelliJ IDEA.
User: liuxiang
Date: 2022/4/20
Time: 23:26
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h1>登录</h1>
<div style="text-align: center">
<%--以post的方式提交表单到login请求--%>
<form action="${pageContext.request.contextPath}/login" method="post">
用户名: <input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
爱好:
<input type="checkbox" name="hobbys" value="女孩">女孩
<input type="checkbox" name="hobbys" value="唱歌">唱歌
<input type="checkbox" name="hobbys" value="代码">代码
<input type="checkbox" name="hobbys" value="电影">电影
<br>
<input type="submit">
</form>
</div>
</body>
</html>
package com.liu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobbys");
System.out.println("================");
//后台接收乱码问题
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
System.out.println("===================");
//通过请求转发
resp.sendRedirect("/request_war/success.jsp");
// req.getRequestDispatcher("/request_war/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
``
package com.liu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobbys");
System.out.println("================");
//后台接收乱码问题
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
System.out.println("===================");
//通过请求转发
resp.sendRedirect("/request_war/success.jsp");
// req.getRequestDispatcher("/request_war/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}