目录
Servlet的原理
Servlet调用过程
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
客户端输入url访问服务器
服务器解析输入的url解析到访问servle的资源路径
服务器根据解析到的资源路径,在web.xml文件里面找到对应的< url-pattenr >,如果有,同时找到servlet名称
根据servlet名称找到对应的servlet类
服务器自动创建servlet 类的对象,调用其中的方法
Servlet的生命周期
- 1、Servlet的生命周期由Servlet容器(如:Tomcat)控制
容器如何处理请求:
- 2、生命周期的各个阶段
初始化和销毁在一个生命周期中只能发生一次。服务可以多次调用。
实例代码:
package com.mytext.servlet;
import jakarta.servlet.*;
import java.io.IOException;
public class Servletlife implements Servlet{
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("初始化init");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("服务service");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("停止");
}
}
当我们访问网页时,服务器端会给我们回显:
ServletConfig接口
在运行 Servlet 程序时,可能需要一些辅助信息,例如,文件使用的编码、使用 Servlet 程序的共享信息等,这些信息可以在 web.xml 文件中使用一个或多个 <init-param> 元素进行配置。当 Tomcat 初始化一个 Servlet 时,会将该 Servlet 的配置信息封装到 ServletConfig 对象中,此时可以通过调用 init(ServletConfig config)方法将 ServletConfig 对象传递给 Servlet。
ServletConfig 接口中定义了一系列获取配置信息的方法,如表 1 所示
下面以 getInitParameter() 方法为例,分步骤讲解该方法的使用。
- 1)创建Servlet
在 com.mytext.servlet 包中创建一个名称为 servletconfig 的 Servlet 类,并在类中编写用于读取 web.xml 文件中参数信息的代码,如下所示。
package com.mytext.servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
public class servletconfig extends HttpServlet {
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletConfig config = this.getServletConfig();
String whoami = ((ServletConfig) config).getInitParameter("name");
out.println("I'm " + whoami);
}
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- 2)配置参数信息
在web.xml中加入:
<servlet>
<servlet-name>servletconfig</servlet-name>
<servlet-class>com.mytext.servlet.servletconfig</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>yourfather</param-value>
</init-param>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>servletconfig</servlet-name>
<url-pattern>/servletconfig</url-pattern>
</servlet-mapping>
- 3)运行项目并查看结果
访问http://localhost:8080/hello_war_exploded/servletconfig
可以看出,web.xml 文件中为 servletconfig 配置的编码信息被读取了出来。由此可见,通过 ServletConfig 对象可以获得 web.xml 文件中的参数信息。
ServletContext接口
当 Tomcat 启动时,Tomcat 会为每个 Web 应用创建一个唯一的 ServletContext 对象代表当前的 Web 应用,该对象封装了当前 Web 应用的所有信息。可以利用该对象获取 Web 应用程序的初始化信息、读取资源文件等。下面对 ServletContext 接口的不同作用分别进行讲解。
1. 获取 Web 应用程序的初始化参数
在 web.xml 文件中,不仅可以配置 Servlet 的映射信息,还可以配置整个 Web 应用的初始化信息。Web 应用初始化参数的配置方式具体如下所示:
<context-param>
<param-name>namecnm</param-name>
<param-value>cnm</param-value>
</context-param>
<context-param>
<param-name>way</param-name>
<param-value>23333</param-value>
</context-param>
package com.mytext.servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class servletcontext extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
ServletContext context= (ServletContext) this.getServletContext();
String name=(String) context.getInitParameter("namecnm");
res.setContentType("text/html");
res.setCharacterEncoding("utf-8");
res.getWriter().print("name:"+name);
res.getWriter().print("<br>");
}
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
2、共享数据
这里的域指的是存取数据的操作范围,整个 web 工程。
域对象
存数据:setAttribute()
取数据:getAttribute()
删除数据:removeAttribute()
我在这个Servlet中保存的数据,可以在另外一个servlet中拿到;
setservlet.java
package com.mytext.servlet;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class setservlet extends HttpServlet {
protected void doGet(HttpServletRequest req , HttpServletResponse res) throws IOException
{
ServletContext context=this.getServletContext();
String username= "landasika";
context.setAttribute("user",username);//将user保存在context中,他的值是username
}
}
package com.mytext.servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.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 name=(String) context.getAttribute("user");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("father name:" + name);
}
}
<servlet>
<servlet-name>getservlet</servlet-name>
<servlet-class>com.mytext.servlet.getservlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>getservlet</servlet-name>
<url-pattern>/getservlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>setservlet</servlet-name>
<servlet-class>com.mytext.servlet.setservlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>setservlet</servlet-name>
<url-pattern>/setservlet</url-pattern>
</servlet-mapping>
测试访问结果;
3、请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo04");
//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
//requestDispatcher.forward(req,resp); //调用forward实现请求转发;
context.getRequestDispatcher("/gp").forward(req,resp);
}
4、读取资源文件
Properties
- 在java目录下新建properties
- 在resources目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath:
思路:需要一个文件流;
username=root12312
password=zxczxczxc
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/kuang/servlet/aa.properties");
Properties prop = new Properties();
prop.load(is);
String user = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
访问测试即可ok;
HttpServletRequest类
转自:https://blog.csdn.net/chenxingxingxing/article/details/123121800
1. HttpServletRequest类
每次只要有请求进入Tomcat服务器,Tomcat服务器会把请求过来的HTTP协议信息解析好封装到Request对象中,然后传递到service(doGet或doPost)方法中供我们使用。然后可以通过HttpServletRequest对象获取所有的请求信息。
servlet代码:
public class HttpServletRequest01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.getRequestURI():获取请求的工程路径
System.out.println("1.请求资源路径:"+req.getRequestURI());
//2.getRequestURL():获取请求的绝对路径
System.out.println("2.请求绝对路径:"+req.getRequestURL());
//3.getRemoteHost():获取客户端ip
System.out.println("3.客户端ip:"+req.getRemoteHost());
//4.getMethod():获取请求的方式(get/post)
System.out.println("4.请求方式:"+req.getMethod());
//5.获取请求参数
String name = req.getParameter("name");
String sex = req.getParameter("sex");
String country = req.getParameter("country");
String []hobby = req.getParameterValues("hobby");
System.out.println("姓名:"+name);
System.out.println("性别:"+sex);
System.out.println("国籍:"+country);
System.out.println("兴趣爱好:"+ Arrays.asList(hobby));
}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8088/servlet01_war/HttpServletRequest01" method="get">
姓名:<input type="text" name="name"><br/>
性别:<input type="radio" name="sex" value="boy">男<input type="radio" name="sex" value="girl">女<br/>
国籍:<select name="country">
<option name="country">--请选择国籍--</option>
<option name="country" selected="selected">中国</option>
<option name="country">美国</option>
<option name="country">意大利</option>
<option name="country">俄罗斯</option>
</select><br/>
兴趣爱好:<input type="checkbox" name="hobby" value="java">java
<input type="checkbox" name="hobby" value="c++">c++
<input type="checkbox" name="hobby" value="python">python
<input type="checkbox" name="hobby" value="js">javascript<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
2.HttpServletRequest类常用方法
- (1)getRequestURI():获取请求的工程路径,可以获取你部署的该工程的路径。
这就是我的部署的web工程路径,用getRequestURI()就可以得到了
- (2)getRequestURL():获取请求的绝对路径
- (3)getRemoteHost():获取客户端ip
如果客户端用localhost访问,得到的是127.0.0.1
如果用同一局域网不同ip访问,就能得到客户端真实ip
- (4)getMethod():获取请求的方式(get/post)
请求有get和post,但大多数是get请求
3.HttpServletRequest获取请求参数的方法
网页数据的对应请求参数
得到的对应提交信息
getParameter()是获取单个参数信息,如以上的姓名,性别国籍
而getParameterValues()获取多个参数信息,如以上的兴趣爱好为多个
HttpServletResponse类
1.HttpServletResponse类的简介
HttpServletResponse类是实现响应的一个类,他将将要响应的数据封装到response对象里面,通过特定的方法响应。响应数据的响应行,响应头,响应体分别由setStatus()、setHeader ()、getWriter() 和getOutputStream()几个方法实现。下面着重介绍 getWriter()(响应字符数据) 和getOutputStream()(响应字节数据)方法。前面我们说到Servlet请求的转发,他是在服务器里面跳转资源的方式。这里介绍的重定向也有类似的功能,但是实现的原理有所不同。
2.响应字符数据
通过response对象,将你想要响应到客户端的字符型数据发送到浏览器里面。只用两步就可以实现:
- 1、先通过response对象获取字符输出流:PrintWriter writer = resp.getWriter();
- 2、将你想要写的数据通过write()方法响应到客户端:writer.write()。public class HttpServletResponse001 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.write("hello servlet!!!");
}}
![9b11449cdd539dc59759c2a5324c7716.png](en-resource://database/3781:0)
需要注意的几点:
- 1.response不仅可以返回纯文本,还可以HTML的各个标签。在返回标签时要注意先把响应响应头的ContentType属性改成text/html格式,不然浏览器会默认把相应的内容当成纯文本解析。public class HttpServletResponse001 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.write("hello servlet!!!");
writer.write("<br/>name:<input type = 'text'/>");
}}
![a8cec17584d19afc29023a71452c73da.png](en-resource://database/3783:0)
- 2.如果响应的是中文的内容,需要把响应头字体类型改成UTF-8。因为服务器默认的字体类型是ISO-8859-1,如果不修改会导致浏览器解析乱码。
public class HttpServletResponse001 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// resp.setContentType("text/html");
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.write("我的servlet程序!!!");
writer.write("<br/>姓名:<input type = 'text'/>");
}}
- 3.修改响应头等信息需要在通过response对象获取字符输出流就完成,在后面才修改没有效果。
public class HttpServletResponse001 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// resp.setContentType("text/html");
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();// resp.setContentType("text/html;charset=utf-8");
writer.write("aaaaa这是在获取输入流对象之前就修改响应头的。");
writer.write("<br/>姓名:<input type = 'text'/>");
}}
- 4.响应结束后,相应的字符流不需要关闭。他不需要向像Java基础里面字节输入流那种最后需要手动关闭流节省资源。因为在响应结束后,response对象自动销毁,服务器会对其关闭。
3.响应字节数据
通过response对象,将你想要响应到客户端的字符型数据发送到浏览器里面。大致需要3步完成:
1、读取文件(图片,音频,视频等二进制输入输出数据)
2、获取字节输出流
3、通过write()方法响应给客户端
public class HttpServletResponse002 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.读物文件
FileInputStream inputStream = new FileInputStream("C:\\Users\\cx\\Desktop\\1.png");
//2.获取字节输出流
ServletOutputStream outputStream = resp.getOutputStream();
//3.打印文件
byte []b = new byte[2048];
int len = 0;
while ((len = inputStream.read(b))!=0){
outputStream.write(b,0,len);
}
inputStream.close();
}}
![7cb0affa8dd3c9975174ca1f86728b52.png](en-resource://database/3789:0)
4.重定向
1.重定向与请求的转发的区别重定向特点;
(1)浏览器地址栏会发生改变,会变成servlet程序1中指定的地址
(2)是两次请求
(3)多个servlet程序不共享request对象内的数据
(4)不可以访问WEB-INF下的资源
(5)可以访问工程以外的其他连接(例如百度、谷歌等网页资源)请求转发的特点(参考我另一篇博客)
(1)浏览器地址栏没有发生变化。
(2)多个servlet程序是同一个请求
(3)多个servlet程序共享一个request对象
(4)可以转发到WEB-INF目录下2.重定向与请求转发的图示区别
2.求情的转发:
重定向:
3.重定向程序的实现
第一种:
@WebServlet("/httpServletResponse003")public class HttpServletResponse003 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.write("servlet001!!!");
//设置响应状态码(302)
resp.setStatus(302);
//设置响应头,告诉新地址在哪
resp.setHeader("location","http://localhost:8888/servlet_war_exploded/httpServletResponse004");
}}
第二种:@WebServlet("/httpServletResponse005")public class HttpServletResponse005 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("http://localhost:8888/servlet_war_exploded/httpServletResponse004");
}}
7
两种方法只要访问了第一个servlet程序再回车,浏览器会自动跳到localhost:8888/servlet_war_exploded/httpServletResponse004而且浏览器地址栏会发生变化。与请求不同,虽然是两个页面,但是是同一个地址(即浏览器地址栏不会发生变化),这与上述所说的第一个特点相对应。
Mapping问题
- 一个Servlet可以指定一个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
2. 一个Servlet可以指定多个映射路径
```xml
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</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>/hello4</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello5</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定通用映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
4. 默认请求路径
```xml
<!--默认请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
- 指定一些后缀或者前缀等等….
<!--可以自定义后缀实现请求映射 注意点,*前面不能加项目映射的路径 hello/sajdlkajda.qinjiang --> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.qinjiang</url-pattern> </servlet-mapping>
6. 优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
```xml
<!--404-->
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Comments | NOTHING