Servlet学习总结(上)
前言在学习JavaWeb过程中学到了Servlet,为了方便自己以后巩固,先对自己已学的知识进行回顾总结1.Servlet技术1.1什么是ServletServlet是JavaEE规范之一,规范就是接口Servlet是JavaWeb三大组件之一。三大组件分别是:Servlet程序、Filter过滤器、Listener监听器。Servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过
前言
在学习JavaWeb过程中学到了Servlet,为了方便自己以后巩固,先对自己已学的知识进行回顾总结
Servlet技术
1. 了解Servlet
1.1什么是Servlet
- Servlet是JavaEE规范之一,规范就是接口
- Servlet是JavaWeb三大组件之一。三大组件分别是:Servlet程序、Filter过滤器、Listener监听器。
- Servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过来的请求,并相应数据给客户端
1.2手动实现Servlet程序
- 编写一个类去继承HttpServlet(常用方式)
- 重写service方法,处理请求,相应数据
- 到web.xml中去配置Servlet程序的访问地址
简单的Servlet程序
public class HelloServlet extends HttpServlet {
private String message;
public HelloServlet() {
System.out.println("默认构造方法被执行");
}
//初始化方法
public void init() {
message = "Hello World!";
System.out.println("init 方法被执行");
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("service 方法被执行");
HttpServletRequest hsr = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
doGet(hsr, response);
}
//当浏览器的请求方式为get时执行doGet方法
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
// Hello
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>" + message + "</h1>");
out.println("</body></html>");
}
//销毁创建的Servlet对象,释放占用资源
public void destroy() {
System.out.println("destroy 方法被执行");
}
}
web.xml的配置信息
<!--servlet标签给Tomcat配置Servlet程序-->
<servlet>
<!--为Servlet程序起一个别名(一般是类名)-->
<servlet-name>HelloServlet</servlet-name>
<!--Servlet程序的全类名-->
<servlet-class>com.example.demo.HelloServlet</servlet-class>
</servlet>
<!--servlet-mapping标签给Servlet程序配置访问地址-->
<servlet-mapping>
<!--告诉服务器,我当前配置的地址给哪个Servlet程序使用-->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern 标签配置访问地址
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
-->
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
在浏览器上输入URL地址访问Servlet程序过程
1.3Servlet生命周期
所有的servlet类都必须实现Servlet接口,其中定义了三个方法:
- init方法:负责初始化Servlet对象
- service方法:用于响应客户端的请求
- destory方法:销毁servlet对象,释放占用的资源
servlet生命周期四个阶段:
- 加载阶段:加载并实例化(创建Servlet实例)
- 初始化阶段:调用init方法,根据web.xml文件中的信息创建ServletConfig对象并传给init
- 响应客户端请求:调用service和对应的doGet或doPost,服务器根据用户请求创建ServletRequest和ServletResponse对象并传给service
- 终止阶段:调用destory方法,销毁创建的Servlet对象
2. ServletConfig
2.1 什么是ServletConfig类
- ServletConfig类,从类名上看是Servlet程序的配置信息类
- Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用
- Servlet程序默认第一次访问的时候创建,Servlet是每个Servlet程序创建时,就创建一个ServletConfig对象。
2.2 ServletConfig类的三大作用
- 可以获取Servlet程序的别名servlet-name的值
- 获取初始化参数init-param
- 获取ServletContext对象
web.xml文件中的配置
代码示例
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);//必须调用父类的init,以便把子类的ServletConfig对象传递过去
String url = config.getInitParameter("url");
String user = config.getInitParameter("user");
System.out.println("ServletConfig 被调用");
System.out.println("url = "+url);
System.out.println("user = "+user);
}
注意
当子类中未调用super.init(config)时,在子类的doGet方法中调用getServletConfig()时,浏览器访问Servlet程序会出错
我们通过查看父类GenericServlet
可见我们要在子类中获得ServletConfig对象,必须在初始化时将config通过super.init(config)传递给父类
输出结果
可以看到通过ServletConfig对象成功获得了init方法中配置的初始化参数(仅对单个Servlet程序有效,因为我们配置的init初始化参数就在web.xml的servlet配置信息中)
3. ServletContext
3.1 什么是ServletContext
- ServletContext是一个接口,它表示Servlet上下文对象,作用域是整个web工程下的所有Servlet程序
- 一个web工程,只有一个ServletContext对象实例
- Servlet对象是一个域对象
- ServletContext是在web工程启动的时候启动的时候创建,在web工程停止的时候销毁。
3.2 域对象
域对象就是可以像Map一样存取数据的对象,这里的域指的是存取数据的操作范围,整个web工程
- setAttribute(),存数据
- getAttribute(),取数据
- removeAttribute(),删除数据
3.3 ServletContext的作用
- 获取web.xml中配置的上下文参数 context-param
- 获取当前的工程路径,格式:/工程路径
- 获取工程部署后在服务器硬盘上的绝对路径
- 像map一样存取数据
代码演示
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletContext context = getServletConfig().getServletContext();
ServletConfig config = getServletConfig();
ServletContext context = config.getServletContext();
//获取web.xml文件中配置的context-param参数的值
String username = context.getInitParameter("username");
System.out.println(username);
//获取当前的工程路径 格式:/工程路径
String contextPath = context.getContextPath();
System.out.println("当前项目的工程路径为:"+contextPath);
//获取工程部署后在服务器硬盘上的绝对路径
/**
* / 斜杠被服务器解析地址为:http:ip:port/工程名/ 映射到idea代码的web目录
*/
String realPath = context.getRealPath("/");
System.out.println("web工程的绝对路径:"+realPath);
}
web.xml配置
结果展示
像map一样存取数据
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = getServletContext();
Object name = context.getAttribute("name");
System.out.println("保存之前context获得的name的值:"+name);
context.setAttribute("name", "zjx");
Object name1 = context.getAttribute("name");
System.out.println("name1 -- "+name1);
/**
* getInitParameter(String name)
* 获取整个web工程的web.xml文件中名字叫做name的值
*
* getAttribute(String key)
* 获取整个web工程中key对应的value值
*/
String username = context.getInitParameter("username");
System.out.println(username);
}
结果输出
4.HttpServletRequest类
4.1 HttpServletRequest类有什么作用
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的Http协议信息解析好封装到Request对象中。然后传递到service方法中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息。
4.2 HttpServletRequest类的常用方法
i. getRequestURI() 获取请求的资源路径
ii. getRequestURL() 获取请求的统一资源定位符(绝对路径)
iii. getRemoteHost() 获取客户端的 ip 地址
iv. getHeader() 获取请求头
v. getParameter() 获取请求的参数
vi. getParameterValues() 获取请求的参数(多个值的时候使用)
vii. getMethod() 获取请求的方式 GET 或 POST
viii. setAttribute(key, value); 设置域数据
ix. getAttribute(key); 获取域数据
x. getRequestDispatcher() 获取请求转发对象
代码示例
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的资源路径
String requestURI = req.getRequestURI();
System.out.println("请求的资源路径:"+requestURI);
//获取请求的统一资源定位符
StringBuffer requestURL = req.getRequestURL();
System.out.println("请求的统一资源定位符(绝对路径)"+requestURL);
//获取客户端的ip地址
String ip = req.getRemoteHost();
System.out.println("客户端IP地址:"+ip);
//获取请求头
String userAgent = req.getHeader("User-Agent");
System.out.println("请求头中user-Agent的信息:"+userAgent);
获取请求的参数
//String username = req.getParameter("username");
//System.out.println("请求参数为username的值:"+username);
获取请求转发对
//req.getRequestDispatcher()
}
输出结果
4.3 获取客户端请求参数
HTML代码部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>form表单</title>
</head>
<body>
<form action="http://localhost:8080/demo_war_exploded/getParameter" method="get">
用户名:<input type="text" value="请输入用户名" name="username"/><br/>
密码:<input type="password" name="password" /><br/>
<input type="checkbox" name="hobby" value="java">Java
<input type="checkbox" name="hobby" value="cpp">C++
<input type="checkbox" name="hobby" value="php">php
<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
Servlet代码部分
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* 获取客户端发送过来的数据信息
*/
//获取表单中name属性为username的数据信息
String username = req.getParameter("username");
//获取表单中name属性为password的数据信息
String password = req.getParameter("password");
//获取表单中name属性为hobby的数据信息,不止一个
String[] hobbies = req.getParameterValues("hobby");
System.out.println("用户名 = "+username);
System.out.println("密码 = "+password);
System.out.println("爱好:");
//java8以流的方式打印数据
Arrays.stream(hobbies).forEach(System.out::println);
}
结果演示
4.4 请求转发
请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发
转发流程
代码演示
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet1程序被执行");
//1.获取请求参数(来办业务那我要看看你是否有材料)
String username = req.getParameter("username");
System.out.println("username = "+username);
//2.敲个章,证明来过一程序办理了业务
req.setAttribute("key", "value");
//3.指明下个办理业务地点
RequestDispatcher dispatcher = req.getRequestDispatcher("/servlet2");//requestDispatcher--请求调度
//4.前去下个业务地点
dispatcher.forward(req, resp);
}
}
------------------------------------------------------------------
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet2程序被执行");
//1.获取请求参数,既然来办业务看看你带材料了没
String username = req.getParameter("username");
System.out.println("username------"+username);
//2.检查业务一是否办理完
Object key = req.getAttribute("key");
//3.开始办理自己业务
System.out.println("业务二办理");
}
}
输出结果
可以看出当访问Servlet1程序时,会紧接着访问Servlet2程序
4.5 base标签的作用
设置当前页中所有相对路径工作时,参照哪个路径来进行跳转
我们通过案例来学习base标签的使用
1.在web工程首页添加form表单的html地址的链接
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title>JSP - Hello World(首页)</title>
</head>
<body>
<h1>
<%= "Hello World!" %>
</h1>
<br/>
<a href="hello-servlet">Hello Servlet</a>
<br/>
<a href="html/form.html">链接到form.html</a>
</body>
</html>
然后在表单中添加首页的链接
<a href="../">回到首页</a>
当我们使用请求转发先访问Servlet3程序,然后转发到form.html然后再点击回到首页会发现出错了
public class Servlet3 extends HttpServlet {
//转发请求到form表单页面
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/html/form.html").forward(req, resp);
}
点击回到首页
现在我们来分析一下出现这种情况的原因
首先我们要知道所有相对路径在工作时都会参照当前浏览器地址栏中的地址来进行跳转。
也就是说当我们访问Servlet程序时,浏览器地址栏为
我们的form.html中超链接写的是<a hret="…/">,然后根据地址栏中返回上级目录得到地址http://localhost:8080/demo_war_exploded/servlet3, servlet3不是目录故不需要考虑,我们首页的正确地址是:http://localhost:8080/demo_war_exploded/,so就出现404啦
解决方案
在form.html中的head标签里使用base标签
<head>
<meta charset="UTF-8">
<title>form表单</title>
<!--base标签设置页面相对路径工作时参照的地址
href属性就是参照的地址值
-->
<base href="http://localhost:8080/demo_war_exploded/html/form.html">
</head>
这样程序在对相对路径进行处理时就会使用base标签设置的地址进行处理
4.6 web中 / 斜杠的不同意义
- 在web中 / 斜杠是一种绝对路径
- / 斜杠 如果被浏览器解析,得到的地址是: http://ip:port/
<a hret="/">斜杠<a> - / 斜杠如果被服务器解析,得到的地址是:http://ip/port/工程路径
- <url-pattern>/servlet1</url-pattern>
- servletContext.getRealPath("/")
- request.getRequestDispatcher("/")
**特殊情况:response.sendRediect("/"); 会把/发送给浏览器进行解析,得到:http://ip/port/
更多推荐
所有评论(0)