Servlet技术
Servlet规范是JavaEE规范中的一个部分,是用于扩展服务器功能的运行在服务器中的小型Java程序(即服务器端小应用程序),是实现了Servlet接口通过http接收和响应web客户端请求的类。
静态和动态
因人因时因地而发生变化
服务器
web服务器:定位资源—Apache
jsp/servlet容器:运行jsp或者servlet程序—Tomcat
Servlet概述
Servlet是一种用于扩展服务器功能的服务器端组件技术
- 要求直接或者间接的实现Servlet接口
- 运行在服务器端,执行结果是一个html文档
Servlet的体系结构
Servlet – 接口
|
GenericServlet – 抽象类
|
HttpServlet – 抽象类
-
GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
* 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可 -
HttpServlet:对http协议的一种封装,简化操作
1. 定义类继承HttpServlet
2. 复写doGet/doPost方法
Servlet相关配置
urlpartten:Servlet访问路径
1. 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})
2. 路径定义规则:
1. /xxx:路径匹配
2. /xxx/xxx:多层路径,目录结构
3. *.do:扩展名匹配
ServletAPI有4个包,如下:
javax.servlet :包含定义了Servlet与Servlet容器之间签约的类和接口。
javax.servlet.http : 包含定义了HttpServlet与与Servlet容器之间签约的类和接口。
javax.servlet.annotation :包含对Servlet、Filter和Listener进行标注的注解。即Servlet3.0的注解配置。
javax.servlet.descriptor:包含为Web应用的配置信息提供编程式访问的类型。
Servlet接口的5个方法
init() //创建servlet实例时,初始化servlet参数。
service() //根据请求方式,处理客户端请求,并发出响应结果。
destroy() //Web应用销毁(停止运行)时,执行该方法。通常用于回收资源。
getServletConfig() //返回一个ServletConfig对象,该对象表示Servlet配置信息。
getServletInfo() //返回关于该Servlet的说明信息。
Servlet生命周期
init()、service()和destroy()分别对应Servlet的三个阶段:初始化阶段、运行时阶段和销毁阶段。
对应如下的Servlet执行流程:当客户端向某个Web服务器发出请求,Tomcat(Servlet容器)接收并解析HTTP请求,然后调用匹配请求的Servlet类。
- 1.创建Servlet实例,执行init()完成初始化,Servlet容器传入一个ServletConfig对象。
- 2.根据请求方式,调用相应的响应方法(doGet()、doPost()或service()),传入包含请求信息的HttpServletRequest对象和用于响应的HttpServletResponse对象,生成响应结果。
- 3.Servlet容器将响应结果发送给客户端,然后执行destroy()方法,销毁和该Servlet有关的对象。例如请求对象、响应对象以及ServletConfig。至此,Servlet的生命周期结束。
额外说明: 创建Servlet实例有两种时机:
1.客户端发起请求,相应的Servlet实例才开始创建。
2.Web应用一启动,就创建Servlet实例,这里方式需要配置一下:< servlet >中配置< load-on-startup >1< /load-on-startup >,值越小,实例化优先级越高。注解配置Servlet,指定参数loadOnStartup = 1。
关于Servlet初始化参数和Web应用的上下文参数的配置方式,在web.xml文件中:
<!-- Web应用参数,可以被Web应用中所有Servlet所共享 --> //使用注解配置初始化参数
<context-param> @WebServlet(urlPatterns= {"/瞎写的URL"}, name="arbitrary",
<param-name>movement</param-name> initParams= {
<param-value>10086</param-value> @WebInitParam(name="admin", value="牛批"),
</context-param> @WebInitParam(name="info", value="10086")
<context-param> }
<param-name>railway</param-name> )
<param-value>12306</param-value> public class InitParamServlet extends HttpServlet{
</context-param> //省略执行代码.....
<servlet> }
<servlet-name>ServletConfig_Context_Test</servlet-name>
<servlet-class>com.test.ServletConfig_Context_Test</servlet-class>
<!-- Servlet的初始化参数 -->
<init-param>
<param-name>sevletConfig01</param-name>
<param-value>测试servlet配置信息</param-value>
</init-param>
</servlet>
Servlet四个对象的常用方法说明
HttpServletRequest
1、获取请求参数 getParameter(),请求参数有多个值 getParameterValues()
获取单个请求头信息 getHeader() 获取所有请求头名称:getHeaderNames(),之后选择遍历。
获取和存取request范围中的数据, getAttribute(str, object) setAttribute(str, object)
get:使用地址的方式传递数据,实际上使用的是协议头,上限2k
http://localhost:8080/test/del.do?id=123&name=lisi其中id=123&name=lisi就是请求参数
post:使用协议体传递数据,默认格式还是id=123&name=lisi,只是不在地址栏中出现,一般用于敏感
数据传递或者上传大于2k的数据
2、以流的方式处理请求信息
InputStream is=request.getInputStream();
BufferedReader br=request.getReader();
上传文件
- 要求使用post提交数据,必须设置enctype=“multipart/form-data”
<form action="test.do" method="post" enctype="multipart/form-data"> 注意表单中的
post必须设置,因为默认为get;必须设置enctype,因为默认值application/x-www-formurlencoded
<input type="file" name="photo"/>
<input type="submit" value="上传文件"/>
</form>
- jspSmartUp组件是一种早期流行使用的上传下载工具,适合于上传小型的文件,具有灵活性简单高
效。
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter pw=response.getWriter();
SmartUpload su=new SmartUpload();//创建上传组件对象
su.initialize(this.getServletConfig(),request,response);//初始化上传组件
su.setMaxFileSize(2*1024*1024); //设置允许上传的文件最大大小,单位字节,一般设
置为2M
su.setAllowedFilesList("jpg,png,gif");//设置允许上传的文件后缀类型
try {
su.upload();//上传文件,将文件从客户端上传到服务器,如果上传文件不符合要求,则包
异常
//SmartUpload组件支持多文件上传
Files files=su.getFiles();//获取所有的上传文件
if(files!=null && files.getCount()>0){//判断上传文件个数是否大于0
File file=files.getFile(0);//获取第一个上传文件
System.out.println(file.getFileName());
String ss=request.getRealPath(""); //获取当前目录的绝对路径,一般推荐
通过application对象获取,不建议使用request对象获取
System.out.println(ss);
file.saveAs("upload/"+file.getFileName()); //使用的是相对路径,相对
于ss的路径
}
pw.println("上传上传,点<a href='abc.html'>这里</a>继续上传")
} catch (Exception e){
e.printStackTrace(pw);
pw.println("<a href='abc.html'>重新上传</a>");
}
pw.flush();
pw.close();
}
3、下载处理
- 列表显示所有的可下载内容
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
String ss=request.getRealPath("upload/"); //获取upload文件夹的绝对路径
File ff=new File(ss);
if(ff.exists()){
File[] fs=ff.listFiles();
if(fs!=null && fs.length>0){
for(File tmp:fs)
out.println("<a href='down.do?fname="+tmp.getName()+"'><img
src='upload/"+tmp.getName()+"' width='80' height='60'></a>");
}
}
out.flush();
out.close();
}
- 下载处理要点:告知浏览器以附件的方式打开响应数据,响应头的名称Content-Disposition,对应的值为attachment;filename=FileName.txt
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
String fname=request.getParameter("fname");
String ss=request.getRealPath("upload/");
File ff=new File(ss,fname);
InputStream is=new BufferedInputStream(new FileInputStream(ff));
response.setHeader("Content-Disposition","attachment;filename=abc.png");
OutputStream outputStream=response.getOutputStream();
byte[] buffer=new byte[8192];
int len=0;
while((len=is.read(buffer))>0)
outputStream.write(buffer,0,len);
outputStream.close();
is.close();
}
3、请求头参数
编程实现获取请求头数据
String val=request.getHeader("Accept"); //根据名称获取指定的请求头数据,数据类型一般有3
种,默认String,还有int和date
//获取所有的请求头名称的迭代器
Enumeration<String> names= request.getHeaderNames();
while(names.hasMoreElements()){
String name=names.nextElement();
String value=request.getHeader(name);
System.out.println(name+"-->"+value);
HttpServletResponse
是由服务器传递给客户端浏览器的额外数据
setContentType() 设置响应内容类型
setCharacterEncoding(arg0); 设置响应正文字符集
getWriter() 获取一个字符流,向响应正文中输出字符数据。 getOutputStream() 向响应正文中输出二进制数据
addCookie() 往响应正文中添加一个Cookie.
sendRedirect(url) 重定向
- 设置响应头
response.setHeader("Content-Disposition","attachment;filename=abc.png"); //告知浏
览器,以附件的方式打开响应数据
Expires: 日期数据 用于设置响应内容类型的缓存过期时间
Date now=new Date();
//例如允许缓存1个月
now=new Date(now.getTime()+1*30*24*60*60*1000);
response.setDateHeader("Expires",now.getTime());
//是否开启缓存
响应头名称Cache-Control,值no-cache表示不缓存数据
写法2:Pragma的值为no-cache时表示禁用缓存,这是一个逐步需要放弃的写法
//禁用缓存
response.setHeader("Pragma","no-cache"); //针对http1.0禁用缓存
response.setHeader("Cache-Control","no-cache"); //针
ServletConfig和ServletContext获取参数都是使用getInitParameter(),只不过一个是获取Servlet初始化参数,一个是Web应用参数。
注意:在Servlet中调用getServletConfig()和getServletContext()方法,需要在响应方法中获取,不然会导致空指针。若在方法外调用,则需要建立一个ServletConfig变量,执行init()时进行赋值,然后再通过建立的ServletConfig变量调用getServletContext(),
这样才不会导致NullPointerException
四个作用域对象的范围
ServletContext对象,通过getServletContext()。范围在整个Web应用。 对应jsp的application对象
HttpSession对象,通过request.getSession()。范围在会话中。 对应jsp的session对象,Session很常用,要熟悉。
request对象,响应方法的参数直接提供。 范围在一次请求中。 对应jsp的request对象
this对象,当前Servlet类,范围仅限于类中。 对应jsp的page对象
Servlet的转发、包含和重定向
HttpServletRequest.getRequestDispatcher("URL").forward(request, response); //跳转到指定URL,本质上是将目标URL页面内容替换当前页面。
HttpServletRequest.getRequestDispatcher("URL").include(request, response); //把目标URL内容包含到当前URL页面内容中,等同于嵌入。
HttpServletResponse.sendRedirect(“URL”); //重定向到指定URL地址,会改变URL地址,相当于打开一个新网页。