Servlet学习2
1. ServletConfig类
ServletConfig类从类名上看,ServletConfig是Servlet程序的配置信息类。
1.1 ServletConfig类的三大作用
(1)可以获取Servlet程序的别名servlet-name的值。(2)获取初始化参数int-param。(3)获取Servlet Context对象。
作用一:
<servlet> <servlet-name>Servlet5</servlet-name> <servlet-class>com.example.web_02.Servlet4</servlet-class> </servlet> <servlet-mapping> <servlet-name>Servlet5</servlet-name> <url-pattern>/servlet5</url-pattern> </servlet-mapping>
package com.example.web_02; import javax.servlet.*; import java.io.IOException; public class Servlet5 implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("servlet5的别名是:"+servletConfig.getServletName()); } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
按照以上程序显然无法实现功能一(因为servlet-class中的全类名我没改),将4修改为5即可,运行结果如下:
作用二:首先在xml中定义初始化变量
<servlet> <servlet-name>Servlet5</servlet-name> <servlet-class>com.example.web_02.Servlet5</servlet-class> <init-param> <!----> <param-name>username</param-name> <!----> <param-value>root</param-value> </init-param> <init-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/test</param-value> </init-param> </servlet>
package com.example.web_02; import javax.servlet.*; import java.io.IOException; public class Servlet5 implements Servlet { public Servlet5() { System.out.println("servlet5的构造方法被执行"); } @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("servlet5的别名是:"+servletConfig.getServletName()); System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username")); System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url")); } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
运行结果:
功能三:获取ServletContext对象。
package com.example.web_02; import javax.servlet.*; import java.io.IOException; public class Servlet5 implements Servlet { public Servlet5() { System.out.println("servlet5的构造方法被执行"); } @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("servlet5的别名是:"+servletConfig.getServletName()); System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username")); System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url")); System.out.println("ServletContext对象是:"+servletConfig.getServletContext()); } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
运行结果:
2. ServletConfig类的补充说明
Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用。Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象,ServletConfig对象封装了一些初始化配置信息。
<servlet> <servlet-name>Servlet4</servlet-name> <servlet-class>com.example.web_02.Servlet4</servlet-class> <init-param> <!----> <param-name>username</param-name> <!----> <param-value>root</param-value> </init-param> <init-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/test</param-value> </init-param> </servlet>
package com.example.web_02; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Servlet4 extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletConfig servletConfig = getServletConfig(); System.out.println("servlet4的别名是:"+servletConfig.getServletName()); System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username")); System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url")); System.out.println("ServletContext对象是:"+servletConfig.getServletContext()); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
运行后结果:
3. ServletContext类
3.1 ServletContext是一个接口,他表示Servlet上下文对象。
3.2 一个web工程只有一个ServletContext对象实例。
3.3 ServletContext对象是一个域对象。
3.4 ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁。
域对象:是可以像Map一样存取数据的对象,叫域对象。这里的域是数据的存取范围,范围是整个web工程。Map存数据的操作是put(),ServletContext存数据的操作是setAttribute();Map取数据的操作是get(),ServletContext取数据的操作是getAttribute();Map存删除数据的操作是remove(),ServletContext删除数据的操作是removeAttribute();
3.5 ServletContext类的四个常见作用
作用一:获取web.xml中配置的上下文参数context-param。作用二:获取当前的工程路径,格式:/ 工程路径。作用三:获取工程部署后在服务器硬盘上的绝对路径。
package com.example.web_02; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Servlet6 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //作用一:获取web.xml中配置的上下文参数context-param ServletContext context = getServletConfig().getServletContext(); System.out.println("context-param的参数user是"+context.getInitParameter("user")); System.out.println("context-param的参数password是"+context.getInitParameter("password")); //作用二:获取当前工程路径 System.out.println("当前工程路径是:"+context.getContextPath()); //作用三:获取工程部署后在服务器硬盘上的绝对路径。 System.out.println("当前工程的绝对路径是:"+context.getRealPath("/")); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
<context-param> <param-name>user</param-name> <param-value>rensaihang</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value>123456</param-value> </context-param> <servlet> <servlet-name>Servlet6</servlet-name> <servlet-class>com.example.web_02.Servlet6</servlet-class> </servlet> <servlet-mapping> <servlet-name>Servlet6</servlet-name> <url-pattern>/servlet6</url-pattern> </servlet-mapping>
作用四:存取数据
package com.example.web_02; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Servlet7 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext servletContext = getServletContext(); System.out.println("servletContext域数据username的值是:"+servletContext.getAttribute("username")); servletContext.setAttribute("username","rensaihang"); System.out.println("servletContext获取域数据username的值是:"+servletContext.getAttribute("username")); } }
运行结果:
4. HTTP协议
4.1 HTTP协议是指客户端和服务器通信时,发送的数据,须遵守的规则,叫HTTP协议。HTTP协议中的数据又叫报文。
4.2 请求的HTTP协议格式
客户端给服务器发送数据叫请求,服务器给客户端回传数据叫响应。请求又分为GET请求和POST请求两种。
GET请求:请求行(请求的方式GET,请求的资源路径+?+请求参数,请求的协议版本号HTTP/1.1),请求头(key:value组成,不同的键值表示不同的含义。常用请求头:Accept(告诉服务器客户端可以接受的数据类型)、Accept-Language(告诉服务器客户端可以接收的语言类型)、User-Agent(就是浏览器的信息)、Accept-Encoding(告诉服务器客户端可以接收的数据编码、压缩格式)、Host(表示请求的服务器ip和端口号)、Connection(告诉服务器请求连接如何处理))。
POST请求:请求行(),请求头(),空行,请求体。
4.3 哪些是GET请求,哪些是POST请求
GET请求:form标签 method=get、a标签、link标签、Script标签引入css、img标签引入图片、iframe引入html页面、在浏览器地址栏输入地址后回车。
POST请求:form标签 method=post
4.4 响应的HTTP协议格式
响应行(响应的协议和版本号、响应状态码、响应状态描述符),响应头(key:value组成,不同的键值表示不同的含义。),空行,响应体。常用状态码(200表示请求成功、302表示请求重定向、404表示服务器收到请求,但数据不存在,请求地址错误、500表示服务器已收到请求,但服务器内部错误,代码错误)
5. HttpServletRequest类
5.1 HttpServletRequest类的作用
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中。然后传递到service方法(doGet和doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息。
5.2 HttpServletRequest类的常用方法
getRequestURI(),getRequestURL(),getRemoteHost(),getHeader(),
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet(name = "Servlet1", value = "/Servlet1") public class Servlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //请求的资源路径 System.out.println("URI->"+request.getRequestURI()); System.out.println("----------------------------"); //请求的统一资源定位符(绝对路径) System.out.println("URL->"+request.getRequestURL()); System.out.println("----------------------------"); //获取客户端的ip地址 System.out.println("客户端ip地址->"+request.getRemoteHost()); System.out.println("----------------------------"); //获取请求头 System.out.println("请求头User-Agent->"+request.getHeader("User-Agent")); System.out.println("----------------------------"); //获取请求方式 System.out.println("请求的方式:"+request.getMethod()); } }
运行结果:
getParameter(),getParameterValues(),getMethod()方法
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; import java.util.Arrays; public class Servlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); //当请求参数为多值时,用getParameterValues()方法 String []hobby = request.getParameterValues("hobby"); String address = request.getParameter("address"); System.out.println("用户名:"+username); System.out.println("密码:"+password); System.out.println("爱好:"+Arrays.asList(hobby)); System.out.println("住址:"+address); } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="http://localhost:8080/web_03/servlet2" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> 兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++ <input type="checkbox" name="hobby" value="java">Java <input type="checkbox" name="hobby" value="js">JavaScript <br> 住址:<input type="checkbox" name="address" value="BeiJing">BeiJing <input type="checkbox" name="address" value="ShangHai">ShangHai <input type="checkbox" name="address" value="GuangZhou">GuangZhou <br> <input type="submit"> <input type="reset"> </form> </body> </html>
运行结果:
注意post请求的中文乱码问题:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="http://localhost:8080/web_03/servlet2" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> 兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++ <input type="checkbox" name="hobby" value="java">Java <input type="checkbox" name="hobby" value="js">JavaScript <br> 住址:<input type="checkbox" name="address" value="BeiJing">BeiJing <input type="checkbox" name="address" value="ShangHai">ShangHai <input type="checkbox" name="address" value="GuangZhou">GuangZhou <br> <input type="submit"> <input type="reset"> </form> </body> </html>
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; import java.util.Arrays; public class Servlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); //当请求参数为多值时,用getParameterValues()方法 String []hobby = request.getParameterValues("hobby"); String address = request.getParameter("address"); System.out.println("用户名:"+username); System.out.println("密码:"+password); System.out.println("爱好:"+Arrays.asList(hobby)); System.out.println("住址:"+address); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); //设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题,必须在获取参数前调用才有效 request.setCharacterEncoding("UTF-8"); String password = request.getParameter("password"); //当请求参数为多值时,用getParameterValues()方法 String []hobby = request.getParameterValues("hobby"); String address = request.getParameter("address"); System.out.println("用户名:"+username); System.out.println("密码:"+password); System.out.println("爱好:"+Arrays.asList(hobby)); System.out.println("住址:"+address); } }
5.4 请求转发
相关方法setAttribute(key,value),getAttribute(key),getRequestDispatcher()获取请求转发对象
请求转发:客户端(浏览器)通过http://ip:port/工程名/servlet1到Servlet1程序,Servlet1检查有没有带请求的参数,Servlet1处理完相应业务,加上标记,再寻找到Servlet2的路径,将请求传递到Servlet2,Servlet2程序获取请求的参数,检查有无Servlet1的标记,在处理自己的业务,然后经过Servlet1使用户收到最终的结果。
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Servlet3 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); //获取请求参数 String username = request.getParameter("username"); System.out.println("在servlet3中的username:"+username); //Servlet1处理自己的业务 System.out.println("Servlet3处理自己的业务"); //Servlet1处理完自己的业务,加盖自己标记 request.setAttribute("key3","servlet3的标记"); //询问Servlet2的路径,传递请求到Servlet4 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet4"); requestDispatcher.forward(request,response); } }
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Servlet4 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String username = request.getParameter("username"); System.out.println("在Servlet4中username:"+username); Object key3 = request.getAttribute("key3"); System.out.println("是否有标记"+key3); System.out.println("Servlet4处理自己的业务"); } }
结果显示:
请求转发的特点:浏览器地址栏没有变化,只是一次请求,共享Request与中的数据,可以转发到WEB-INF目录下,不可以访问工程以外的的资源。
6. base标签的作用
base设置相对路径的工作地址。例:添加base设置相对路径的工作地址便都可跳转。
工程路径:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> 这是web下的首页 <br> <a href="a/b/c.html">a/b/c.html</a> <a href="http://localhost:8080/web_03/servlet5">请求转发:a/b/c.html</a> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <base href="http://localhost:8080/web_03/a/b/"> </head> <body> <p>这是a下的b下的c.html</p> <!- base设置相对路径工作室的参照地址-> <a href="../../index.html">跳转到index页面</a> </body> </html>
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Servlet5 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("经过了Servlet5程序"); request.getRequestDispatcher("/a/b/c.html").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
7. web中“/"的不同意义
/ 在浏览器中被解析为:http://ip:port/,例<a href="/">斜杠</a>
/ 在服务器中被解析为http://ip:port/工程路径,例:
<url-pattern>/servlet1</url-pattern>,servletContext.getRealPath("/"),request.getRequestDispather("/")
特殊情况:response.sendRedirect("/"):把斜杠发送给浏览器解析。得到:http://ip:port/
8. HttpServletResponse类
HttpServletResponse类和HttpServletRequest类一样。每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用。HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有相应信息。如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来设置。
HttpServletResponse对象通过两个输出流返回给客户端信息。两个流是字节流和字符流。字节流:getOutputStream(),常用于下载和传递二进制数据。字符流:getWriter()常用于回传字符串(常用)。注意:两个流同时只能使用一个。
如何向客户端回传数据
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; import java.io.PrintWriter; public class Servlet6 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter writer = response.getWriter(); writer.write("web_03"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
解决响应的中文乱码:
两种方式选一种即可。
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; import java.io.PrintWriter; public class Servlet6 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //方式一 //设置服务器字符集 response.setCharacterEncoding("UTF-8"); //通过响应头,设置浏览器的字符集 response.setHeader("Content-Type","text/html;charset=UTF-8"); //方式二 //同时设置服务器和客户端的字符集 response.setContentType("text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); writer.write("我真帅"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
9. 请求重定向
浏览器访问服务器的Response1程序,此时Response1程序由于某种原因不再使用,并由Response2程序所取代。Response1程序须向客户端反馈响应状态码和Location响应头,新地址。客户端再通过新地址访问Response2程序,Response2响应信息。
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Response1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("response1的响应"); //设置响应状态码,表示重定向 response.setStatus(302); //设置响应头,说明新的响应地址 response.setHeader("Location","http://localhost:8080/web_03/response2"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Response2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); response.getWriter().write("response2的响应"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
请求重定向的特点:浏览器地址栏会发生变化,两次请求,不共享Request域中的数据,不能访问WEB-INF下的资源,可以访问工程外的资源。
请求重定向常用方式
package com.example.web_03; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class Response1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("response1的响应"); //设置响应状态码,表示重定向 //response.setStatus(302); //设置响应头,说明新的响应地址 //response.setHeader("Location","http://localhost:8080/web_03/response2"); response.sendRedirect("http://localhost:8080/web_03/response2"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
加上昨天的就是所学的Servlet全部知识内容了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)