Servlet基本内容
Servlet通过Http协议接收和响应来自客户端的请求。
实际开发中我们创建Servlet类的话直接在eclipse中创建Servlet就很便捷,IDE工具会自动帮我们继承HttpServlet类,并且下面会给出覆写类的选项,根据需要选择需要覆写的类比较方便。
点击next会来到xml文件的配置选项页面:
可以看到我们可以填写Servlet名字、映射路径、web.xml文件路径等,这些eclipse会根据上一步的配置自动填写,我们可以根据需要更改,点击finish即完成Servlet的创建。
我们将上面Servlet文件创建完成并放到服务器上,本机访问地址为:
http://localhost:8080/session_test/servlet/SessionDemo1
http协议 本机地址:端口号 项目目录 Servlet自动生成的映射目录(因为我没有修改)
我们在访问的时候会经历一下步骤:
1.浏览器访问tomcat服务器
2.服务器找到session_test应用
3.在web.xml文件中找到映射路径/servlet/SessionDemo1
4.由映射路径找到对应的对应servlet对应java类
5.找到java类SessionDemo1,并实例化
6.调用init(ServletConfig config)方法
7.调用service(ServletRequest req, ServletResponse res)方法
8.将消息响应给客户端服务器
9.关闭服务器或者重新部署的时候时会调用destroy()方法
Servlet体系结构
Servlet是一个接口。其待实现方法如下:
void |
destroy() Called by the servlet container to indicate to a servlet that the servlet is being taken out of service. |
ServletConfig |
getServletConfig() Returns a ServletConfig object, which contains initialization and startup parameters for this servlet. |
String |
getServletInfo() Returns information about the servlet, such as author, version, and copyright. |
void |
init(ServletConfig config) Called by the servlet container to indicate to a servlet that the servlet is being placed into service. |
void |
service(ServletRequest req, ServletResponse res) Called by the servlet container to allow the servlet to respond to a request. |
创建Servlet的方法有三种:
①创建一个类实现Servlet接口并重写所有方法
②创建一个类继承GenericServlet抽象类。GenericServlet类实现了Servlet接口、ServletConfig接口以及java.io.Serializable接口。
③创建一个类继承HttpServlet类。这个类继承了GenericServlet类。
三个类之间的关系也可以从源码中看出:Servlet..源码粘贴 。
Servlet总体继承实现关系如下:
Servlet全靠这张图了,很重要!!!!!!!!!
自动生成的Servlet会带有很多说明和参数我们可以:找到MyEclipse\Common\plugins目录,找或在百度下载下面的jar包:com.genuitec.eclipse.wizards_9.0.0.me201108091322.jar复制到上面目录,可以让我们创建的Servlet更简洁。
Servlet映射
访问步骤里已经给出了映射的基本模式——<Servlet-mapping>标签配置地址映射到<servlet>中的java类。
下面还要说的是多映射&&映射通配符:
多映射<servlet-mapping>拥有等同于一个<servlet>中的<servlet-name>的值,但是各个<servlet-mapping>的<url-pattern>内对应多个路径,即我们可以通过配置的不同路径来访问同一个Servlet。
映射通配 写在url-pattern标签 *代表通配任意字符串 /*任意字符串都可以访问 /action/*以/action开头的请求都可以访问 *.do 以*.字符串的请求都可以访问
通配优先级:绝对匹配> /开头匹配> 扩展名方式匹配
Servlet安全
Servlet是多线程的,存在线程安全问题,如果需要定义变量我们最好不要定义全局变量,这样可以避免使用公共条件,使用局部变量就不存在安全问题了。
ServletConfig接口——Servlet获取配置信息
String |
getInitParameter(String name) 返回包含指定初始化参数值的String,如果参数不存在,则返回null。 |
Enumeration |
getInitParameterNames() 以Enumeration of String对象的形式返回servlet的初始化参数的名称,如果servlet没有初始化参数,则返回空的Enumeration。 |
ServletContext |
getServletContext() 返回对调用者正在执行的ServletContext的引用。 |
String |
getServletName() 返回此servlet实例的名称。 |
我们定义一个全局变量和init(ServletConfig config)方法中的config对应。
作用一:可以在doGet方法中取出初始化的配置对象,通过调用上面的方法获取需要的配置参数参数。
作用二:可以获取ServletContext对象
ServletContext接口——代表整个应用
ServletContext对象包含在ServletConfig对象中,ServletConfig对象在初始化servlet时由Web服务器提供给servlet。ServletContext是单实例,一个应用只能有一个此对象。
void setAttribute(String name,object value) | 向ServletContext对象的map中添加数据 |
Object getAttribute(String name); | 从ServletContext对象的map中取数据 |
void removeAttribute(String name); | 根据name去移除数据 |
获取全局配置信息
首先在web.xml文件中设置全局信息:
<!-- 配置当前应用的全局信息 -->
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
在doGet方法中获取全局信息encoding的值UTF-8,并打印:
String encoding = this.getServletContext().getInitParameter("encoding");
System.out.println(encoding);
说明:getInitParameter(String name)这个方法来自于ServletContext接口,返回值是枚举字符串类型。
获取资源路径
getRealPath(String path) | 返回包含给定虚拟路径的实际路径的String |
虚拟路径:应用目录的下一个目录WEB-INF后,如:/WEB-INF/classes/b.properties。可以得到当前应用任何位置的任何资源。
请求转发
注意:这里的String必须以“/”开始 |
返回一个RequestDispatcher对象,请求转发,将请求传递 |
ServletContext application = this.getServletContext();
//将请求向下传递
application.getRequestDispatcher("/servlet/demo6").forward(request, response);
Response和Request
response是服务器给客户端的响应对象,request是客户端给服务器的请求对象。
请求和响应消息分为三种:消息头、消息行、消息正文。
HttpServletResponse继承自ServletResponse
设置响应消息头:
//告诉服务器应用使用UTF-8解析文本
response.setCharacterEncoding("UTF-8");
//告诉客户端要使用什么编码
response.setHeader("content-type", "text/html;charset=UTF-8");
setCharacterEncoding(String)这个方法来自于ServletResponse接口。
setHeader(String name,String value)这个方法来自于HttpServletResponse类。可以用于设置消息头
//告诉服务器应用使用UTF-8解析文本,告诉客户端要使用什么编码
response.setContentType("text/html; charset=UTF-8");
下面是一个下载图片的demo:
package com.itheima.servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//通过路径得到一个输入流
String path = this.getServletContext().getRealPath("/WEB-INF/classes/美女.jpg");
FileInputStream fis = new FileInputStream(path);
//创建字节输出流
ServletOutputStream sos = response.getOutputStream();
//得到要下载的文件名
String filename = path.substring(path.lastIndexOf("\\")+1);//字符串切割。从最后一个“/”+1的位置作为开始分割到完
//设置文件名的编码
filename = URLEncoder.encode(filename, "UTF-8");//将不安全的文件名改为UTF-8格式
//设置相应消息头,告知客户端要下载的文件名,文件类型
response.setHeader("content-disposition", "attachment;filename="+filename);
response.setHeader("content-type", "image/jpeg");
//执行输出操作
int len = 1;
byte[] b = new byte[1024];
while((len=fis.read(b))!=-1){
sos.write(b,0,len);
}
sos.close();
fis.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
下面是一个基于Servlet的验证码demo:
下面是一个刷新跳转的demo的主要部分代码:
response.getWriter().write("注册成功!3秒钟跳到主页");
//设置3秒钟跳转
response.setHeader("refresh", "3;url=/day09_00_HttpServletResponse/servlet/demo6");
url是跳转的另一个Servlet的url。
重定向
HTTPServletResponse类中有一个方法:sendRedirect(String location)可以设置请求重定向。重定向的特点是不会保存表单数据,需要访问两个Servlet,有别于请求转发。参数location是重定向的资源的全路径。执行顺序是先执行完当前Servlet中的内容再进入到重定向的Servlet执行里面的内容。
演示demo:
package com.itheima.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo7 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("A:我要借钱!");
System.out.println("B:我不有,但是我可以告诉你谁有");
/*//告诉客户端要重新定向新的资源
response.setStatus(302);
//告诉浏览器要去访问哪个URL
response.setHeader("location", "/day09_00_HttpServletResponse/servlet/demo8");*/
//请求重定向
response.sendRedirect("/day09_00_HttpServletResponse/servlet/demo8");
System.out.println("A: 我去了");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
执行结果:
我有钱,我借你! 这句话是来自转发的servlet的。验证了执行顺序。
HttpServletRequset继承自ServletRequest
response对象大多执行set和add方法,request对象大多执行get类方法,是客户端获取来自服务器端的http协议传输内容的方法。
常用重要get方法:
// getMethod(); 获得请求方式
// ***getRequestURL();返回客户端发出请求时的完整URL。
// ***getRequestURI(); 返回请求行中的资源名部分。
// *****getContextPath(); 当前应用的虚拟目录 /day09_01_HttpServletRequest
// getQueryString() ; 返回请求行中的参数部分。
System.out.println(request.getMethod());// GET
System.out.println(request.getRequestURL()); // http://localhost:8080/day09_01_HttpServletRequest/servlet/demo1
System.out.println(request.getRequestURI()); // /day09_01_HttpServletRequest/servlet/demo1
System.out.println(request.getContextPath()); // /day09_01_HttpServletRequest
System.out.println(request.getQueryString()); // username=tom
还有一个重要的是获取消息头:getHeader(String name) getHeaders(String name)
getHeaders方法返回的是枚举字符串类型,我们需要遍历显示,主要代码如下:
Enumeration headers = request.getHeaders("accept-language");
while(headers.hasMoreElements()){
String e = (String) headers.nextElement();
System.out.println(e+":"+request.getHeader(e));
}
Servlet的作用:
1.获取表单数据
2.处理业务逻辑
3.分发转向
Servlet写html页面需要很多的代码,是个体力活,所以下面引入jsp——既可以写静态内容又可以嵌套java代码。但是jsp虽然适合编写输出动态内容,但是不适合编写java逻辑。