目录
Servlet的介绍
Servlet的生命周期
Service和doGet和doPost方法的区别
Request对象
Respose对象
请求乱码解决
请求转发:
Request对象作用域
重定向
Cookie
Session
ServletContext
ServletConfig
web.xml文件
Serve.xml文件
一位大佬的博客:https://www.cnblogs.com/fjdingsd/
问题:服务器在接受到浏览器请求后,他会自动调用对应的逻辑代码进行请求处理,但是逻辑代码是由程序员编写并放在浏览器里面的,那么服务器怎么知道该怎么调用并调用哪个类或者方法来进行请求的处理?
解决:程序员在编写逻辑代码时候按照浏览器能够识别的规则进行编写,浏览器会按照指定的规制进行发送请求,那么服务器就可以调用并响应逻辑代码来处理请求;
实现:Servlet技术
概念:狭义的 Servlet 是指 Java 语言实现的一个接口,广义的 Servlet 是指 任何实现了这个 Servlet 接口的类,一般情况下,人们将 Servlet 理解为后者。 Servlet 运行于支持 Java 的应用服务器中。从原理上讲,Servlet 可以响应任何 类型的请求,但绝大多数情况下 Servlet 只用来扩展基于 HTTP 协议的 Web 服 务器
特点:
使用:
运行流程:
url:http://localhost:8080/project/my2
组成: 服务器地址:端口号/虚拟项目名 /servlet的别名
uri:虚拟项目名 /servlet的别名
浏览器发送请求到服务器,服务器根据请求URL地址 中的URI信息在webapps目录下找到对应的项目文件夹, 然后在web.xml中检索对应的servlet,找到后调用并执行 Servlet。
从第一次调用,到服务器关闭。如果在web.xml 中配置了load-on-startup则是从服务器开启到服务器关闭。
package com.bjsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet的生命周期:
* 1、从第一次调用到服务器关闭。
* 2、如果Servlet在web.xml中配置了load-on-startup(里面的数组为初始化的次序),生命周期为
从服务器启动到服务器关闭
* 注意:
* init方法是对Servlet进行初始化的一个方法,会在Servlet第一次
加载进行存储时执行
* destory方法是在servlet被销毁时执行,也就服务器关闭时。
*
*/
public class ServletLife extends HttpServlet {
//初始化方法,在servlet第一次加载内容的时候被调用
@Override
public void init() throws ServletException {
System.out.println("servlet初始化完成");
}
//service方法,真正处理请求的方法
@Override
protected void service(HttpServletRequest req,HttpServletResponse resp)throwsServletException, IOException {
resp.getWriter().write("servlet life");
System.out.println("servlet life");
}
@Override
public void destroy() {
System.out.println("我被销毁了...");
}
}
web.xml设置
This is the description of my J2EE
component
This is the display name of my J2EE
component
ServletLife
com.bjsxt.servlet.ServletLife
1
my
/my
ServletLife
/life
Service的常见错误总结
注意:如果Service的方法中调用了父类的Service方法(super.service(arg0,arg1))Service处理玩后会根据请求方式响应的doGet方法和doPost方法执行,所以一般情况下,我们不在覆写 Service方法中调用父类的Service方法,避免405错误
package com.servlet.one;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption : Service方法和doGet和doPost的区别
* @date :2019-3-26 下午8:21:38
* @author :田坤
*/
public class One extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("我的全面的");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("我可以执行get方法");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("我可以执行post方法");
}
}
问题: 浏览器发起请求到服务器,会遵循HTTP协议将请求数据发送给服务器。 那么服务器接受到请求的数据改怎么存储呢?不但要存,而且要保证完成性。
解决: 使用对象进行存储,服务器每接受一个请求,就创建一个对象专门的存 储此次请求的请求数据。
实现:Request对象
解释:服务器接收到浏览器的请求后,会创建一个Request对象,对象中 存储了此次请求相关的请求数据。服务器在调用Servlet时会将创建的 Request对象作为实参传递给Servlet的方法,比如:service方法。
使用:获取请求头数据 、获取请求行数据 、 获取用户数据
package com.servlet.one;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :Request对象获取数据
* @date :2019-3-26 下午9:16:19
* @author :田坤
*/
public class Request extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 获取请求头数据:
System.out.println("获取请求头数据:");
// 获取请求方法
System.out.println(req.getMethod());
// 获取请求的URL
System.out.println(req.getRequestURL());
// 获取请求的URI
System.out.println(req.getRequestURI());
// 获取请求的协议
System.out.println(req.getScheme());
// 获取请求行数据
System.out.println("获取请求行数据:");
// 获取指定的请求行信息
System.out.println(req.getHeader("User-Agent"));
// 获取所有请求行的键的枚举
Enumeration e = req.getHeaderNames();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
String value = req.getHeader(name);
System.out.println(name + ":" + value);
}
// 获取用户信息
System.out.println("获取用户信息");
String name = req.getParameter("num");
String password = req.getParameter("pwd");
System.out.println(name + "--" + password);
//req.getParameterValues(“键名”) 返回同键不同值的请求数据(多选),返回的数组
//req.getParameterNames(); 返回所有用户请求数据的枚举集合
}
}
获取请求头数据:
POST
http://localhost:8080/newproject/Request
/newproject/Request
http
获取请求行数据:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
host:localhost:8080
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
accept-language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
accept-encoding:gzip, deflate
referer:http://localhost:8080/newproject/MyJsp.jsp
content-type:application/x-www-form-urlencoded
content-length:25
connection:keep-alive
cookie:JSESSIONID=70AB1304971FF438296871CCD774DD00; Pycharm-ab6eb338=0f1c29eb-c033-404f-905f-73964fbc2665; Pycharm-134fe017=6a4fd521-686f-4450-a917-d0124760806b
upgrade-insecure-requests:1
获取用户信息
songxudong--111111
注意:如果获取的数据不存在,不会报错,返回的是NULL
问题: 在使用Request对象获取了请求数据并进行处理后,处理的结果如何显 示到浏览器中呢?
解决:使用Response对象
解释: 服务器在调用指定的Servlet进行请求处理的时候,会给Servlet的方 法传递两个实参request和response。其中request中封存了请求相关的 请求数据,而response则是用来进行响应的一个对象。
使用: 设置响应头 、设置响应编码格式、置响应实体
package com.servlet.one;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Desciption :Respose的使用
* @date :2019-3-26 下午10:34:52
* @author :田坤
*/
public class Respose extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 相应处理结果
// 设置响应头
resp.addHeader("mouse", "mumaren");
resp.setHeader("keyboard", "mumaren"); // set和add add可以重复加,set会覆盖
// 设置响应编码格式
// resp.setHeader("content-type", "text/html;charset=utf-8");
resp.setContentType("text/html;charset=utf-8");
// 设置响应码的状态
// resp.sendError(405, "nou found!");
resp.getWriter().write("Respose!");
}
}
Service请求处理代码流程:
关于MIME类型(Multipurpose Internet Mail Extensions)
Servlet流程总结:
数据流转流程:
浏览器——>服务器——>数据库——>服务器——>浏览器
问题:使用请求转发后,不同的 Servlet 之间怎么进行数据的共享呢?或者说数据怎么从一个 servlet 流转给另外一个 Servlet 呢?
解决:使用 request 对象的作用域
使用: request.setAttribute(objectname,Objectvalue);
request.getAttribute(Objectobj)
作用:解决了一次请求内的不同 Servlet 的数据(请求数据+其他数据)共享问题。
作用域: 基于请求转发,一次请求中所有的servlet共享(一个给一个)
注意:使用request对象进行数据流转,数据只能在一次请求中有效(一个请求一个request)
特点:服务器创建的、每次请求都会创建、生命周期是一个请求
package com.servlet.two;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.service.LoginService;
import com.service.impl.LoginServiceImpl;
/**
*
* @Desciption :servlet处理登录请求 Login的相对路径为 login
* @date :2019-3-27 下午4:35:06
* @author :田坤
*/
public class Login extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
// 设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
// 获取请求信息
String id = req.getParameter("uname");
String password = req.getParameter("pwd");
// String pwd = new String(password.getBytes("iso8859-1"), "utf-8");
System.out.println(id + "--" + password);
// 处理请求信息(操作数据库)
// 获取业务层对象:
LoginService ls = new LoginServiceImpl();
User u = ls.checkLoginService(Integer.valueOf(id), password);
if (u != null) {
resp.getWriter().write("成功");
} else {
// 使用request对象实现不同servlet的数据流转
req.setAttribute("str", "账号或者密码输入错误");
// 使用请求转发
req.getRequestDispatcher("page1").forward(req, resp);
return;
}
}
}
package com.servlet.two;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :响应出登录的页面
* @date :2019-3-27 下午4:55:25
* @author :田坤
*/
public class PageServlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
// 获取请求信息
// 处理请求
// 响应处理结果
// 获取request对象作用域
String str = (String) (req.getAttribute("str") == null ? "" : req
.getAttribute("str"));
resp.getWriter().write("");
resp.getWriter().write("");
resp.getWriter().write("");
resp.getWriter().write("");
resp.getWriter().write(
"" + str + "");
resp.getWriter().write("");
resp.getWriter().write("");
resp.getWriter().write("");
}
}
解决了表单重复提交的问题,以及当前servlet无法处理的请求问题
用法:resp.sendRedirect("路径"); 本地路径为:URI 、网路路径为:定向资源的URL信息
特点:俩次请求,俩个request对象、浏览器地址栏信息改变
时机:
解释:Cookie 技术其实是浏览器端的数据存储技术,解决了不同请求需要使用相同的请求数据的问题。我们把请求需要共享的请求数据,存储在浏览器端,避免用户进行重复的书写请求数据。但是哪些数据需要使用 Cookie 技术存储起来是一个主观问题,需要在后台进行响应的时候来告诉浏览器,有些数据其他请求还会使用,需要存储起来。
作用:解决了发送的不同请求的数据共享问题
使用:
注意:一个cookie只能存储一条数据
特点:
package com.cookie.one;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :创建和设置Cookie
* @date :2019-3-27 下午6:34:05
* @author :田坤
*/
public class CookieServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 请求对象编码格式
req.setCharacterEncoding("utf-8");
// 响应对象编码格式
resp.setContentType("text/html;charset=utf-8");
//获取请求信息
//处理请求信息
//响应处理结果
//使用Cookie进行浏览器的存储
//创建对象
Cookie c = new Cookie("nan", "huge") ;
Cookie c1 = new Cookie("nv", "liushishi");
//设置Cookie
//设置Cookie的有效期
c1.setMaxAge(3*24*3600); //3天
//设置Cookie的有效路径
c1.setPath("/Cookie/gcs"); //只在此路径下可可以附带Cookie信息
//响应Cookie信息
resp.addCookie(c); //临时存储
resp.addCookie(c1); //定时存储
//直接响应
//请求响应
//重定向
}
}
package com.cookie.one;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :获取Cookie
* @date :2019-3-27 下午7:40:02
* @author :田坤
*/
public class GetCookies extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//获取请求信息
//获取Cookie信息
Cookie[] cookie = req.getCookies();
String name = ""; //cookie的键名
String value = ""; //cookie的值
if(cookie != null){
for(Cookie c:cookie){
name = c.getName();
value = c.getValue();
System.out.println(name+" : "+value);
}
}
}
}
问题:Request 对象解决了一次请求内的不同 Servlet 的数据共享问 题,那么一个用户的不同请求的处理需要使用相同的数据怎么办呢?
解决:使用Session技术
原理:用户使用浏览器第一次向服务器发送请求,服务器在接受到请求后,调用对应的 Servlet 进行处理。在处理过程中会给用户创建 一个 session 对象,用来存储用户请求处理相关的公共数据,并将 此 session 对象的 JSESSIONID 以 Cookie 的形式存储在浏览器中 (临时存储,浏览器关闭即失效)。用户在发起第二次请求及后续请 求时,请求信息中会附带 JSESSIONID,服务器在接收到请求后, 调用对应的 Servlet 进行请求处理,同时根据 JSESSIONID 返回其 对应的 session 对象。
特点:
作用:解决一个用户不同请求的数据共享问题
使用:
/**
*
* @Desciption :Session的使用
* @date :2019-3-27 下午11:32:07
* @author :田坤
*/
public class SessionServlet1 extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//请求信息编码格式
req.setCharacterEncoding("utf-8");
//响应信息编码格式
resp.setContentType("text/html;charset=utf-8");
//获取请求信息
String name = "田坤";
//处理请求信息
//创建Session对象
HttpSession hs = req.getSession();
//设置Session生存时间(默认30分钟)
// hs.setMaxInactiveInterval(5); //设置存储时间为5秒
//Session销毁
// hs.invalidate();
//响应处理结果
//加入Session数据
hs.setAttribute("name", name);
//输出JSESSIONID
System.out.println(hs.getId());
//直接响应
resp.getWriter().write("Session学习");
}
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
HttpSession hs = req.getSession();
String name = (String) hs.getAttribute("name");
//获取JSESSIONID
String sessionid = "";
Cookie[] ck = req.getCookies();
for(Cookie c : ck){
if(c.getName().equals("JSESSIONID"))
sessionid = c.getValue();
}
if(sessionid.equals(hs.getId())){
System.out.println(sessionid);
System.out.println(hs.getId());
resp.getWriter().write("俩个Session是同一个Session");
}
}
除了可以用hs.setMaxInactiveInterval(int seconds)的方法还可以在Tomcat的web.xml的公共属性session-config标签进行修改,但不推荐这样修改
30
问题:不同用户使用相同的对象
作用:解决了不同用户的数据共享问题
原理:ServletContext 对象由服务器进行创建,一个项目只有一个对象。不管在项目的任意位置进行获取得到的都是同一个对象,那么不同用户发起的请求获取到的也就是同一个对象了,该对象由用户共同拥有。
特点:服务器创建、用户共享、一个项目一个ServletContext
作用域:一个项目
生命周期:一个项目开始到一个项目结束
使用:
package com.servlet.one;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption : ServletContext的使用
* @date :2019-3-28 下午8:57:58
* @author :田坤
*/
public class ServletContext1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
// 獲取ServletContext对象
// 第一种方式
ServletContext sc = this.getServletContext();
// 第二种方式
ServletContext sc1 = this.getServletConfig().getServletContext();
// 第三种方式
ServletContext sc2 = req.getSession().getServletContext();
ServletContext sc3 = req.getServletContext();
System.out.println(sc == sc1);
System.out.println(sc == sc2);
System.out.println(sc == sc3);
// 使用ServletContext完成数据的共享
// 存储数据
sc.setAttribute("name", "我爱学习");
// 获取项目web.xml的全局配置数据
String data = sc.getInitParameter("name");
System.out.println("全局配置参数" + data);
// 获取项目根路径下的资源的绝对路径
// String path =
// " C:/Program Files/Apache Software Foundation/Tomcat 7.0/webapps/ServletContext/META-INF/1.txt";
String path = sc.getRealPath("1.txt");
System.out.println(path);
// 获得项目目录下的资源的流对象
InputStream is = sc.getResourceAsStream("1.txt");
}
}
package com.servlet.one;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletContext2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
ServletContext sc = this.getServletContext();
String name = (String) sc.getAttribute("name");
System.out.println(name);
}
}
true
true
true
全局配置参数tiankun
C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\ServletContext\1.txt
我爱学习
问题:使用ServletContext对象可以获取web.xml中的全局配置文件,在 web.xml 中每个 Servlet 也可以进行单独的配置,那么该怎么获取配置信息呢?
作用:ServletConfig 对象是 Servlet 的专属配置对象,每个 Servlet 都单独拥有一个 ServletConfig 对象,用来获取 web.xml 中的配置信
息。
使用:获取 ServletConfig 对象、获取 web.xml 中 servlet 的配置信息
This is the description of my J2EE component
This is the display name of my J2EE component
ServletConfigServlet
com.servlet.one.ServletConfigServlet
code
utf-8
package com.servlet.one;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Desciption :ServletConfig学习
* @date :2019-3-29 下午1:45:10
* @author :田坤
*/
public class ServletConfigServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
ServletConfig sc = this.getServletConfig();
// 获取在web.xml中写的局部变量
String code = sc.getInitParameter("code");
System.out.println(code);
}
}
作用:存储项目的相关的配置信息,保护Servlet,解耦一些数据对程序的依赖。
使用位置:
内容(核心组件)
加载顺序:Web 容器会按 ServletContext -> context-param -> listener ->filter-> servlet 这个顺序加载组件,这些元素可配置在 web.xml
文件中的任意位置。
加载时机:服务器启动时。
问题:浏览器发起请求后,服务器根据请求在 webapps 目下调用对应的 Servlet 进行请求处理。那么为什么是 webapps 目录难道不能是
其他的目录吗?
解决:了解 server.xml 文件的配置信息
Server.xml 文件核心组件:
热部署:
只要文件有修改就可以直接部署在服务器上,而我们正常使用的是冷部署,只要在启动服务器后才可以将修改的文件部署到服务器上