Servlet初了解

Servlet是什么?

Java Servlet是由Java编写的运行在服务器端上的程序,作为服务端和客户端的中间层。根据来自客户端的http请求生成动态Web内容,并由服务端将响应内容返回给客户端。通常地,Servlet作为MVC架构模式中Controller层的组件,将来自View层(html/css/jsp)的请求交给Model层处理完毕后,再将处理结果返回给View层。

Servlet体系结构

Servlet接口是所有Servlet类必须直接或间接实现的一个接口,GenericServlet抽象类是HttpServlet的父类,HttpServlet除了Servlet有的方法之外还添加了doGet、doPost、doDelete、doPut等方法处理http协议的请求。
在这里插入图片描述

Servlet接口

Servlet

ServletConfig对象

在Servlet初始化时,Servlet容器会给Servlet的init方法传入一个ServletConfig的实例,该实例中封装了当前Servlet在web.xml中的配置信息。通过此对象可以读取到web.xml配置文件< init-param >标签中的初始化参数,使程序更加灵活。

String getInitParameter(String name)	//当前Servlet获取name参数值
String getServletName()		//获取当前Servlet在web.xml中配置的名字
Enumeration getInitParameterNames()		//获取当前Servlet所有初始化参数的名字组成的枚举
ServletContext getServletContext()		//获取代表当前web应用的ServletContext对象

ServletRequest接口

对于每个http请求,Servlet容器都会创建一个封装了请求信息的ServletRequest对象,并把这个对象传递给service()方法。

int getContentLength();		//返回请求主体的字节数
String getContentType();		//返回请求主体的类型
String getParameter(String name);		//返回请求参数的值

getParameter是ServletRequest最常用的方法,通常用来返回html表单域的值,也可以获取查询字符串的值

ServletResponse接口

表示一个Servlet响应,调用Servlet的service()方法之前由Servlet容器创建,并把ServletResponse对象作为第二个参数传给service方法。

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
void setContentType(String var);
void setCharacterEncoding(String var);

GenericServlet抽象类

GenericServlet类实现了Servlet和ServletConfig两个接口,将init方法中的ServletConfig赋给了一个内部的ServletConfig来保存ServletConfig对象,让程序员不用维护该对象可直接调用getServletConfig()方法获取。此外,该类该提供了一个不带参数的init()方法让我们使用它的继承类时候直接覆盖即可,且GenericServlet类仍然保存着ServletConfig对象,使代码更具简洁性。

void init(ServletConfig servletconfig) throws ServletException
void init() throws ServletException
ServletConfig getServletConfig()

Servlet的生命周期

在这里插入图片描述
Servlet的生命周期分为5个阶段:

  • 加载:当Tomcat第一次访问Servlet的时候,Servlet容器会负责创建Servlet的实例。
  • 初始化:当Servlet被实例化后调用init()方法初始化Servlet对象,该方法只在第一次请求Servlet时调用,Servlet容器会传入一个ServletConfig对象来对Servlet初始化,后续请求中不会再被Servlet容器调用。
  • 处理服务:当服务器请求Servlet时,Servlet容器就会调用service()方法。该方法会传入一个ServletRequest对象和一个ServletResponse对象作为参数来处理请求。
  • 销毁:当要销毁Servlet时,调用destory()方法让该实例释放掉所占用的资源。一个Servlet对象长期不使用也会被自动销毁。
  • 卸载:Servlet调用销毁方法后,等待垃圾回收。下次需要Servlet时,重新调用init()方法进行初始化操作。

Servlet的使用

HttpServlet抽象类继承于GenericServlet抽象类,使用HttpServlet抽象类时,还需要借助分别代表Servlet请求和Servlet响应的HttpServletRequest和HttpServletResponse对象(由ServletRequest和ServletResponse转换而来)。

Servlet的实现方式

一般我们自定义的Servlet都是继承HttpServlet类来编写的,它实现了Servlet接口的所有方法,而且在原有接口上添加了一些与HTTP协议处理相关的方法。实现步骤有三步:

  • 继承HttpServlet类
  • 重写doGet()和doPost()方法
  • 配置web.xml(也可以使用@WebServlet注解)

在这里插入图片描述

Servlet的配置

编写一个Servlet之后,我们要配置Servlet才能让Servlet容器知道怎么访问,有两种方式配置Servlet:

  • web.xml中配置< servlet >和< servlet-mapping >两个标签
  • 注解访问Servlet
web.xml配置
<servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>org.qwb.dao.MyServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
</servlet>  
<servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
  1. 当浏览器发送请求时,发现web.xml配置文件中< url-pattern >标签的映射路径;
  2. 根据映射路径的标签值< servlet-name >进行匹配,找到Servlet编译后class文件存放的位置;
  3. 从而调用并执行相应的Servlet类
注解配置

在相应的Servlet类中添加Servlet注解,当浏览器发送请求时,在当前工程路径下寻找是否存在对应url名称的@WebServlet注解,调用并执行相应的Servlet类。

Servlet其他配置

Servlet的路径映射问题

我们可以在web.xml文件配置多个映射路径来访问用一个Servlet,如下:

<servlet>
	<servlet-name>myServlet</servlet-name>
	<servlet-class>org.qwb.dao.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>MyServlet</servlet-name>
	<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
	<servlet-name>MyServlet</servlet-name>
	<url-pattern>/qwb</url-pattern>
</servlet-mapping>

< url-pattern >中映射的url路径也可以使用两种通配符()格式,一种是*.扩展名;一种是正斜杠(/)开头并以“/”结束。由于通配符的引入有可能一个路径被多个< url-pattern >匹配,所以通配符格式访问有优先级判断:

  • 哪个精确找哪个
  • *.后缀的格式匹配级最低
<servlet>
	<servlet-name>myServlet</servlet-name>
	<servlet-class>org.qwb.dao.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>MyServlet</servlet-name>
	<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
	<servlet-name>MyServlet</servlet-name>
	<url-pattern>/*</url-pattern>
</servlet-mapping>
缺省Servlet

缺省Servlet用于处理所有其他Servlet都不处理的访问请求,将一个Servlet的< url-pattern >配置为正斜杠"/",这个Servlet就变成了缺省Servlet。第一次启动Tomcat服务器时看到的页面就是一个缺省Servlet:

<servlet>
	<servlet-name>default</servlet-name>
	<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
	<param-name>debug</param-name>
	<param-value>0</param-value>
</init-param>
<init-param>
	<param-name>listings</param-name>
	<param-value>false</param-value>
</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>default</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>
Servlet初始化参数

在Servlet的配置文件中,可以使用一个或多个< init-param >标签在< servlet >标签中为Servlet配置一些初始化参数。

load-on-startup

如果在< servlet >标签中配置了< load-on-startup >,那么Web应用程序在启动时,就会装载并创建Servlet的实例、以及调用Servlet实例对象的init()方法。

Request对象

HttpServletRequest接口扩展于javax.servlet.Servlet接口,表示Http环境中的Servlet请求。
常用API:

String getContentPath();	//返回请求上下文的请求URI部分
Cookie[] getCookies();		//返回一个cookie对象数组
String getMethod();			//返回生成这个请求http的方法名称
HttpSession getSession();	//返回与这个请求相关的会话对象

获得http请求行:

StringBuffer getRequestURL();	//返回客户端发出请求时的完整URL
String getRequestURI();			//返回请求行中的资源名部分
String getQueryString();		//返回请求行中的参数部分

获得http请求头:

String getHeader(String name);		
Enumeration getHeaders(String name);
Enumeration getHeaderNames();

获得http请求体:

String getParameter(String name);
String[] getParameterValues(String name);
Enumeration getParameterNames();
Map< String, String[] > getParameterMap();

HttpServletRequest应用

防盗链

可以调用request.getHeader("Referer")方法获取来自http请求中请求头的Referer消息头,判断消息头中的url是否是特定网站,如果不是则重定向跳转到该页面,从而实现防盗链。

获取表单的提交数据

getParameter(String name)getParameterValues(String name)两个方法可以用来获取到http请求中的请求参数,从而得到一个或多个值。

解决乱码问题

Tomcat服务器默认为ISO-8859-1编码格式,当浏览器使用UTF-8编码格式时,request用默认编码格式解码数据就会出现乱码的情况,可以用request.setCharacterEncoding("utf-8")解决post方式提交的乱码问题,get提交则用parameter = newString(parameter.getbytes("iso8859-1"), "utf-8");

Response对象

HttpServletResponse接口扩展于javax.servlet.servletResponse接口,表示Http环境中的Servlet响应。
`常用API:

void addCookie(Cookie cookie);		//给该响应添加一个Cookie
void addHeader(String var1, String var2);	//给请求添加响应头
void sendRedirect(string var) throws Exception;		//重定向
void setStatus(int var);			//设置响应行的状态码
ServletOutputStream getOutputStream() throws IOException;	//通过字节流向response写入字节并返回响应
PrintWriter getWriter() throws IOException;			//通过字符流将字符串写入response返回响应

getOutputStream()和getWriter()方法

这两个方法都是用来发送响应消息体并向客户端输出数据,但是他们之间互相排斥,不可以同时使用,否则会出现异常。

getOutputStream( )

该方法获取一个ServletOutputStream字节输出流对象,为OutputStream的子类。它通过字节流的write(byte[] bytes)向response缓冲区写入字节,getOutputStream()方法可以使用print()也可以使用write()输出数据。
**乱码问题解决:**无论使用print还是write方法,由于字节流对象输出的是二进制数据且Servlet容器的编码跟客户端浏览器的编码可能不一致,所以存在着输出乱码的问题。因此,我们可以先让服务端对response的编码方式改为utf-8,再设置http响应的消息头让浏览器自己设置utf-8的编码格式:

response.setCharacterEncoding("utf-8");		//服务端编码格式
response.setHeader("Content-Type", "text/html;charset=UTF-8");	//客户端编码格式
response.getOutputStream().write("xxxxx".getBytes("UTF-8"));
getWriter()

该方法获得一个字符流对象,通过字符流的write(String s)将字符串设置到response缓冲区中,Servlet容器再将response缓冲区的内容组装成http响应返回给客户端。

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("xxxx");

tips:setContentType是解决中文乱码问题的第二种方式,它不仅设置浏览器用utf-8显示数据,内部还把中文转码的码表设置成utf-8。

HttpServletResponse应用

文件下载

客户端可以通过访问Servlet来实现文件下载功能,从路径获取并读取到资源后把读取到的内容通过io流发送到浏览器。

String path = this.getServletContext().getRealPath("文件路径");
FileInputStream fileInputStream = new FileInputStream(path);
String fileName = path.substring(path.lastIndexOf("\\")+1);
//设置消息头,告诉浏览器要下载的资源
response.setHeader("Content-Disposition", "attachment; filename="+fileName);
//解决文件名乱码实现方式
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
//读取到的内容回送到浏览器
int len = 0;
byte[] bytes = new byte[1024];
ServletOutputStream servletOutputStream = response.getOutputStream();
while( (len = fileInputStream.read(bytes)) > 0){
	servletOutputStream.write(bytes, 0, len);
}
servletOutputStream.close();
fileInputStream.close();
实现自动刷新和自动跳转

我们可以通过修改消息头以规定的时间让页面刷新,更新资源。

response.setHeader("Refresh", "3");		//每三秒自动刷新页面一次

除了自动刷新还能实现页面的跳转,跳转到index.jsp页面:

response.setHeader("Refresh", "3;url='/index.jsp'");

ServletContext对象

Tomcat容器在启动的时候,它会为每个Web应用程序都创建一个对应的ServletContext对象,代表着当前web应用。ServletContext对象被称为域对象,可以理解为一个类似于Map集合的容器。一个web站点中的所有Servlet都共享着一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。
ServletContext的三种获取方式:

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext1 = this.getServletContext();        
        ServletContext servletContext2 = this.getServletConfig().getServletContext();
        ServletContext servletContext3 = req.getSession().getServletContext();
    }

有了ServletContext对象,就可以从应用程序的所有资料访问信息,并且可以动态注册Web对象。保存在ServletContext中的对象被称作为属性。

Servlet之间实现通讯

实现Servlet之间通讯就要用到ServletContext的setAttribute(String name, Object obj)方法,可以在整个web应用范围内共享数据。
处理属性的方法:

void setAttribute(String name, Object obj);		//存数据
Object getAttribute(String name);			//取数据
void removeAttribute(String name);			//删除数据
Enumeration<String> getAttributeNames()		//返回所有属性名的枚举类型

获取web.xml配置文件信息

使用< context-param >标签为整个web应用配置属性的话,那么所有的Servlet就能访问里面的参数(可以把数据库的配置信息放在这里)。

web.xml文件配置:

<context-param>
	<param-name>name</param-name>
	<param-value>abc</param-value>
<context-param>

配置信息的获取:

ServletContext servletContext = this.getServletContext();
String value = servletContext.getInitParameter("name");

加载资源文件

  • 在/WEB-INF/classes目录下读取文件:
    通过Servlet直接读取src目录下的文件是不行的,根据web的目录规范,Servlet编译后的class文件存放在classes文件夹内,所以要进入到classes目录中通过绝对路径读取文件,当代码模块转移需要修改代码,显得不方便。
FileInputStream fileInputStream = new FileInputStream("D:\\test\web\WEB-IN\classes\test.jpg");
``
这时,我们可以用ServletContext读取直接避免修改代码的情况,因为ServletContext对象是根据当前web站点生成的。

```java
ServletContext servletContext = this.getServletContext();
InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/test.jpg");
  • web目录下直接通过文件名读取
ServletContext servletContext = this.getServletContext();
InputStream inputStream = servletContext.getResourceAsStream("test.jpg");
  • 通过类加载器读取资源文件,文件放在src目录下。
//获取到类加载器
ClassLoader classLoader = ServletTest.class.getClassLoader();
//通过类加载器获取到读取文件流
InputStream inputStream = classLoader.getResourceAsStream("test.jpg");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值