JavaWeb学习——Servlet学习(Reponse、Request)、转发和重定向的区别
1.Servlet简介
Servlet是sun公司提供的一门用于动态开发WEB资源的技术,sun(Sun Microsystems)公司创建于1982年,2009年4月20日被Oracle公司收购。
- 使用servlet技术步骤
- 1.编写好一个类,实现servlet接口
- 2.把开发好的Java类部署到WEB服务器中,通常我们把实现了servlet接口的Java程序,称为Servlet
2.Servlet运行过程
- ①Web服务器检查是否已经装在并创建了该Servlet的实例对象。如果装载了,直接执行第④步
- ②装载并创建Servlet实例对象
- ③调用Servlet实例对象的init()方法进行初始化
- ④创建一个用于封装HTTP请求消息的HttpServletResqurst对象和一个代表HTTP响应消息的HttpServletResponse对象。然后调用Servlet的service()方法向服务器发出请求,并将请求对象和响应对象作为参数传递进去
- ⑤WEB应用在程序被停止或重新启动之前,Servlet引擎卸载Servlet。并在卸载之前调用Sevlet的destroy()方法释放资源
过程图示:
Servlet调用图:
3.Servlet实现类
Servlet接口有两个默认实现类:GenericServlet和HttpServlet,我们把实现了Servlet接口的类都称之为Servlet
- GenericServlet
- GenericServlet是 Servlet 接口和 ServletConfig 接口的实现类. 但是一个抽象类. 其中的 service 方法为抽象方法
- 如果新建的 Servlet 程序直接继承 GenericSerlvet 会使开发更简洁
- 具体实现:
①. 在 GenericServlet 中声明了一个 SerlvetConfig 类型的成员变量, 在 init(ServletConfig) 方法中对其进行了初始化
②. 利用 servletConfig 成员变量的方法实现了 ServletConfig 接口的方法
③. 还定义了一个 init() 方法, 在 init(SerlvetConfig) 方法中对其进行调用, 子类可以直接覆盖 init() 在其中实现对 Servlet 的初始化.
④. 不建议直接覆盖 init(ServletConfig), 因为如果忘记编写 super.init(config); 而还是用了 SerlvetConfig 接口的方法,
则会出现空指针异常.
⑤. 新建的 init(){} 并非 Serlvet 的生命周期方法. 而 init(ServletConfig) 是生命周期相关的方法.
- HttpServlet
- HttpServlet是一个 Servlet, 继承自 GenericServlet. 针对于 HTTP 协议所定制.
- 在 service() 方法中直接把 ServletReuqest 和 ServletResponse 转为 HttpServletRequest 和 HttpServletResponse.
并调用了重载的 service(HttpServletRequest, HttpServletResponse)在service(HttpServletRequest, HttpServletResponse) 获取了请求方式: request.getMethod(). 根据请求方式有创建了doXxx() 方法(xxx 为具体的请求方式, 比如 doGet, doPost) - 实际开发中, 直接继承 HttpServlet, 并根据请求方式复写 doXxx() 方法即可.
- 好处: 直接由针对性的覆盖 doXxx() 方法; 直接使用 HttpServletRequest 和 HttpServletResponse, 不再需要强转.
4.使用IDEA开发Servlet
- ①新建WEB项目,并新建Servlet类
- 在项目目录下新建lib目录并将servlet的jar包导入
- 编写Servlet类,继承Httpservlet类,重写doGet和doPost方法
- 如果是post请求就在doPost方法里写代码,如果是get请求就在doGet方法里写代码.这里为了学习期间出错,我们在doGet请求里调用doPost方法
package com.muhan.servlet;
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 ServletTest01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//编写代码
}
}
- 配置web.xml
<servlet>
<!--
servlet-name:名称(任意,但必须与<servlet-mapping>中的servlet-name同名)
servlet-class:servlet类的路径(包名+类名)
-->
<servlet-name>ServletTest01</servlet-name>
<servlet-class>com.muhan.servlet.ServletTest01</servlet-class>
</servlet>
<!--
servlet-name:与<servlet>中的servlet-name同名即可
url-pattern:请求路径,格式为:/请求名
-->
<servlet-mapping>
<servlet-name>ServletTest01</servlet-name>
<url-pattern>/servlet.do</url-pattern>
</servlet-mapping>
- 当我们在网页上输入请求路径时是怎么知道是哪个Servlet呢:
- 从< servlet-mapping>的< url-pattern>:/servlet.do找到< servlet-mapping>的< servlet-name>:ServletTest01
- 再从< servlet-mapping>的< servlet-name>:ServletTest01找到< servlet>的< servlet-name>:ServletTest01
- 最后从< servlet>的:ServletTest01找到:com.muhan.servlet.ServletTest01
5.Servlet——Reponse
①重定向
重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它页面
- 新建info.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Hello Servlet</h1>
</body>
</html>
- 在servlet中写入重定向代码:
resp.sendRedirect("info.jsp");
重定向的参数为页面的路径,但是默认路径是在web目录下,如果该文件在web目录下,就可以省略前面的路径,直接写问文件名
- 测试
我们输入的是http://localhost:8080/WEB01/servlet.do但是却重定向到http://localhost:8080/WEB01/info.jsp页面去了
②ServletContext
ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
- 1).ServletContext的目的就是为了让资源之间共享数据,因为Servlet之间是不嫩直接承诺书数据的,所以要依靠ServletContext对象
- 2).案例:通过servletContext对象读取网站配置文件
- 在src下创建resources目录,并在目录下新建一个jdbc.properties文件
driver=com.mysql.jdbc.Driver
username=root
password=123456
url=jdbc:mysql://localhost:3306/smbms
- 编写Servlet
package com.muhan.servlet;
import javax.servlet.ServletException;
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.util.Properties;
public class ServletTest02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取配置文件路径
String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/resources/database.properties");
//2.新建Properties集合用来读取配置文件信息,Properties集合可以与流关联读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream(realPath));//将配置文件加载至集合
String driver = properties.getProperty("driver");//获取driver的值
String username = properties.getProperty("username");//获取username的值
String password = properties.getProperty("password");//获取password的值
String url = properties.getProperty("url");//获取url的值
//3.将获取到的值相应到网页
resp.getWriter().println(driver);
resp.getWriter().println(username);
resp.getWriter().println(password);
resp.getWriter().println(url);
}
}
```
- 配置web.xml
<servlet-mapping>
<servlet-name>ServletTest01</servlet-name>
<url-pattern>/servlet.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletTest02</servlet-name>
<url-pattern>/q1.do</url-pattern>
</servlet-mapping>
- 启动tomcat访问http://localhost:8080/WEB01/q1.do
③一些其他常用方法
- response.setHeader(“Refresh”, “2;url=http://www.baidu.com”);两秒钟自动跳转到百度,可以跳到自身页面,用于刷新,可以带参数,若不写参数三则是刷新自身网页
- resp.setContentType();设置响应类型,如:"image/jpg"为图片类型
- resp.setCharacterEncoding(“utf-8”);设置响应编码格式为utf-8
6.Servlet——Request
① 一些常用方法
req.getContextPath(); //获得web项目路径
req.getRequestURI(); //请求的URL路径
req.getRemoteUser(); //获得远程的用户名
req.getRequestedSessionId(); //获SessionId;
req.getServletPath(); //请求servlet的url
req.getLocalAddr(); //获得本地地址 防火墙
req.getLocalName(); //获得本地名字
req.getLocalPort(); //获得访问的端口号
获取的结果:
/WEB01
/WEB01/q2.do
null
921A65357F41059EC6156E08E0D054CD
/q2.do
0:0:0:0:0:0:0:1
0:0:0:0:0:0:0:1
8080
②Request对象接收前端用户提交的参数
- 写前端注册页面
- 表单提交方式get/post
- 表单提交的位置:服务器形目路径/servlet对应的请求url
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<%--
Form表单
action:代表要提交的路径,表单要提交到哪里 ,可以提交到一个Servlet
${pageContext.request.contextPath}为项目的路径名,
/q3.do是请求Servlet的url
method: 提交表单的方式
--%>
<h1>注册</h1>
<form action="${pageContext.request.contextPath}/q3.do" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit">
<input type="reset"><br>
</form>
</body>
</html>
- 写处理前端请求的Servlet
package com.muhan.servlet;
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 ServleTest04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求和响应字符编码
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("utf-8");
//req.getParameter("控件的name");获取控件传来的值
String username = req.getParameter("username");
String password = req.getParameter("password");
//模拟匹配数据库
if (username.equals("张三")&&password.equals("123456")){
System.out.println("登陆成功,转到成功页面");
}else {
System.out.println("登陆失败,提示用户重新注册");
}
//打印一下从前端取来的数据,看是否取到
System.out.println(username);
System.out.println(password);
}
}
- 配置web.xml
<servlet>
<servletname>ServletTest04</servlet-name>
<servletclass>com.muhan.servlet.ServleTest04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletTest01</servlet-name>
<url-pattern>/servlet.do</url-pattern>
</servlet-mapping>
- 测试
- 看后台打印结果
登陆成功,转到成功页面
张三
123456
③Request实现请求转发
- 前端页面1
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<h1>注册</h1>
<form action="${pageContext.request.contextPath}/q4.do" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit">
<input type="reset"><br>
</form>
</body>
</html>
- 前端页面2
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Success!!!</h1>
</body>
</html>
- servlet代码
package com.muhan.servlet;
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 ServletTest05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//转发到成功页面
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
}
- web.xml配置
<servlet>
<servlet-name>ServletTest05</servlet-name>
<servlet-class>com.muhan.servlet.ServletTest05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletTest05</servlet-name>
<url-pattern>/q4.do</url-pattern>
</servlet-mapping>
- 测试
7.转发和重定向的区别
- 重定向:服务器告诉客户端,你去请求另一个地址.
- 属于客户端行为
- resp.sendRedirect();响应的方法
- 地址栏会变
- 不可以携带参数
- 转发:服务器自己转发到另一个请求
- 属于服务器行为
- req.getRequestDispatcher().forward(req,resp);请求的方法
- 地址栏不会变
- 可以携带参数