三、ServletContext类
1、什么是ServletContext
代表整个web工程,可以与程序的容器(Tomcat服务器)通信
1.ServletContext是一个接口,它表示Servlet上下文对象
2.一个web工程,只有一个ServletContext对象实例
ServletConfig对象取决于有多少个Servlet程序(一一对应,只能访问到配置文件中属于自己 的配置信息)
但ServletContext对象还能访问配置文件中上下文参数
3.ServletContext对象是一个域对象
4.ServletContext对象是在web工程部署启动的时候创建,在web工程停止的时候销毁
什么是域对象
域对象指的是可以像Map一样存取数据的对象
这里的域指的是存取数据的操作范围——整个web工程
存数据 |
取数据 | 删除数据 | |
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
2、获取ServletContext对象的方法
1.通过HttpServletRequest对象获取
- request.getServletContext();
2.通过HttpServlet获取
- this.getServletContext();
3.通过servletConfig对象获取
- servletConfig.getServletContext();
@WebServlet("/getcontext") public class GetContextServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //通过HttpServlet获取 ServletContext servletContext1 = this.getServletContext(); //通过HttpServletRequest req对象获取 ServletContext servletContext2 = req.getServletContext(); //通过servletConfig对象获取 ServletContext servletContext3 = this.getServletConfig().getServletContext(); System.out.println(servletContext1); System.out.println(servletContext2); System.out.println(servletContext3); } }
3、ServletContext类的四大作用
1.获取web.xml中配置的上下文参数context-param
2.获取当前工程路径,格式:/工程路径
3.获取工程部署在服务器硬盘上的绝对路径
4.像Map一样存取数据
1)获取信息
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--新增部分--> <!--context-param是上下文参数(它属于整个web工程),可以配置多组--> <context-param> <param-name>username</param-name> <param-value>context</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value>root</param-value> </context-param> <!--新增部分--> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.first.cyh.HelloServlet</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/test</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
public class ContextServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取配置文件中的上下文参数 ServletContext context = getServletConfig().getServletContext(); System.out.println(context.getInitParameter("username")); System.out.println(context.getInitParameter("password")); //获取当前的工程路径,格式:/工程路径 System.out.println(context.getContextPath()); //获取工程部署后在服务器硬盘的绝对路径 /* getRealPath()返回一个给定虚拟路径的真实路径 这个斜杆表示站点的根,也就是获取网站的根目录,即工程部署路径 而/css就是表示该路径下的css文件夹 */ System.out.println(context.getRealPath("/")); System.out.println(context.getRealPath("/css")); System.out.println(context.getRealPath("/jpg")); } }
上述程序执行后会返回
context
root
/myfirst
E:\eclipse-workspace\Javaweb-servlet\out\artifacts\Javaweb_servlet_war_exploded
E:\eclipse-workspace\Javaweb-servlet\out\artifacts\Javaweb_servlet_war_exploded\css
E:\eclipse-workspace\Javaweb-servlet\out\artifacts\Javaweb_servlet_war_exploded\jpg
而为什么获得的路径为什么和我们项目创建的路径不一样,在我的另一篇博文(web工程部署路径与getServletConfig().getRealPath()_得过且过的勇者y的博客-CSDN博客中详细讲解了
为什么需要获取工程存放路径呢?
因为项目在本地开发后,项目中的文件路径写的是本地的路径。然而当项目部署到其他设备后,物理地址发生改变,就会导致文件找不到而报错。
2)存取数据
public class ContextServlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //GenericServlet获取获取ServletContext对象的方式,等同于getServletConfig().getServletContext() ServletContext servletContext = getServletContext(); System.out.println("保存之前Context1中获取域数据key1的值是:" + servletContext.getAttribute("key1")); public class ContextServlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext servletContext = getServletContext(); System.out.println("Context2中获取域数据key1的值是:" + servletContext.getAttribute("key1")); } } //存数据 servletContext.setAttribute("key1","value1"); //取数据 System.out.println("Context1中获取域数据key1的值是:" + servletContext.getAttribute("key1")); } } public class ContextServlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext servletContext = getServletContext(); System.out.println("Context2中获取域数据key1的值是:" + servletContext.getAttribute("key1")); } }
public class ContextServlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext servletContext = getServletContext(); System.out.println("Context2中获取域数据key1的值是:" + servletContext.getAttribute("key1")); } }
以下为两次访问ContextServlet1输出的结果(没有重新部署)
保存之前Context1中获取域数据key1的值是:null
Context1中获取域数据key1的值是:value1
保存之前Context1中获取域数据key1的值是:value1
Context1中获取域数据key1的值是:value1
重新部署后再次访问ContextServlet1输出的结果
保存之前Context1中获取域数据key1的值是:null
Context1中获取域数据key1的值是:value1
这是因为ServletContext对象是在web工程部署启动的时候创建,在web工程停止的时候销毁,所以没有重新部署的话key1在set之后就一直存在,所以第二次及以后访问时都会有保存之前Context1中获取域数据key1的值是:value1,而重新部署之后第一次访问就又是null
而前文中的getInitParameter()获取的数据是保存在xml文件中的,故一直存在
总结
setAttribute方式存参数相当于把数据存在内存中,工程停止时消失,而xml方式存参数则是持久化到硬盘中
getInitParameter获得的是xml方式存储的参数
getAttribute获得的是setAttribute方式存储的参数
而当我们已经访问完ContextServlet1后再访问ContextServlet2,会输出
Context2中获取域数据key1的值是:value1
这是因为一个web工程,只有一个ServletContext对象实例,两个Servlet程序中的servletContext其实是相同的,如果我们在两个程序中都输出servletContext这个对象,值是相同的
所以当第一个Servlet程序设置完key1参数后,第二个自然也可以使用它
3)获取MIME类型
MIME类型是在互联网通信过程中定义的一种文件数据类型,格式为:大类型/小类型,如text/html,image/jpg
用处:响应头中content-type需要返回响应体的数据类型,这时候就要获取我们返回的数据的MIME类型
获取方法:通过文件后缀名在tomcat配置文件(tomcat的conf目录下的web.xml)中寻找对应的MIME类型(因为context对象可以与tomcat进行通信)
@WebServlet("/getmime") public class GetMime extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); //定义文件名 String filename = "a.jpg"; //通过文件名的后缀获取对应MIME类型 String mimeType = servletContext.getMimeType(filename); System.out.println(mimeType); } }
返回image/jpeg
四、HttpServletRequest类
1、作用
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的Http协议信息解析封装好到Request对象中,然后传递到service方法(doGet和doPost)中给我们使用。我们可以通过HttpServletRequest对象,获得到所有请求的信息
2、常用方法
getRequestURI():获取请求的资源路径
getRequestURL():获取请求的统一资源定位符(绝对路径)
getRemoteHost():获取客户端的IP地址
getHeader():获取请求头
getParameter():获取请求的参数
getParameterValues():获取请求的参数(多个值得时候使用)
getMethod():获取请求的方式(GET或POST)
setAttribute(key, value):设置域数据
getAttribute(key):获取域数据
getRequestDispatcher():获取请求转发对象
public class RequestAPIServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("URI-->" + req.getRequestURI());//URI-->/myfirst/req System.out.println("URL-->" + req.getRequestURL());//URL-->http://localhost:8080/myfirst/req //如果以localhost访问,则返回0:0:0:0:0:0:0:10:0:0:0:0:0:0:1 //以127.0.0.1访问,则返回127.0.0.1 //以真实ip访问,则返回真实ip System.out.println("HOST-->" + req.getRemoteHost()); //HEADER-->Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30 System.out.println("METHOD-->" + req.getMethod());//GET System.out.println("HEADER-->" + req.getHeader("User-Agent")); } }
public class RequestGetParameter extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("用户名" + req.getParameter("username")); System.out.println("密码" + req.getParameter("password")); String[] hobbies = req.getParameterValues("hobby"); try{ System.out.println("兴趣爱好" + Arrays.asList(hobbies)); }catch (Exception e){ System.out.println(e.getStackTrace()); } } }
注意点
如果使用的是post请求,则需要设置字符集,否则在post请求参数是中文会出现乱码
req.setCharacterEncoding(“UTF-8”);
且此设置要在所有获取参数语句(不管会不会获取中文)的前面设置
只要有获取参数的语句在设置语句前面,不管这条语句会不会获取中文,都会导致设置失效,从而使那些在设置语句后的获取参数语句同样会乱码
3、请求转发
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e8l4Ttgx-1636276443283)(C:\Users\Ken-Chy\Desktop\大二临时\00自学部分\后端\笔记\请求转发.png)]
public class Servlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //查看请求的带来的数据 String username = req.getParameter("username"); System.out.println("servlet1中请求带来的数据:" + username); //处理业务 //doSth username += "ahahha"; System.out.println("业务1完成,username=" + username); //处理完业务,在request域中存储数据 req.setAttribute("username",username); //询问servlet2的路径 //请求转发必须以斜杆开始,表示http://ip:8080/工程名/ RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2"); //带着请求走向servlet requestDispatcher.forward(req,resp); } }
public class Servlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //查看请求带来的数据 String username = request.getParameter("username"); System.out.println("servlet2中请求带来的数据:" + username); //获取servlet1传入的数据 Object obj = request.getAttribute("username"); System.out.println("servlet1传入的数据:"+obj); //处理自己的业务 System.out.println("业务处理完成"); } }
请求转发的特点
1.浏览器地址栏没有发生变化
2.它们是一次请求
3.它们共享Request域中的数据
4.可以转发到WEB-INF目录下
5.不可以访问工程以外的资源
4、base标签的作用
设置页面相对路径工作时参照的地址,href属性就是参数的地址值
应用场景
如果页面采用请求转发,跳转页面时地址不会发生改变,这时候在跳转到的页面中如果访问了设置成相对路径的地址,则会发生请求错误,因为如果没有设置base标签,默认相对地址会参照于当前浏览器的地址
5、web中’/‘的不同意义
在web中,’/'是一种绝对路径
如果被浏览器解析,得到的地址是:http://ip:port/
<a href="/"></a>
如果被服务器解析,得到的地址是:http://ip:port/工程路径
<url-pattern>/servlet1</url-pattern>
servletContext.getRealPath("/")
request.getRequestDispatcher("/")
特殊情况:response.sendRediect("/")是把斜杠发给浏览器解析,故得到的是http://ip:port/