Servlet3.0新特性
1、注解代替配置文件
需要注意的是,如果使用Servlet3.0版本的话:首先Tomcat服务器必须使用7.0版本以上的(老版本不提供3.0版本),其次Eclipse创建Web工程时选择3.0版本。
Servlet3.0版本允许使用注解方式来替代web.xml文件中配置Servlet、Filter和Listener的信息,首先回忆一下web.xml文件是如何配置Servlet、Filter和Listener的:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<!-- 配置Servlet -->
<servlet>
<servlet-name>ServletTest</servlet-name>
<servlet-class>app.java.servlet.ServletTest</servlet-class>
<init-param>
<param-name>longestory</param-name>
<param-value>你好</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ServletTest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- 配置Filter -->
<filter>
<filter-name>FilterTest</filter-name>
<filter-class>app.java.servlet.FilterTest</filter-class>
<init-param>
<param-name>longestory</param-name>
<param-value>你好</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FilterTest</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置Listener -->
<listener>
<listener-class>app.java.servlet.ListenerTest</listener-class>
</listener>
</web-app>
使用注解替代web.xml文件配置Servlet。
@WebServlet(urlPatterns="/*",initParams={@WebInitParam(name="longestory",value="你好")},loadOnStartup=0)
public class ServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
super.doGet(req, resp);
}
}
使用注解替代web.xml文件配置Filter
@WebFilter(urlPatterns="/*",initParams={@WebInitParam(name="longestory",value="你好")})
public class FilterTest implements Filter {
@Override
public void init(FilterConfig arg0) throws ServletException {}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
}
@Override
public void destroy() {}
}
使用注解替代web.xml文件配置Listener
@WebListener
public class ListenerTest implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent arg0) {}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {}
}
TestServlet:
package app.java.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* <servlet>
* <servlet-name></servlet-name>
* <servlet-class></servlet-class>
* <init-param>
* <param-name></param-name>
* <param-value></param-value>
* </init-param>
* <load-on-startup>0-9</load-on-startup>
* </servlet>
* <servlet-mapping>
* <servlet-name></servlet-name>
* <url-pattern></url-pattern>
* </servlet-mapping>
*/
/*@WebServlet(
name="TestServlet",
urlPatterns={"/test","/atest"},
initParams={@WebInitParam(name="hcx",value="www.hcx.com")},
loadOnStartup=0
)*/
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
TestListener:
package hcx.java.servlet;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/*
* <listener>
* <listener-class></listener-class>
* <listener>
*/
//@WebListener
public class TestListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent arg0) {
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
}
}
TestFilter:
package hcx.java.servlet;
import java.io.IOException;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
/*
* <filter>
* <filter-name></filter-name>
* <filter-class></filter-class>
* <init-param>
* <param-name></param-name>
* <param-value></param-value>
* </init-param>
* </filter>
* <filter-mapping>
* <filter-name></filter-name>
* <url-pattern></url-pattern>
* </filter-mapping>
*/
/*@WebFilter(
urlPatterns={"/*"},
initParams={@WebInitParam(name="",value="")},
servletNames={"/test"},
dispatcherTypes={DispatcherType.REQUEST,DispatcherType.FORWARD}
)*/
public class TestFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
2、使用servlet实现文件上传
* @MultipartConfig
@MultipartConfig(
maxFileSize=1024*1024*3, // 设置上传单个文件大小
maxRequestSize=1024*1024*10, // 设置上传总大小
fileSizeThreshold=1024*1024*3, // 设置缓存大小
location="WEB-INF/tmp" // 设置文件上传的临时目录
)
* 利用Part接口
* 获取Part接口实例:request.getPart(name)
* 常用方法:
* 手动获取上传文件名称:
String header = part.getHeader("Content-Disposition");
int index = header.lastIndexOf("filename=\"");
String filename = header.substring(index+10, header.length()-1);
* getInputStream()方法:获取文件输入流.
* write(保存文件的路径)方法:将上传的文件输入流,写入到指定的目录中.
* 解决中文乱码:
request.setCharacterEncoding("utf-8");
Servlet3.0的另一个新特性就是提供了处理文件上传的功能,使用Servlet3.0的内容实现文件上传需要以下几个内容:
Ø 在处理文件上传的Servlet上增加@MultipartConfig注解,表示当前Servlet符合MIME类型的multipart/form-data。
|
|
|
|
|
|
|
|
Part接口,表示允许接收MIME类型是multipart/form-data类型的POST请求。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
利用Servlet3.0实现文件上传的功能,具体实现代码如下:
1.创建一个JSP页面用于文件上传显示:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<form action="uploadFile" method="post" enctype="multipart/form-data">
文件描述:<input type="text" name="filetext"><br>
<input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
</body>
</html>
2.创建一个Servlet用于处理文件上传逻辑。
@WebServlet(urlPatterns="/uploadFile")
@MultipartConfig(
fileSizeThreshold = 10 * 1024,//缓存大小,当上传的文件超出这个大小时会生成临时文件
location = "/temp",// 存放临时文件的目录
maxFileSize = 5 * 1024,// 单个文件大小限制
maxRequestSize = 10 * 1024// 整个请求大小限制
)
public class UploadFileServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 处理请求中文乱码
req.setCharacterEncoding("utf-8");
// 接收上传文件的描述内容
String filetext = req.getParameter("filetext");
// 接收上传文件的内容
Part part = req.getPart("upload");
// 获取上传文件的真实名称
String cd = part.getHeader("Content-Disposition");
int index = cd.indexOf("filename=\"") + 10;
String filename = cd.substring(index, cd.length() - 1);
// 读取上传目录的绝对路径
String path = getServletContext().getRealPath("/upload");
// 将上传文件进行保存
part.write(path + "/" + filename);
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
}
package hcx.java.upload;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet(urlPatterns={"/upload"})
@MultipartConfig(
location="\\WEB-INF\\tmp", // 设置文件上传的临时目录
fileSizeThreshold=1024*1024*3, // 设置缓存大小
maxFileSize=1024*1024*3, // 设置上传单个文件大小
maxRequestSize=1024*1024*10 // 设置上传总大小
)
public class UploadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 如何来处理文件的上传逻辑:Part接口
request.setCharacterEncoding("utf-8");
/*
* 1 如何获取文件上传的普通项?
* * 通过Request对象的getParameter(String name)方法,可以或上传的普通项.
* * name参数:指定客户端页面上传普通项的name属性值.
*/
String filetext = request.getParameter("filetext");
/*
* 2 如何获取Part接口的实例对象?
* * 通过Request对象的getPart(String name)方法,可以获取Part接口的实例对象.
* * name参数:指定客户端页面上传文件域的name属性值.
* * 通过Part接口的实例对象获取有关文件上传项的名称、文件输入流.
* * Part接口提供的write(filename)方法:
* * 将接收到的文件输入流,写入指定的服务器端的目录中.
* * 参数filename:指定的保存文件的绝对路径.
* * Part接口提供getName()方法:
* * 获取的是上传文件域的name属性值.
* * 并没有获取真实上传的文件名称.
* * 上传的真实文件名称应该是如何获取到的呢?
* * Servlet 3.0完成文件上传功能的诟病.
* *
*/
Part part = request.getPart("upload");
/*String filename = part.getName();
System.out.println(filename);*/
/*
* 获取上传的真实文件名称:
* Content-Disposition: form-data; name="upload"; filename="readme.txt"
*/
String header = part.getHeader("Content-Disposition");
int index = header.lastIndexOf("filename=\"");
String filename = header.substring(index+10, header.length()-1);
InputStream in = part.getInputStream();
String realPath = getServletContext().getRealPath("/WEB-INF/uploads");
part.write(realPath+"/"+filename);
}
}
3、servlet异步处理
所谓异步处理就是指数据发送方发送数据给数据接收方后,不必等待数据接收方作出响应,可以继续发送下一个数据的通信方式。
Servlet3.0版本提供了相关异步处理的功能,具体实现方式如下:
- 需要使用注解在对应Servlet配置asyncSupported=true,表示当前Servlet支持异步。
- 通过Request对象的startAsync(Request,Response)方法获取异步上下文对象。
- 通过异步上下文对象调用start(newRunnable(){})方法开始异步处理,Runnable类的run()方法提供具体异步的逻辑代码。
* 实现异步的步骤:
* 需要使用注解在对应Servlet配置asyncSupported=true,表示当前Servlet支持异步.
* 通过Request对象的startAsync(Request, Response)方法获取异步上下文对象.
* 通过异步上下文对象调用start(new Runnable(){})方法开始异步处理,
Runnable类的run()方法提供具体异步的逻辑代码.
* 注意:
* 目前实际情况,实现异步交互的效果,基本上都是Ajax实现.
@WebServlet(urlPatterns="/async",asyncSupported=true)
public class AsyncServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, final HttpServletResponse resp)
throws ServletException, IOException {
// 设置响应类型及编码格式
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().print("马上开始:<br/>");
// 刷新缓冲区
resp.getWriter().flush();
// 获取异步上下文对象
final AsyncContext ac = req.startAsync(req, resp);
// 开始异步处理
ac.start(new Runnable() {
@Override
public void run() {
try {
for (char ch = 'A'; ch <= 'Z'; ch++) {
resp.getWriter().print(ch);
resp.getWriter().flush();
Thread.sleep(250);
}
// 表示异步处理完毕
ac.complete();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
}
package hcx.java.async;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns={"/async"},asyncSupported=true)
public class AsyncServlet extends HttpServlet {
public void doGet(HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
// 设置响应类型及编码格式
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("马上开始:<br/>");
// 刷新缓冲区
response.getWriter().flush();
final AsyncContext context = request.startAsync(request, response);
context.start(new Runnable() {
@Override
public void run() {
try {
for (char ch = 'A'; ch <= 'Z'; ch++) {
response.getWriter().print(ch);
response.getWriter().flush();
Thread.sleep(250);
}
// 表示异步处理完毕
context.complete();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}