1.基本概念
1.1 web开发
- web是网页的意思,表示我们可以从网站上取得一定的资源
- 静态web:
- html、css
- 提供给所有人看的数据,数据始终不会发生变化
- 动态web:
- 几乎所有的网站都是动态的
- 提供给所有人看的数据,数据始终会发生变化。每个人在不同的时间、地点看到的信息各不相同
- 常用技术栈:Serblet/JSP, ASP, PHP
- 在java中动态web资源开发的技术统称为javaWeb
1.2 web应用程序
- web应用程序:可以提供浏览器访问的程序
- 如xxx.html……多个web资源整合起来,这些资源可以被外界访问,对外界提供服务。
- 能够被访问到的任何一个资源或者页面,都存在于这个世界的某一台计算机上
- URL
- 这些统一的web资源会被放在同一个文件夹下,这就是一个web应用程序,依赖于Tomcat(服务器)去访问
- 一个web应用由多部分组成(静态web、动态web)
- html、css、js
- jsp、servlet
- java程序
- jar包
- 配置文件(properties)
- web应用程序编写完毕后,若想提供给外界访问,需要一个服务器来统一管理
1.3 静态web
- *.htm、 *.html是网页的后缀,若服务器上一直存在这些东西,就可以直接通过网络进行读取。
- 流程如下:
- 静态web的缺点:
- web页面无法更新,所有用户看到的页面相同
- 轮播图,点击特效:伪动态(使用javaScript实现)
- 无法和数据库交互,数据无法持久化,用户无法交互
1.4 动态web
- 页面可以动态展示,每个用户看到的页面都不一样。web页面展示的效果因人而异。
- 流程如下
- 缺点:若服务器的动态web资源出错,就需要重新编写后台程序并且重新发布,代价会有点大
- 优点:
- web页面可以动态更新,每个用户看到的页面都不一样
- 可以和数据库交互,可以做数据持久化,存储用户数据
2.web服务器
2.1 技术
ASP:
- 国内最早流行的,来自微软
- 在html中嵌入了VB脚本
- 在ASP开发中,一个页面往往会有几千行的业务代码,极难维护
PHP:
- 开发速度快、功能强大、跨平台、代码简单
- 无法承载大量访问的情况,具有局限性,仅适用于中小型的网站
JSP:
- 基于java语言
- 可以承载高并发、高可用、高性能带来的影响
- 语法和ASP相似,加强市场竞争力
2.2 web服务器
- 服务器是一种被动的操作,用来处理用户的请求,并给用户响应
- IIS
- Tomcat
3. Tomcat详解
3.1 安装tomcat
- tomcat官网下载最新的安装包
- 解压
3.2 Tomcat启动
- Tomcat文件夹目录介绍
- bin目录下是启动、关闭的脚本文件,存放tomcat命令
- conf是配置文件,里面的server.xml文件是核心的配置文件
- lib是依赖的jar包
- logs是日志
- webapps存放网站
- mac操作系统启动、关闭Tomcat的方式
- 将下载好的tomcat压缩包移入/usr/local目录下
sudo mv /Users/taozehua/Downloads/apache-tomcat-10.0.10.tar.gz /usr/local/ - 解压缩在/usr/local/目录
sudo (需要先进入特权模式) cd /usr/local/ tar zxvf apache-tomcat-10.0.10.tar.gz - 建立链接,方便维护使用
sudo ln -s /usr/local/apache-tomcat-10.0.10/Library/Tomcat - 命令行启动Tomcat:
/Library/Tomcat/bin/startup.sh 若出现如下提示则表示安装并运行成功:Using CATALINA_BASE: /Library/Tomcat
Using CATALINA_HOME: /Library/Tomcat
Using CATALINA_TMPDIR: /Library/Tomcat/temp
Using JRE_HOME: /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
- 打开浏览器,输入 http://localhost:8080/
回车之后如果看到Apache Tomcat,表示已经成功运行Tomcat - 停止tomcat:
/Library/Tomcat/bin/shutdown.sh
3.3 Tomcat配置
3.4 发布一个web网站的流程
- 将自己写的网站放到服务器(tomcat)中指定的web应用的文件夹下,这里是webapps目录下。如这里的tao文件夹下面就是自己写的网页。
文件夹结构如下 这时启动tomcat服务器,并且使用浏览器访问http://localhost:8080/tao/就会显示出自己写的网站 - 网站应有的结构:
--webapps: Tomcat服务器的web目录
--ROOT
--tao:自己写的网站的目录名
-WEB-INF
-classes:java程序
-lib:web应用所依赖的jar包
-web.xml:网站的配置文件
-index.html:默认的首页
- static
-css
-js
-img
-……
4.Http详解
4.1 什么是Http
- Http(超文本传输协议)是一个简单的请求响应协议,通常运行在TCP之上。
- 超文本:图片、音乐、视频、地图……
- http默认端口:80
- Https:(安全的)
4.2 两个时代
- http1.0
- HTTP/1.0:客户端与web服务器连接后,只能获得一个web资源,断开连接(再要使用的时候需要重新连接请求)
- http2.0
- HTTP/1.1:客户端与web服务器连接后,只能获得多个web资源
4.3 Http请求(Request)
- 客户端向服务器发送请求
- 以百度为例:
- Request URL:请求地址
- Request Method:请求方法
- Status Code:状态码
- Remote Address:远程地址+端口
Request URL: https://www.baidu.com/sugrec?prod=pc_his&from=pc_web&json=1&sid=&hisdata=&_t=1631334447290&req=2&csor=0
Request Method: GET
Status Code: 200 OK
Remote Address: 127.0.0.1:7890
Accept: application/json, text/javascript
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Cache-Control: max-age=0
- 请求行:
- 请求行中的请求方式:GET、POST、HEAD、DELETE、PUT……
- get:一次请求能够携带的参数比较少,大小有限制,会在浏览器的url地址栏显示数据内容,不安全但高效。
- post:一次请求能够携带的参数没有限制,大小没有限制,不会在浏览器的url地址栏显示数据内容,安全但不高效。
- 消息头:
- Accept:告诉浏览器,它所支持的数据类型
- Accept-Encoding:支持哪种编码格式
- Accept-Language:告诉浏览器,它的语言环境
- Cache-Control:缓存控制
- Connection: 告诉浏览器请求完成是断开还是保持连接
- HOST:主机
4.4 Http响应(Response)
5. Maven
在javaweb开发中,需要使用大量的jar包,手动导入太麻烦,需要Maven来自动导入和配置jar包。
5.1 Maven(项目架构管理工具)
- 使用Maven来自动导入和配置jar包
- Maven的核心思想:约定大于配置(有约束不要去违反)
- Maven会规定好该如何去编写java代码,必须要按照规范来(如代码的目录结构的规定)
5.2 在IDEA中使用Maven
maven项目创建步骤:
- 选择webapp模版进行创建maven项目
- 等待一段时间后导入成功,并且自己加入java目录和resources目录(可能会需要自己标记目录类别),最后完整的项目结构如下:
5.3 在IDEA中配置Tomcat
- 点击右上角Add Configuration……
- 点击左上角的加号添加配置,并且找到Tomcat Server,选择本地
- 设置Tomcat的服务器启动名称、JDK环境和Tomcat的默认启动端口号。
注意还需要在Application Server一栏中选择自己电脑上的tomcat所在的路径(如果出现Application server libraries not found可能是因为tomcat版本过高不兼容,降低tomcat版本就好) 若出现其他问题点击fix即可 - 配置完成后右上角就可以启动tomcat了
- 启动成功
- 使用浏览器访问http://localhost:8080/javawebmaven_war/就可以得到Hello World!这里访问到的Hello World!就是项目目录webapp下index.jsp里面的内容
6. Servlet
6.1 Servlet简介
- Servlet是sun公司开发动态web的一门技术
- sun公司在这些API中提供一个接口,叫做Servlet。开发一个Servlet程序只需要完成:
- 编写一个类,实现Servlet接口
- 把开发好的java类部署到web服务器中
- 把实现了Servlet接口的java程序叫做Servlet,Servlet接口Sun公司有两个默认的实现类:HttpServlet、GenericServlet
6.2 HelloServlet
- 构建一个普通的maven项目,不需要以webapp为模版。
- 在pom.xml中导入Servlet和JSP的依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
- 在项目下新建一个Model:Servlet-01,相当于一个子模块
父项目中会有<modules>
<module>Servlet-01</module>
</modules>
父项目中的jar包子项目可以直接使用,子项目的jar包父项目不可以直接使用 - Maven环境优化:
- 编写一个Servlet程序
- 编写一个普通类
- 实现Servlet接口,直接继承HttpServlet
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.println("Hello Servlet!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 编写Servlet的映射
- 配置Tomcat:见5.3节
- 启动测试,使用浏览器访问http://localhost:8080/Servlet01_war/hello就会显示出打印出来的Hello Servlet!
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可以指定多个映射路径,这时候访问/hello、/hello1……都可以得到对应的页面
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</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>/hello2</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定通用映射路径,映射为/hello/*后访问/hello+任意内容(或者不加)都可以访问到该页面
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
- 如果直接写/*(默认请求路径),那么默认页面就不再是index.jsp对应的那个页面,而是hello对应的页面
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
- 可以自己指定一些后缀,这时候*前面不能加任何映射的路径,即不能出现“/”。(这时候访问/hello/sadhha.truth也能访问到hello)
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.truth</url-pattern>
</servlet-mapping>
- 优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求
6.5 ServletContext对象的应用
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用,可以对当前的web应用进行管理
6.5.1 共享数据:在一个Servlet中保存的数据可以在另一个Servlet中拿到
- 先实现一个放置数据的servlet类。该类中先使用getServletContext方法得到ServletContext对象,再由setAttribute方法将数据保存在ServletContext中
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = "tao";
context.setAttribute("username",username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 再去实现一个servlet类获取数据。同样可以使用getServletContext方法得到ServletContext对象,并且通过getAttribute方法可以拿到HelloServlet中保存的数据。(注意:HelloServlet和GetServlet共享一个ServletContext对象,因此它们之间可以进行数据交换)
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String username =(String) servletContext.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("name:"+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.example.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>get</servlet-name>
<servlet-class>com.example.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>get</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
- 最后运行项目,先访问http://localhost:8080/Servlet02_war/hello,再去访问http://localhost:8080/Servlet02_war/get就可以得到在HelloServlet中设置的用户名。注意访问顺序不能颠倒,因为需要先设置再读取。
6.5.2 获取初始化参数
- 在web.xml中配置web应用的初始化参数
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
相当于一个键值对,key是url,value是jdbc:mysql://localhost:3306/mybatis - 实现一个DemoServlet类来获取初始化参数。通过servletContext.getInitParameter(“url”)方法就可以获得url对应的参数
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
System.out.println(servletContext.getInitParameter("url"));
}
- 当然仍然需要在web.xml中进行注册和映射
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.example.servlet.DemoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
- 运行项目后访问http://localhost:8080/Servlet02_war/gp就会在控制台输出jdbc:mysql://localhost:3306/mybatis
- 注意如果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">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
6.5.3 请求转发
- 实现一个DemoServlet2类进行请求转发。这里使用getRequestDispatcher和forward方法将请求转发到6.5.2节实现的DemoServlet类对应的页面
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/gp");
requestDispatcher.forward(req,resp);
}
- 在web.xml中进行注册
<servlet>
<servlet-name>dp</servlet-name>
<servlet-class>com.example.servlet.DemoServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dp</servlet-name>
<url-pattern>/dp</url-pattern>
</servlet-mapping>
- 此时运行项目并且使用浏览器访问http://localhost:8080/Servlet02_war/dp就会显示出/gp页面的内容。可以理解为自动跳转到了该页面,但url路径没变,仍然是/dp。
- 通常应用于以下场景:
- a需要向c请求资源,但a只能访问b,这时候就需要b进行请求转发(a始终只与b直接交流)。
- 不同于重定向,重定向通常是a向b请求资源,然后b告诉a资源在c上,a再去向c请求资源。这时a和b、c都有交流
6.5.4 读取资源文件
要使用Properties类
- 在java目录下新建properties
- 在resources目录下新建properties
项目运行后这两个properties都被打包到了一个路径下:classes,我们称这个路径为classpath
- 在resources目录下新建一个properties文件,填入如下内容
username=root
password=123456
- 实现一个PropertiesServlet类来读取资源。使用ServletContext对象的getResourceAsStream方法(方法参数需要填入资源所在位置的相对路径)获得一个文件流,然后通过Properties类进行加载就可以得到properties文件中存储的内容。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
resp.getWriter().println(properties.getProperty("username"));
resp.getWriter().println(properties.getProperty("password"));
}
- 在web.xml中进行注册和映射
<servlet>
<servlet-name>prop</servlet-name>
<servlet-class>com.example.servlet.PropertiesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>prop</servlet-name>
<url-pattern>/prop</url-pattern>
</servlet-mapping>
- 运行项目后使用浏览器访问http://localhost:8080/Servlet02_war/prop就会得到
root
123456
6.6 HttpServletResponse
- web服务器接收到客户端的http请求,会针对这个请求分别创建一个代表请求的HttpServletRequest对象和代表相应的HttpServletResponse对象。
- 若要获取客户端请求来的参数,就要使用HttpServletRequest
- 若要给客户端响应一些信息,就要使用HttpServletResponse
6.6.1 方法分类
负责向浏览器发送数据的方法 getOutputStream方法负责向浏览器写流,getWriter方法负责向浏览器写中文
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);
响应的状态码
public static final int SC_CONTINUE = 100;
public static final int SC_SWITCHING_PROTOCOLS = 101;
public static final int SC_OK = 200;
public static final int SC_CREATED = 201;
public static final int SC_ACCEPTED = 202;
public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
public static final int SC_NO_CONTENT = 204;
public static final int SC_RESET_CONTENT = 205;
public static final int SC_PARTIAL_CONTENT = 206;
public static final int SC_MULTIPLE_CHOICES = 300;
public static final int SC_MOVED_PERMANENTLY = 301;
public static final int SC_MOVED_TEMPORARILY = 302;
public static final int SC_FOUND = 302;
public static final int SC_SEE_OTHER = 303;
public static final int SC_NOT_MODIFIED = 304;
public static final int SC_USE_PROXY = 305;
public static final int SC_TEMPORARY_REDIRECT = 307;
public static final int SC_BAD_REQUEST = 400;
public static final int SC_UNAUTHORIZED = 401;
public static final int SC_PAYMENT_REQUIRED = 402;
public static final int SC_FORBIDDEN = 403;
public static final int SC_NOT_FOUND = 404;
public static final int SC_METHOD_NOT_ALLOWED = 405;
public static final int SC_NOT_ACCEPTABLE = 406;
public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
public static final int SC_REQUEST_TIMEOUT = 408;
public static final int SC_CONFLICT = 409;
public static final int SC_GONE = 410;
public static final int SC_LENGTH_REQUIRED = 411;
public static final int SC_PRECONDITION_FAILED = 412;
public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;
public static final int SC_REQUEST_URI_TOO_LONG = 414;
public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
public static final int SC_EXPECTATION_FAILED = 417;
public static final int SC_INTERNAL_SERVER_ERROR = 500;
public static final int SC_NOT_IMPLEMENTED = 501;
public static final int SC_BAD_GATEWAY = 502;
public static final int SC_SERVICE_UNAVAILABLE = 503;
public static final int SC_GATEWAY_TIMEOUT = 504;
public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
}
6.6.2 常见应用
- 向浏览器输出数据、信息
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
- 下载文件
- 获取下载文件的路径。之所以使用
"/WEB-INF/classes/t.jpg" 来获得文件的绝对路径,是因为项目运行后在target目录下的WEB-INF/classes中会生成图片文件。String realPath =this.getServletContext().getRealPath("/WEB-INF/classes/t.jpg");
System.out.println(realPath);
- 获取下载的文件名,路径下最后一个"/" 后面的一定是文件名
String filename = realPath.substring(realPath.lastIndexOf("//") + 1);
- 设置让浏览器能够支持下载我们需要的东西。设置响应头Content-Disposition,表示文件在浏览器中下载。使用URLEncoder.encode可以让中文文件名用UTF-8进行编码,解决在浏览器中的乱码问题。
resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename,"UTF-8"));
- 获取下载文件的输入流
FileInputStream fileInputStream = new FileInputStream(realPath);
- 创建缓冲区,通常使用一个1024长度的字节数组来充当缓冲区
int len=0;
byte[] buffer = new byte[1024];
- 获得OutputStream对象
ServletOutputStream outputStream = resp.getOutputStream();
- 将FileOutputStream写入到缓冲区(buffer),并且使用OutputStream将缓冲区中的数据输出到客户端
while((len=fileInputStream.read(buffer))>0){
outputStream.write(buffer,0,len);
}
- 关闭流
fileInputStream.close();
outputStream.close();
- 验证码功能
- 验证码怎么来的?
- 前端实现需要通过js来判断
- 后端实现,需要用到java的图片类,生成一个图片
- 首先实现一个随机数生成器
private String makeNum(){
Random random = new Random();
String num= String.valueOf(random.nextInt(9999));
StringBuffer stringBuffer = new StringBuffer();
for(int i=0;i<4-num.length();i++){
stringBuffer.append("0");
}
return stringBuffer.toString() + num;
}
- 在内存中生成一个图片并向图片写入随机数的数据
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = (Graphics2D)image.getGraphics();
graphics.setColor(Color.white);
graphics.fillRect(0,0,80,20);
graphics.setColor(Color.blue);
graphics.setFont(new Font(null,Font.BOLD,20));
graphics.drawString(makeNum(),0,20);
- 设置响应头,使得浏览器不缓存图片,最后将图片写到浏览器
resp.setHeader("refresh","3");
resp.setContentType("image/jpeg");
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
ImageIO.write(image, "jpg",resp.getOutputStream());
- 实现重定向
- 重定向:一个web资源受到客户端请求后,他会通知客户端去访问另一个web资源。
- 常见场景:用户登录
- 使用sendRedirect来实现重定向
void sendRedirect(String location) throws IOException;
- 我们以跳转至/image页面为例子,跳转的路径前面要加上项目名称“/HttpServletResponse_war”,否则会跳转失败
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/HttpServletResponse_war/image");
}
- 注册后再去访问http://localhost:8080/HttpServletResponse_war/redirect就会自动跳转到http://localhost:8080/HttpServletResponse_war/image页面。这时候url路径发生改变,与请求转发不同
- 上述的sendRedirect方法可以使用如下代码代替,效果一样
resp.setHeader("Location","/HttpServletResponse_war/image");
resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
- 面试题:重定向和转发的区别
- 相同点:页面都会跳转
- 不同点:请求转发时url不会发生变化;重定向时url地址栏会发生变化
6.7 HttpServletRequest
- HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器
- Http请求中的所有信息会被封装到HttpServletRequest,通过HttpServletRequest的方法,可以获得客户端的所有信息
6.7.1 获取前端传递的参数以及请求转发
- 首先需要引入jsp的依赖
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
- 用jsp实现登录页面和登录成功页面,模拟前端
- 登录页面,action="${pageContext.request.contextPath}/login"和method="post"代表以post方式提交表单,提交到web项目下的/login请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Login</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="hobby" value="打篮球">打篮球
<input type="checkbox" name="hobby"value="唱歌">唱歌
<input type="checkbox" name="hobby" value="电影">电影
<br>
<input type="submit">
</form>
</div>
</body>
</html>
- 登录成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>
- 实现一个LoginServlet类使用req.getParameter和req.getParameterValues方法来获得前端传来的参数,并使用req.getRequestDispatcher方法进行请求转发。
@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));
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
- 在web.xml中进行注册和映射
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.example.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
- 运行项目后访问http://localhost:8080/HttpServletRequest_war/就会进入登录页面,填入参数后点击提交按钮就会跳转到登录成功页面,且在控制台会输出用户名、密码和爱好。至此已经成功的从前端获得了参数并且进行了请求转发。
|