一.Servlet

1.概念

什么是Servlet?
1.Servlet 是 java EE 的规范之一。也就是接口。Servlet 接口定义了一套网络请求的规范2.Servlet 是 javaweb 的三大组件之一。 javaweb 的三大组件分为 Servlet程序、Filter 过滤器、Listener 监听器3.Servlet 是运行在服务器上的一个 java 程序。作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层(可以接收客户端发送的请求,并且响应 数据给客户端)。* 概念:* 定义了一个类被浏览器访问的规则。是一个接口。* 功能:* 接受请求* 处理请求* 作出响应* 快速入门:0.创建web项目1.定义一个Java类,实现Servlet接口2.重写所有未实现方法 service()方法里面写句话3.配置Servlet,web/WEB-INF/web.xml 配置Servlet<!-- 配置Servlet,为了配置Servlet的访问路径 --><servlet><servlet-name>demo1</servlet-name><servlet-class>cn.itcast.servlet.ServletDemo1</servlet-class></servlet><servlet-mapping><servlet-name>demo1</servlet-name><!-- 设置访问路径,以/开头  --><url-pattern>/demo</url-pattern></servlet-mapping>4.发布项目5.访问/demo路径访问该Servlet浏览器中:http://127.0.0.1:8080/项目名/web.xml中配置的虚拟路径名

Java类,需要实现Servlet方法

package org.westos.demo;import javax.servlet.*;
import java.io.IOException;public class MyServlet implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("请求来了");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}

配置文件 web.xml

<?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"><servlet><servlet-name>MyServlet</servlet-name><servlet-class>org.westos.demo.MyServlet</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet</servlet-name><!--配置映射路径--><url-pattern>/demo</url-pattern></servlet-mapping>
</web-app>

客户端浏览器发送请求:

服务器收到请求

2.Servlet的生命周期

Servlet的原理:* 服务器通过反射的方式 创建Servlet对象,调用其方法* servlet生命周期:* 被创建:默认情况下,Servlet第一次被访问时,被创建,调用init()方法。只执行一次。Servlet是单例的。可能会存在线程安全问题,尽量不要定义成员变量。可以配置Servlet的创建时机。在web.xml的<servlet>标签中配置<load-on-startup><!-- 修改servlet的创建时机:* 负整数:默认值 -1,在第一次被访问时创建* 非负整数:在服务器启动时创建* 数字越小,优先级越高--><load-on-startup>0</load-on-startup>* 提供服务:每一次被访问时,会调用service()方法提供服务* 被销毁:服务器关闭时,servlet被销毁。服务器正常关闭是,在销毁Servlet之前,会调用destory()方法Servlet的生命周期方法生命周期:一个事物从生到死,所经历的一个过程。Servlet的生命周期方法:Servlet从被创建 到 销毁,在不同阶段,所要调用的一些生命周期方法。init()----service()----destroy()

MyServlet2.java

package org.westos.demo;import javax.servlet.*;
import java.io.IOException;public class MyServlet2 implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {//被创建:默认情况下,Servlet第一次被访问时,Servlet通过构造被创建,调用init() 方法。//init()只调用一次。那么这个方法里面,可以做一下准备工作。System.out.println("init()方法调用了");}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {//*提供服务:每一次被访问时,会调用service() 方法提供服务//service() 每次请求都会调用System.out.println("service()方法调用了");}@Overridepublic void destroy() {//正常关闭服务器时,服务器会销毁servlet,那么销毁之前,就会调用destroy()方法System.out.println("destory()方法调用了");}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic String getServletInfo() {return null;}}

web.xml

<?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"><servlet><servlet-name>MyServlet</servlet-name><servlet-class>org.westos.demo.MyServlet</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet</servlet-name><!--配置映射路径--><url-pattern>/demo</url-pattern></servlet-mapping><!--多加一个Servlet,就要多配置一个xml路径--><servlet><servlet-name>MyServlet2</servlet-name><servlet-class>org.westos.demo.MyServlet2</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet2</servlet-name><url-pattern>/demo2</url-pattern></servlet-mapping>
</web-app>

3.配置Servlet的创建时机

修改servlet的创建时机:* 负整数:默认值 -1,在第一次被访问时创建* 非负整数:在服务器启动时创建* 数字越小,优先级越高<load-on-startup>0</load-on-startup>如果优先级相同,会按照web.xml文件从上到下加载

MyServlet1.java

package org.westos.demo;import javax.servlet.*;
import java.io.IOException;public class MyServlet implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("Servlet1创建了");}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("请求来了");}@Overridepublic void destroy() {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic String getServletInfo() {return null;}}

MyServlet2.java

package org.westos.demo;import javax.servlet.*;
import java.io.IOException;public class MyServlet2 implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("Servlet2创建了");}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {}@Overridepublic void destroy() {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic String getServletInfo() {return null;}}

web.xml

<?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"><!--配置servlet--><servlet><servlet-name>MyServlet</servlet-name><servlet-class>org.westos.demo.MyServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>MyServlet</servlet-name><url-pattern>/demo</url-pattern></servlet-mapping><servlet><servlet-name>MyServlet2</servlet-name><servlet-class>org.westos.demo.MyServlet2</servlet-class><load-on-startup>0</load-on-startup></servlet><servlet-mapping><servlet-name>MyServlet2</servlet-name><url-pattern>/demo2</url-pattern></servlet-mapping>
</web-app>

4.ServletConfig

* ServletConfig对象: ServletConfig 配置对象,是个接口,他的对象由服务器创建,然后传递给init方法* 功能1.获取servlet初始化参数*  String getInitParameter(String name)键找值  *  Enumeration getInitParameterNames()  拿出集合后再键找值例子:System.out.println(config.getInitParameter("src"));System.out.println(config.getInitParameter("href"));Enumeration<String> names = config.getInitParameterNames();while (names.hasMoreElements()) {String key = names.nextElement();System.out.println(key);System.out.println(config.getInitParameter(key));}初始化参数可在 web.xml中配置
<servlet><servlet-name>demo3</servlet-name><servlet-class>com.click369.servlet.ServletDemo3</servlet-class>
<!--配置一些初始化参数--><init-param><param-name>src</param-name><param-value>c://a.txt</param-value></init-param><init-param><param-name>href</param-name><param-value>d://a.txt</param-value></init-param></servlet><servlet-mapping><servlet-name>demo3</servlet-name><url-pattern>/demo3</url-pattern></servlet-mapping>作用2:获取ServletContext全局上下文对象   因为 ServletContext对象是由服务器创建出来的 我们要获取其对象 得通过ServletConfig对象中的方法才能获取出来* ServletContext getServletContext()//ServletContext:全局上下文对象,代表你整个web应用。全局上下文对象,由服务器来创建,服务器一启动,就会创建//ServletContext:全局上下文对象,你是通过配置对象获取出来用。作用3.获取servlet配置的名称 就是在web.xml中给servlet起的名字* String getServletName() * Servlet中对应getServletConfig方法。要想使用该方法获取config对象。则需要提升config对象的作用域。1.声明成员变量ServletConfig 2.在init方法中赋值3.在getServletConfig方法中获取

MyServlet3.java

package org.westos.demo;import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;public class MyServlet3 implements Servlet {//提升变量作用域,让他在其他方法中也能使用,不局限于init方法private ServletConfig servletConfig=null;@Overridepublic void init(ServletConfig servletConfig) throws ServletException {//servletConfig配置对象   ServletConfig是一个接口 在Servlet初始化的时候 有服务器创建其子类对象传递给 init()方法//servlet 容器使用的 servlet 配置对象,该对象在初始化期间将信息传递给 servlet。this.servletConfig=servletConfig;System.out.println(servletConfig);//org.apache.catalina.core.StandardWrapperFacade@2392c6c//作用:1.可以获取web.xml中 配置的一些初始化参数//两种方式: 键找值String username = servletConfig.getInitParameter("username");String password = servletConfig.getInitParameter("password");/*张三123456*/System.out.println(username);System.out.println(password);//遍历方式:Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();while (initParameterNames.hasMoreElements()){String key = initParameterNames.nextElement();String value = servletConfig.getInitParameter(key);System.out.println("key:=="+key+"value:=="+value);/** key:==password value:==123456key:==username value:==张三* */}System.out.println("===========================================");//ServletConfig 作用:2. 可以获取 ServletContext 全局上下文对象。ServletContext servletContext = servletConfig.getServletContext();//ServletContext:全局上下文对象,代表你整个web应用。全局上下文对象,由服务器来创建,服务器一启动,就会创建//ServletContext:全局上下文对象,你是通过配置对象获取出来用。System.out.println(servletConfig);//org.apache.catalina.core.StandardWrapperFacade@25f12241//ServletConfig 作用:3. 可以获取web.xml中配置的Servlet的名字。String servletName = servletConfig.getServletName();System.out.println(servletName);//MyServlet3}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {//我想在service()方法里面用到这个配置对象。// servletConfig.getInitParameter("username");ServletConfig servletConfig = getServletConfig();}@Overridepublic void destroy() {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic String getServletInfo() {return null;}}

web.xml

<?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"><servlet><servlet-name>MyServlet</servlet-name><servlet-class>org.westos.demo.MyServlet</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet</servlet-name><!--配置映射路径--><url-pattern>/demo</url-pattern></servlet-mapping><!--多加一个Servlet,就要多配置一个xml路径--><servlet><servlet-name>MyServlet2</servlet-name><servlet-class>org.westos.demo.MyServlet2</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet2</servlet-name><url-pattern>/demo2</url-pattern></servlet-mapping><servlet><servlet-name>MyServlet3</servlet-name><servlet-class>org.westos.demo.MyServlet3</servlet-class><!--配置初始化参数--><init-param><param-name>username</param-name><param-value>张三</param-value></init-param><init-param><param-name>password</param-name><param-value>123456</param-value></init-param></servlet><servlet-mapping><servlet-name>MyServlet3</servlet-name><url-pattern>/demo3</url-pattern></servlet-mapping>
</web-app>

5.Servlet的三种创建方式

     1. 实现Servlet2. 继承GenericServlet1.适配器2.对ServletConfig进行优化。提升config对象的作用域3.实现了ServletConfig接口,简化对config对象的使用方式3. 继承HttpServlet:对http协议的封装* 重写doGet()和doPost()...方法      注意去掉super.doGet(); 和 super.doPost();


方式2:继承GenericServlet

GenericServlet.java源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package javax.servlet;import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {private static final long serialVersionUID = 1L;private transient ServletConfig config;public GenericServlet() {}public void destroy() {}public String getInitParameter(String name) {return this.getServletConfig().getInitParameter(name);}public Enumeration<String> getInitParameterNames() {return this.getServletConfig().getInitParameterNames();}public ServletConfig getServletConfig() {return this.config;}public ServletContext getServletContext() {return this.getServletConfig().getServletContext();}public String getServletInfo() {return "";}public void init(ServletConfig config) throws ServletException {this.config = config;this.init();}public void init() throws ServletException {}public void log(String msg) {this.getServletContext().log(this.getServletName() + ": " + msg);}public void log(String message, Throwable t) {this.getServletContext().log(this.getServletName() + ": " + message, t);}public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;public String getServletName() {return this.config.getServletName();}
}

web.xml

<?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"><servlet><servlet-name>MyServlet</servlet-name><servlet-class>org.westos.demo.MyServlet</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet</servlet-name><!--配置映射路径--><url-pattern>/demo</url-pattern></servlet-mapping><!--多加一个Servlet,就要多配置一个xml路径--><servlet><servlet-name>MyServlet2</servlet-name><servlet-class>org.westos.demo.MyServlet2</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet2</servlet-name><url-pattern>/demo2</url-pattern></servlet-mapping><servlet><servlet-name>MyServlet3</servlet-name><servlet-class>org.westos.demo.MyServlet3</servlet-class><!--配置初始化参数--><init-param><param-name>username</param-name><param-value>张三</param-value></init-param><init-param><param-name>password</param-name><param-value>123456</param-value></init-param></servlet><servlet-mapping><servlet-name>MyServlet3</servlet-name><url-pattern>/demo3</url-pattern></servlet-mapping><servlet><servlet-name>MyServlet4</servlet-name><servlet-class>org.westos.demo2.MyServlet4</servlet-class><init-param><param-name>username</param-name><param-value>李白</param-value></init-param></servlet><servlet-mapping><servlet-name>MyServlet4</servlet-name><url-pattern>/demo4</url-pattern></servlet-mapping>
</web-app>

MyServlet4.java

package org.westos.demo2;import javax.servlet.*;
import java.io.IOException;public class MyServlet4 extends GenericServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {ServletConfig servletConfig = this.getServletConfig();ServletContext servletContext = servletConfig.getServletContext();System.out.println(servletConfig);//org.apache.catalina.core.StandardWrapperFacade@9d71d74System.out.println(servletContext);//org.apache.catalina.core.ApplicationContextFacade@710f23e//从父类中继承而来String username = this.getInitParameter("username");System.out.println(username);//李白String username1=servletConfig.getInitParameter("username");System.out.println(username1);//李白}
}

方式3:继承HttpServlet:对http协议的封装

package org.westos.demo2;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;//以注解的方式配置Servlet的名称  ,       映射路径
@WebServlet(name = "MyServlet5", value = "/demo5")
public class MyServlet5 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("get请求来了");}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("post请求来了");this.doPost(request, response);}
}

6. ServletContext全局域对象

* 特点:* 由服务器创建* 单例* 功能:* 域对象:在域的范围内共享数据* 范围:整个web应用* 存储所有用户共享的数据,这四个方法四个域对象都有* setAttribute():* getAttribute():* removeAttribute():* JavaWeb中四大域对象:
1.ServletContext 他是一个全局域对象,域,就是范围的意思,域对象可以在他所代表                的范围内进行数据的共享。
2.HttpSession:会话域
3.ServletRequest:请求域
4.PageContext:页面域四个域对象存取数据,删除数据的方法。context.setAttribute();context.getAttribute()context.removeAttribute();* 获取文件mime类型:* getMimeType(文件名称):* 获取文件运行的真实路径:* 真实路径:指服务器路径* getRealPath():* 1.webRoot下:项目根目录下* 2.WEB-INF下: 项目根目录下/WEB-INF* 3.src下: 项目根目录下/WEB-INF/classes* *注意:如果getRealPath("/"),获取的路径是项目的根目录//根目录ServletContext context = this.getServletContext();String rootpath = context.getRealPath("/");//System.out.println(rootpath);//1.webRootString b = context.getRealPath("/b.txt");System.out.println(b);//2.WEB-INFString c = context.getRealPath("/WEB-INF/c.txt");System.out.println(c);//3.srcString a = context.getRealPath("/WEB-INF/classes/a.txt");System.out.println(a);* ServletContext只能用于web环境。如果是非web环境,则使用ClassLoader来获取真实路径比如我web项目里有一个普通的java工具类 我想获取文件的真实路径 那我就用不了 ServletContext//1.获取该类对应的类加载器对象ClassLoader loader = this.getClass().getClassLoader();//2.获取文件运行的真实路径URL url = loader.getResource("a.txt");String path = url.getPath();//注意类加载器来获取路径也有局限性 只能获取src目录下的文件// 方式2InputStream stream = MyUtil.class.getClassLoader().getResourceAsStream("/a.txt");System.out.println(stream);

编写两个类来模拟

MyServlet.java

package org.westos.demo;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet(name = "MyServlet", value = "/demo")
public class MyServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("请求来了");//获取全局域对象ServletContext context = this.getServletConfig().getServletContext();//往域中存储数据context.setAttribute("username","zs");}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}

MyServlet2.java

package org.westos.demo;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet(name = "MyServlet2", value = "/demo2")
public class MyServlet2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//  ServletContext 全局上下文对象,服务器已开启,就会创建,他代表了整个web应用。/* 特点:由服务器创建单例//web 中的四大域对象。ServletContext 他是一个全局域对象,域,就是范围的意思,域对象可以在他所代表的范围内进行数据的共享。Session 会话域Request 请求域PageContext 页面域四个域对象存取数据,删除数据的方法。context.setAttribute();context.getAttribute()context.removeAttribute();*/ServletContext context = this.getServletConfig().getServletContext();//获取域中的数据String username = (String) context.getAttribute("username");System.out.println(username);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}

7.本地项目与Web项目

 本地项目是可以在自己计算机上访问到的项目,以前的JavaSE所有项目都属于本地项目,本地项目的路径是写死的;Web项目是你将写好的项目打成war包发送给运维人员,放到公司服务器上,而这个项目仍然可以在你公司的服务器上运行,这就要求我们不能把路径写死,否则这个项目可能只会在你自己的计算机上运行注意:打成war包后项目的路径有所改变,且war包下没有src路径

本地项目的方式:

这种直接把路径给写死了

package org.westos.demo;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;@WebServlet(name = "MyServlet", value = "/demo")
public class MyServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("demo 请求来了");//我在web目录下有一个a.txt//web/WEB-INF/ 有一个b.txt//在 src 下有一个c.txtFileInputStream in = new FileInputStream(new File("D:\\develop\\apache-tomcat-8.5.43\\webapps\\demo\\WEB-INF\\classes\\c.txt"));System.out.println(in);FileInputStream in2 = new FileInputStream(new File("D:\\develop\\apache-tomcat-8.5.43\\webapps\\demo\\a.txt"));System.out.println(in2);FileInputStream in3 = new FileInputStream(new File("D:\\develop\\apache-tomcat-8.5.43\\webapps\\demo\\WEB-INF\\b.txt"));System.out.println(in3);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}

8.获取文件运行的真实路径

* 获取文件mime类型:* getMimeType(文件名称):* 获取文件运行的真实路径:* 真实路径:指服务器路径* getRealPath():* 1.webRoot下:项目根目录下* 2.WEB-INF下: 项目根目录下/WEB-INF* 3.src下: 项目根目录下/WEB-INF/classes* *注意:如果getRealPath("/"),获取的路径是项目的根目录//根目录ServletContext context = this.getServletContext();String rootpath = context.getRealPath("/");//System.out.println(rootpath);//1.webRootString b = context.getRealPath("/b.txt");System.out.println(b);//2.WEB-INFString c = context.getRealPath("/WEB-INF/c.txt");System.out.println(c);//3.srcString a = context.getRealPath("/WEB-INF/classes/a.txt");System.out.println(a);* ServletContext只能用于web环境。如果是非web环境,则使用ClassLoader来获取真实路径比如我web项目里有一个普通的java工具类 我想获取文件的真实路径 那我就用不了 ServletContext//1.获取该类对应的类加载器对象ClassLoader loader = this.getClass().getClassLoader();//2.获取文件运行的真实路径URL url = loader.getResource("a.txt");String path = url.getPath();//注意类加载器来获取路径也有局限性 只能获取src目录下的文件// 方式2InputStream stream = MyUtil.class.getClassLoader().getResourceAsStream("/a.txt");System.out.println(stream);

获取web环境下的真实路径

package org.westos.demo;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;@WebServlet(name = "MyServlet2", value = "")
public class MyServlet2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//继承自GenericServlet.clasServletContext context = this.getServletContext();System.out.println(context);//  org.apache.catalina.core.ApplicationContextFacade@2566f84dString realPath = context.getRealPath("/");System.out.println(realPath);//D:\develop\apache-tomcat-8.5.43\webapps\demo\FileInputStream in1 = new FileInputStream(new File(realPath + "a.txt"));System.out.println(in1);//java.io.FileInputStream@764bb5c2FileInputStream in2 = new FileInputStream(new File(realPath + "WEB-INF\\b.txt"));System.out.println(in2);//java.io.FileInputStream@72742fd3FileInputStream in3 = new FileInputStream(new File(realPath + "WEB-INF\\classes\\c.txt"));System.out.println(in3);//java.io.FileInputStream@3776bff9String mimeType = context.getMimeType(realPath + "a.txt");System.out.println(mimeType);//text/plainnew MyUtils().test();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}

读取web工程下普通的java类

  如果是web工程中普通的Java类,想要读取src下的文件,通过类加载器
package org.westos.utils;import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URL;public class MyUtils {public void test() throws FileNotFoundException {//如果是web工程中普通的Java类,想要读取src下的文件,只能通过类加载器InputStream resourceAsStream = MyUtils.class.getClassLoader().getResourceAsStream("c.txt");System.out.println(resourceAsStream);URL url = MyUtils.class.getClassLoader().getResource("c.txt");System.out.println(url);//file:/D:/develop/apache-tomcat-8.5.43/webapps/demo/WEB-INF/classes/c.txtString path = url.getPath();System.out.println(path);//  /D:/develop/apache-tomcat-8.5.43/webapps/demo/WEB-INF/classes/c.txt}
}

二.MIME类型

1、什么是MIME类型

根据百度百科的解释:MIME:全称Multipurpose Internet Mail Extensions,多功能Internet邮件扩充服务。它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。说白了也就是文件的媒体类型。浏览器可以根据它来区分文件,然后决定什么内容用什么形式来显示。

2.部分文件的MIMEType

文件拓展名 MIMEType
png image/png
bmp\dib image/bmp
jpg\jpeg\jpg image/ipeg
gif image/gif
mp3 audio/mpeg
mp4\mpg4\m4v\mp4v video/mp4
js application/javascript
pdf application/pdf
text\txt text/plan
json application/json
xml text/xml

3.为什么要获取MIMEType

关于为什么要获取MIMEType的原因,是因为在进行文件上传的时候,需要在POST请求体中传递相应的参数,来进行文件的上传操作​```
说明:当然你也可以直接传递application/octet-stream,此参数表示通用的二进制类型。
​```

三.常用的头信息

请求头Accept: text/html,image/* --告诉服务器当前客户端可以接收的文档的类型。其实这里包含了*/*,就表示什么都可以接收;  大类型/小类型 比如 text/css text/javascriptAccept-Charset: ISO-8859-1  --告诉服务器,客户端提交的表单可能使用的编码类型Accept-Encoding: gzip       --浏览器发给服务器,声明浏览器支持的编码类型Accept-Language:zh-cn        --语言环境Host: localhost:8080      --访问主机If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT   客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:
后面跟的时间是本地浏览器存储的文件修改时间Referer: http://www.baidu.com/index.jsp     --来自哪个页面、防盗链User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)CookieConnection:Keep-Alive      --链接状态 长链接Date: Tue, 11 Jul 2000 18:23:51 GMT   --时间响应头
Location: http://www.baidu.org/index.jsp    --跳转方向 302重定向
Server:apache tomcat            --服务器型号
Content-Encoding: gzip          --数据压缩
Content-Length: 80          --数据长度
Content-Language: zh-cn         --语言环境
Content-Type: text/html; charset=GB2312 --告诉浏览器,服务器返回的文本采用什么编码
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT    在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,
Refresh: 3;url=http://www.hehe.org     --延时3s跳转页面
Content-Disposition: attachment; filename=aaa.zip  --下载
Set-Cookie:SS=Q0=5Lb_nQ; path=/search
Expires: -1                 --缓存  就是让页面立即过期
Cache-Control: no-cache  --浏览器和缓存服务器都不应该缓存页面信息强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验
Connection: Keep-Alive              --保持连接 长链接
Date: Tue, 11 Jul 2000 18:23:51 GMTprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");response.getWriter().write("进入了demo11,接下来3秒钟后进入demo10");response.setHeader("refresh", "3;url=/ResponseDemo/ResponseDemo10"); //设置刷新头延时3秒跳转页面}

四.Servlet是单例多线程

Servlet如何处理多个请求访问?
Servlet容器默认是采用单实例多线程的方式处理多个请求的:
1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例);
2.容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等。
3.当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread) 调度它管理下线程池中等待执行的线程(Worker Thread)给请求者;
4.线程执行Servlet的service方法;
5.请求结束,放回线程池,等待被调用;
(注意:避免使用实例变量(成员变量),因为如果存在成员变量,可能发生多线程同时访问该资源时,都来操作它,照成数据的不一致,因此产生线程安全问题)从上面可以看出:
第一:Servlet单实例,减少了产生servlet的开销;
第二:通过线程池来响应多个请求,提高了请求的响应时间;
第三:Servlet容器并不关心到达的Servlet请求访问的是否是同一个Servlet还是另一个Servlet,直接分配给它一个新的线程;如果是同一个Servlet的多个请求,那么Servlet的service方法将在多线程中并发的执行;
第四:每一个请求由ServletRequest对象来接受请求,由ServletResponse对象来响应该请求;Servlet/JSP技术和ASP、PHP等相比,由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的安全性问题。 JSP的中存在的多线程问题:
当客户端第一次请求某一个JSP文件时,服务端把该JSP编译成一个CLASS文件,并创建一个该类的实例,然后创建一个线程处理CLIENT端的请求。如果有多个客户端同时请求该JSP文件,则服务端会创建多个线程。每个客户端请求对应一个线程。以多线程方式执行可大大降低对系统的资源需求,提高系统的并发量及响应时间. 对JSP中可能用的的变量说明如下:
实例变量: 实例变量是在堆中分配的,并被属于该实例的所有线程共享,所以不是线程安全的.
JSP系统提供的8个类变量
JSP中用到的OUT,REQUEST,RESPONSE,SESSION,CONFIG,PAGE,PAGECONXT是线程安全的(因为每个线程对应的request,respone对象都是不一样的,不存在共享问题), APPLICATION在整个系统内被使用,所以不是线程安全的. 局部变量: 局部变量在堆栈中分配,因为每个线程都有它自己的堆栈空间,所以是线程安全的.
静态类: 静态类不用被实例化,就可直接使用,也不是线程安全的. 外部资源: 在程序中可能会有多个线程或进程同时操作同一个资源(如:多个线程或进程同时对一个文件进行写操作).此时也要注意同步问题. 使它以单线程方式执行,这时,仍然只有一个实例,所有客户端的请求以串行方式执行。这样会降低系统的性能 问题
问题一. 说明其Servlet容器如何采用单实例多线程的方式来处理请求
问题二. 如何在开发中保证servlet是单实例多线程的方式来工作(也就是说如何开发线程安全的servelt)。 一. Servlet容器如何同时来处理多个请求 Java的内存模型JMM(Java Memory Model)
JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有实例变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存由缓存和堆栈两部分组成,缓存中保存的是主存中变量的拷贝,缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是线程的局部变量,线程之间无法相互直接访问堆栈中的变量。根据JMM,我们可以将论文中所讨论的Servlet实例的内存模型抽象为图所示的模型。 工作者线程Work Thread:执行代码的一组线程。
调度线程Dispatcher Thread:每个线程都具有分配给它的线程优先级,线程是根据优先级调度执行的。 Servlet采用多线程来处理多个请求同时访问。servlet依赖于一个线程池来服务请求。线程池实际上是一系列的工作者线程集合。Servlet使用一个调度线程来管理工作者线程。 当容器收到一个Servlet请求,调度线程从线程池中选出一个工作者线程,将请求传递给该工作者线程,然后由该线程来执行Servlet的service方法。当这个线程正在执行的时候,容器收到另外一个请求,调度线程同样从线程池中选出另一个工作者线程来服务新的请求,容器并不关心这个请求是否访问的是同一个Servlet.当容器同时收到对同一个Servlet的多个请求的时候,那么这个Servlet的service()方法将在多线程中并发执行。
Servlet容器默认采用单实例多线程的方式来处理请求,这样减少产生Servlet实例的开销,提升了对请求的响应时间,对于Tomcat可以在server.xml中通过<Connector>元素设置线程池中线程的数目。 就实现来说:
调度者线程类所担负的责任如其名字,该类的责任是调度线程,只需要利用自己的属性完成自己的责任。所以该类是承担了责任的,并且该类的责任又集中到唯一的单体对象中。而其他对象又依赖于该特定对象所承担的责任,我们就需要得到该特定对象。那该类就是一个单例模式的实现了。 注意:服务器可以使用多个实例来处理请求,代替单个实例的请求排队带来的效益问题。服务器创建一个Servlet类的多个Servlet实例组成的实例池,对于每个请求分配Servlet实例进行响应处理,之后放回到实例池中等待下此请求。这样就造成并发访问的问题。
此时,局部变量(字段)也是安全的,但对于全局变量和共享数据是不安全的,需要进行同步处理。而对于这样多实例的情况SingleThreadModel接口并不能解决并发访问问题。 SingleThreadModel接口在servlet规范中已经被废弃了。二 如何开发线程安全的Servlet 1、实现 SingleThreadModel 接口 该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。这种方法只要将前面的Concurrent Test类的类头定义更改为: Public class Concurrent Test extends HttpServlet implements SingleThreadModel {
…………
} 2、同步对共享数据的操作 使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段,在本论文中的Servlet可以通过同步块操作来保证线程的安全。同步后的代码如下: …………
Public class Concurrent Test extends HttpServlet { …………
Username = request.getParameter ("username");
Synchronized (this){
Output = response.getWriter ();
Try {
Thread. Sleep (5000);
} Catch (Interrupted Exception e){}
output.println("用户名:"+Username+"<BR>");
}
}
} 3、避免使用实例变量 本实例中的线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。 修正上面的Servlet代码,将实例变量改为局部变量实现同样的功能,代码如下: ……
Public class Concurrent Test extends HttpServlet {public void service (HttpServletRequest request, HttpServletResponse
Response) throws ServletException, IOException {
Print Writer output;
String username;
Response.setContentType ("text/html; charset=gb2312");
……
}
} ** 对上面的三种方法进行测试,可以表明用它们都能设计出线程安全的Servlet程序。但是,如果一个Servlet实现了SingleThreadModel接口,Servlet引擎将为每个新的请求创建一个单独的Servlet实例,这将引起大量的系统开销。SingleThreadModel在Servlet2.4中已不再提倡使用;同样如果在程序中使用同步来保护要使用的共享的数据,也会使系统的性能大大下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量降低,而且很多客户处于阻塞状态。另外为保证主存内容和线程的工作内存中的数据的一致性,要频繁地刷新缓存,这也会大大地影响系统的性能。所以在实际的开发中也应避免或最小化 Servlet 中的同步代码;在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。
更加详细的说明:1,变量的线程安全:这里的变量指字段和共享数据(如表单参数值)。
a,将 参数变量 本地化。多线程并不共享局部变量.所以我们要尽可能的在servlet中使用局部变量。
例如:String user = "";
user = request.getParameter("user"); b,使用同步块Synchronized,防止可能异步调用的代码块。这意味着线程需要排队处理。在使用同板块的时候要尽可能的缩小同步代码的范围,不要直接在sevice方法和响应方法上使用同步,这样会严重影响性能。 2,属性的线程安全:ServletContext,HttpSession,ServletRequest对象中属性。
ServletContext:(线程是不安全的)
ServletContext是可以多线程同时读/写属性的,线程是不安全的。要对属性的读写进行同步处理或者进行深度Clone()。所以在Servlet上下文中尽可能少量保存会被修改(写)的数据,可以采取其他方式在多个Servlet中共享,比方我们可以使用单例模式来处理共享数据。
HttpSession:(线程是不安全的)
HttpSession对象在用户会话期间存在,只能在处理属于同一个Session的请求的线程中被访问,因此Session对象的属性访问理论上是线程安全的。
当用户打开多个同属于一个进程的浏览器窗口,在这些窗口的访问属于同一个Session,会出现多次请求,需要多个工作线程来处理请求,可能造成同时多线程读写属性。这时我们需要对属性的读写进行同步处理:使用同步块Synchronized和使用读/写器来解决。
ServletRequest:(线程是安全的)
对于每一个请求,由一个工作线程来执行,都会创建有一个新的ServletRequest对象,所以ServletRequest对象只能在一个线程中被访问。ServletRequest是线程安全的。注意:ServletRequest对象在service方法的范围内是有效的,不要试图在service方法结束后仍然保存请求对象的引用。 4,不要在Servlet中创建自己的线程来完成某个功能。
Servlet本身就是多线程的,在Servlet中再创建线程,将导致执行情况复杂化,出现多线程安全问题。 5,在多个servlet中对外部对象(比方文件)进行修改操作一定要加锁,做到互斥的访问。 6,javax.servlet.SingleThreadModel接口是一个标识接口,如果一个Servlet实现了这个接口,那Servlet容器将保证在一个时刻仅有一个线程可以在给定的servlet实例的service方法中执行。将其他所有请求进行排队。 PS:
Servlet并非只是单例的. 当container开始启动,或是客户端发出请求服务时,Container会按照容器的配置负责加载和实例化一个Servlet(也可以配置为多个,不过一般不这么干).不过一般来说一个servlet只会有一个实例。
1) Struts2的Action是原型,非单实例的;会对每一个请求,产生一个Action的实例来处理。
2) Struts1的Action,Spring的Ioc容器管理的bean 默认是单实例的. Struts1 Action是单实例的,spring mvc的controller也是如此。因此开发时要求必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
Spring的Ioc容器管理的bean 默认是单实例的。
Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)。
当Spring管理Struts2的Action时,bean默认是单实例的,可以通过配置参数将其设置为原型。(scope="prototype )Servlet的生命周期:1.      Servlet在web服务器启动时被加载并实例化,容器运行其init方法初始化,请求到达时运行其service方法;2.      service运行请求对应的doXXX(doGet,doPost)方法;3.      服务器销毁实例,运行其destory方法;Servlet的生命周期由Servlet容器管理;(三个概念的理解:Servlet容器<Web容器<应用服务器?Servlet容器的主要任务就是管理Servlet的生命周期;Web容器也称之为web服务器,主要任务就是管理和部署web应用的;应用服务器的功能非常强大,不仅可以管理和部署web应用,也可以部署EJB应用,实现容器管理的事务等等。。。Web服务器就是跟基于HTTP的请求打交道,而EJB容器更多是跟数据库,事务管理等服务接口交互,所以应用服务器的功能是很多的。常见的web服务器就是Tomcat,但Tomcat同样也是Servlet服务器;常见的应用服务器有WebLogic,WebSphere,但都是收费的;没有Servlet容器,可以用Web容器直接访问静态Html页面,比如安装了apache等;如果需要显示Jsp/Servlet,就需要安装一个Servlet容器;但是光有servlet容器也是不够的,它需要被解析为html显示,所以仍需要一个web容器;所以,我们常把web容器和Servlet容器视为一体,因为他们两个容器都有对方的功能实现了,都没有独立的存在了,比如tomcat!)

五.响应状态吗


http状态返回代码 1xx(临时响应)
表示临时响应并需要请求者继续执行操作的状态代码。http状态返回代码 代码   说明
100   (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
101   (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。http状态返回代码 2xx (成功)
表示成功处理了请求的状态代码。http状态返回代码 代码   说明
200   (成功)  服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
201   (已创建)  请求成功并且服务器创建了新的资源。
202   (已接受)  服务器已接受请求,但尚未处理。
203   (非授权信息)  服务器已成功处理了请求,但返回的信息可能来自另一来源。
204   (无内容)  服务器成功处理了请求,但没有返回任何内容。
205   (重置内容) 服务器成功处理了请求,但没有返回任何内容。
206   (部分内容)  服务器成功处理了部分 GET 请求。http状态返回代码 3xx (重定向)
表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。http状态返回代码 代码   说明
300   (多种选择)  针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301   (永久移动)  请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302   (临时移动)  服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303   (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304   (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
305   (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
307   (临时重定向)  服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。http状态返回代码 4xx(请求错误)
这些状态代码表示请求可能出错,妨碍了服务器的处理。http状态返回代码 代码   说明
400   (错误请求) 服务器不理解请求的语法。
401   (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
403   (禁止) 服务器拒绝请求。
404   (未找到) 服务器找不到请求的网页。
405   (方法禁用) 禁用请求中指定的方法。
406   (不接受) 无法使用请求的内容特性响应请求的网页。
407   (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
408   (请求超时)  服务器等候请求时发生超时。
409   (冲突)  服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
410   (已删除)  如果请求的资源已永久删除,服务器就会返回此响应。
411   (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
412   (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
413   (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
414   (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
415   (不支持的媒体类型) 请求的格式不受请求页面的支持。
416   (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
417   (未满足期望值) 服务器未满足"期望"请求标头字段的要求。http状态返回代码 5xx(服务器错误)
这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。http状态返回代码 代码   说明
500   (服务器内部错误)  服务器遇到错误,无法完成请求。
501   (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
502   (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503   (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
504   (网关超时)  服务器作为网关或代理,但是没有及时从上游服务器收到请求。
505   (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
一些常见的http状态返回代码为:200 - 服务器成功返回网页
404 - 请求的网页不存在
503 - 服务不可用

六.响应对象

1.概述

 当服务器收到浏览器的请求后,服务器会创建Servlet对象,也会去创建请求对象和响应对象,请求对象,会把浏览器的请求的信息封装到,请求对象里面,然后服务器,通过方式调用service()方法, 然后把请求对象和响应对象,传给该方法,你就可以在service()方法 中取出这两个对象来用。如果你要设置响应信息,你就把响应的数据设置到响应对象里面,服务器在正式响应浏览器之前,会从响应对象里面取出响应的数据,给浏览器响应回去,但这次请求响应完成之后,服务器就会这次创建的请求对象和响应对象

2.重定向

 请求对象和响应对象,由服务器创建,管理,和销毁,你只是拿来用。response:设置响应消息设置响应行: HTTP/1.1   200   oksetStatus(int code);设置响应状态码重定向  302特点:1.两次请求,两次响应2.地址栏发生变化3.不仅可以访问内部资源,也可访问外部资源代码:// 设置状态码 302 重定向response.setStatus(302);// 设置响应头 locationresponse.setHeader("location","http://127.0.0.1:8080/MyServlet/index.jsp");// 以上两步可以合成一个简便方法response.sendRedirect("http://www.baidu.com");设置响应头: 例如:content-type:text/html;charset=utf-8setHeader(String headName,String headValue); 设置响应头的名称和值setDateHeader(String name,long date); 设置日期头setIntHeader(String name,int count); 设置数字头设置响应体:响应体响应的是数据  得通过流的方式获取输出流写出数据**PrintWriter getWriter();发送字符数据的对象// 为了防止乱码,我们设置一下服务器对字符流的编码 默认服务器用的是ISO-8859-1// 所以在获取流之前告诉服务器用什么编码response.setCharacterEncoding("utf-8");//告诉浏览器我们用的是什么编码 ,好让浏览器用响应的编码去解码response.setHeader("content-type","text/html;charset=utf-8");//以上两个方法可以合二为一response.setContentType("text/html;charset=utf-8");//作用:设置字符打印输出流的编码,并告诉浏览器用相应的编码去解码**ServletOutputStream getOutputStream(); 发送字节数据的对象  // 获取字节流 用流向浏览器写出一张图片ServletOutputStream sos = response.getOutputStream();// 获取图片的真实路径String realPath = this.getServletContext().getRealPath("/302.png");// 获取输入流读取图片FileInputStream fis = new FileInputStream(new File(realPath));byte[] by = new byte[1024];int len = 0;while ((len = fis.read(by)) != -1) {sos.write(by, 0, len);}

MyServlet3.java

package org.westos.demo2;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet(name = "MyServlet3", value = "/demo3")
public class MyServlet3 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 请求对象和响应对象,由服务器创建,管理,和销毁,你只是拿来用。/**  当服务器收到浏览器的请求后,服务器会创建Servlet对象,也会去创建请求对象和响应对象,* 请求对象,会把浏览器的请求的信息封装到,请求对象里面,然后服务器,通过方式调用service()方法,* 然后把请求对象和响应对象,传给该方法,你就可以在service()方法 中取出这两个对象来用。* 如果你要设置响应信息,你就把响应的数据设置到响应对象里面,服务器在正式响应浏览器之前,会从响应对象里面取出响应* 的数据,给浏览器响应回去,但这次请求响应完成之后,服务器就会这次创建的请求对象和响应对象。*/System.out.println(request);System.out.println(response);System.out.println("servlet1,收到请求了");}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}

MyServlet4.java

package org.westos.demo2;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet(name = "MyServlet4", value = "/demo4")
public class MyServlet4 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("demo4收到请求了");//设置响应状态码response.setStatus(302);response.setHeader("location","http://www.baidu.com");//跳转到我们自己站点中的资源//response.setHeader("location", "/20200816___war_exploded/index.jsp");//response.setHeader("location", "/20200816___war_exploded/demo3");/**           重定向  302特点:1.两次请求,两次响应2.地址栏发生变化3.不仅可以访问内部资源,也可访问外部资源**** *///重定向,以上两步,综合为一步,只需调用sendRedirec()//response.sendRedirect("https://www.baidu.com");}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}

Servlet+常用头信息+响应状态码+响应对象相关推荐

  1. HTTP 响应行及响应状态码

    响应行 响应行/状态行(status line):意思是服务器响应的状态. 响应报文里的起始行. 也由三部分组成 版本号:表示报文使用的 HTTP 协议版本,通常是 HTTP/1.1 状态码:一个三位 ...

  2. HTTP响应状态码及含义

    HTTP响应状态码响应码(HTTP Status Code)代表了不同的响应情况 一. 1xx 提示信息,表示请求被接收,需要执行者继续操作,出现这种概率相对比较低. 100 表示请求者需要继续提出请 ...

  3. HTTP协议---HTTP请求中的常用请求字段和HTTP的响应状态码及响应头

    http://blog.csdn.net/qxs965266509/article/details/8082810 用于HTTP请求中的常用请求头字段 Accept:用于高速服务器,客户机支持的数据类 ...

  4. 常用HTTP响应状态码

    web应用中常用的响应状态码: 状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值: 1xx:指示信息–表示请求已接收,继续处理 2xx:成功–表示请求已被成功接收.理解.接受 3x ...

  5. iOS开发之HTTP的请求头和响应头 以及常见的响应状态码

    *************请求头************** 请求头:包含了对客户端的环境描述.客户端请求信息等 GET /minion.png HTTP/1.1   //包含了请求方法.请求资源路径 ...

  6. python构造响应头_Python爬虫库requests获取响应内容、响应状态码、响应头

    首先在程序中引入Requests模块 import requests 一.获取不同类型的响应内容 在发送请求后,服务器会返回一个响应内容,而且requests通常会自动解码响应内容 1.文本响应内容 ...

  7. python request返回的响应_Python爬虫库requests获取响应内容、响应状态码、响应头...

    首先在程序中引入Requests模块 import requests 一.获取不同类型的响应内容 在发送请求后,服务器会返回一个响应内容,而且requests通常会自动解码响应内容 1.文本响应内容 ...

  8. HTTP简介、请求方法与响应状态码

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! Https相关的文章,请看这一篇:TCP.IP协议族之数字签名与HTTPS详解 接下来想系统的回顾 ...

  9. TCP/IP协议族(一) HTTP简介、请求方法与响应状态码

    接下来想系统的回顾一下TCP/IP协议族的相关东西,当然这些东西大部分是在大学的时候学过的,但是那句话,基础的东西还是要不时的回顾回顾的.接下来的几篇博客都是关于TCP/IP协议族的,本篇博客就先简单 ...

最新文章

  1. Objective-C学习—UIWebView的使用
  2. jQuery EasyUI API 中文文档 - 数字框(NumberBox)
  3. KMP算法 串模式识别 用nextval[j]改进next[j]
  4. bootstrap方法_中介效应中的bootstrap方法
  5. 21世纪C语言(影印版)
  6. git branch看不到分支_这份Git 日常操作清单,你都用到了吗
  7. 小凡Dynamips 虚拟pc的使用
  8. golang 如何识别不同语言
  9. CardView的基本使用、DrawerLayout 滑动菜单、Fragment
  10. Linux kernel ‘aac_send_raw_srb’函数输入验证漏洞
  11. 【小玩意】锟斤拷语加密器
  12. java.sql.SQLException: Invalid utf8 character string: 'ACED00'
  13. python绘制多个散点图_绘制多个散点图熊猫
  14. TDengine集群搭建
  15. void *指针是什么含义
  16. 远程访问服务器Jupyter Notebook的两种方法
  17. 让台式机通过笔记本上网的方法
  18. 金融直播有哪些好处?直播平台有哪些?
  19. 计算机无法格式化分区,电脑硬盘无法格式化也无法分区怎么办?
  20. linux下进入bios设置u盘启动项,u盘启动g4l_u盘启动快捷键_bios设置u盘启动

热门文章

  1. 使用section.key的形式读取ini配置项
  2. java-不死神兔百钱百鸡
  3. 产品| 产品经理学习路径及职业规划
  4. 手动标记用例状态_别再用「六个点」当省略号了,这些标点都有更规范的输入方式...
  5. 划水小老虎的mysql学习路线
  6. AcWing 1714.混合牛奶
  7. 20145212 罗天晨 免杀原理与实践
  8. 编程打印如下形式的杨辉三角形,打印的杨辉三角形的行数n(不超过10行)要求由用户从键盘输入。要求按照如下函数原型进行编程,不能使用全局变量
  9. 一个员工的离职成本有多高,超出想象
  10. 微信小程序邀请判断登陆信息(邀请前做其他操作)