Servlet3.0的新特性
1、新增标注支持
属性名 | 类型 | 是否可选 | 描述 |
name | String | 否 | 指定参数的名字,等价于<param-name> |
value | String | 否 | 指定参数的值,等价于<param-value> |
description | String | 是 | 指定参数的描述,等价于<description> |
package com.yyq.servlet3.annotation;
import javax.servlet.ServletConfig;
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;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by gao on 16-4-14.
*/
@WebServlet(name = "servlet3annotation", urlPatterns = {"/servlet3"},
description = "servletinfo", displayName = "abc", asyncSupported = true, loadOnStartup = -1,
initParams = {@WebInitParam(name = "username", value = "YangYuqin")})
public class Servlet3Annotation extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取ServletConfig的实例
ServletConfig config = this.getServletConfig();
//获取指定参数名称的值
String name = config.getInitParameter("username");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<html>");
out.println("<head><title>Servlet3应用实例</title></head>");
out.println("<body>");
out.print("获取InitParamServlet的初始化参数\"username\"的字符串值:" + name);
out.println("</body>");
out.println("</html>");
}
@Override
public void destroy() {
//空
}
@Override
public void init() throws ServletException {
//空
}
}
启动Tomcat,输入:http://localhost:8080/servlet3
属性名 | 类型 | 描述 |
filterName | String | 指定过滤器的name属性,等价于<filter-name> |
value | String[] | 该属性等价于urlPatterns属性,两个属性不能同时使用 |
urlPatterns | String[] | 指定一组Servlet的URL匹配模式,等价于<url-pattern>标签 |
servletNames | String[] | @WebServlet中的name属性的取值,或者是web.xml中<servlet-name>的取值 |
initParams | WebInitParam[] | 指定一组Servlet初始化参数,等价于<init-param>标签 |
dispatcherTypes | DispatcherType | 指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST |
asyncSupported | boolean | 声明过滤器是否支持异步操作模式,等价于<async-supported>标签 |
description | String | 该Servlet的描述信息,等价于<description>标签 |
displayName | String | 该Servlet的显示名,通常配合工具使用,等价于<display-name>标签 |
package com.yyq.servlet3.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
/**
* Created by gao on 16-4-14.
*/
@WebFilter(servletNames = {"servlet3filterannotation"}, filterName = "characterFilter",
initParams = {@WebInitParam(name = "encoding", value = "UTF-8")})
public class Servlet3FilterAnnotation implements Filter {
private FilterConfig filterConfig = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//获取此Filter的初始参数的值
String encoding = filterConfig.getInitParameter("encoding");
System.out.println(encoding);
//设置请求数据的编码方式
servletRequest.setCharacterEncoding(encoding);
//把请求和响应对象传给过滤链中的下一个要调用的过滤器或Servlet
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
//空
}
}
4)WebListener标注
属性名 | 类型 | 是否可选 | 描述 |
value | String | 是 | 该监听器的描述信息 |
package com.yyq.servlet3.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.LinkedList;
import java.util.List;
/**
* Created by gao on 16-4-14.
*/
@WebListener("This is the Listener")
public class Servlet3Listener implements ServletContextListener, HttpSessionAttributeListener, HttpSessionListener {
private ServletContext application = null;
//往会话中添加属性时回调的方法
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
//取得用户名列表
List<String> online = (List<String>) this.application.getAttribute("online");
if ("username".equals(httpSessionBindingEvent.getName())) {
//将当前用户名添加到列表中
online.add((String) httpSessionBindingEvent.getValue());
}
//将添加后的列表重新设置到application属性中
this.application.setAttribute("online", online);
}
//以下方法用空实现
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
//应用上下文初始化会回调的方法
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//初始化一个application对象
this.application = servletContextEvent.getServletContext();
//设置一个列表属性,用于保存在线用户名
this.application.setAttribute("online",new LinkedList<String>());
}
//会话销毁时会回调的方法
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
//取得用户名列表
List<String> online = (List<String>) this.application.getAttribute("online");
//取得当前用户名
String username = (String) httpSessionEvent.getSession().getAttribute("username");
//将此用户名从列表中删除
online.remove(username);
//将删除后的列表重新设置到application属性中
this.application.setAttribute("online", online);
}
}
登录Servlet类:
package com.yyq.servlet3.listener;
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;
import java.io.PrintWriter;
import java.util.List;
/**
* Created by gao on 16-4-14.
*/
@WebServlet(name = "servlet3login",urlPatterns = {"/login"})
public class Servlet3Login extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应内容类型
req.setCharacterEncoding("utf-8");
//获取请求参数中的用户名
String username = req.getParameter("username");
//往Session中添加属性
//会触发HttpSessionAttributeListener中的attributeAdded方法
if (username != null && !username.equals("")) {
req.getSession().setAttribute("username", username);
}
//从应用上下文中获取在线用户名列表
List<String> online = (List<String>) getServletContext().getAttribute("online");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<html>");
out.println("<head><title>用户列表</title></head>");
out.println("<body>");
out.println("当前用户是:" + username);
out.println("<hr/><h3>在线用户列表</h3>>");
int size = ((online == null) ? 0 : online.size());
for (int i = 0; i < size; i++) {
if (i > 0) {
out.println("<br />");
}
out.println(i + 1 + "." + online.get(i));
}
//注意:要对连接URL进行自动重写处理
out.println("<hr/><a href=\"" + resp.encodeURL("logout") + "\">注销</a>");
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
public void destroy() {
//空
}
@Override
public void init() throws ServletException {
//空
}
}
注销Servlet类:
package com.yyq.servlet3.listener;
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;
import java.io.PrintWriter;
import java.util.List;
/**
* Created by gao on 16-4-14.
*/
@WebServlet(name = "servlet3logout", urlPatterns = {"/logout"})
public class Servlet3Logout extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应内容类型
req.setCharacterEncoding("utf-8");
//销毁会话,会触发SessionLinstener中的sessionDestroyed方法
req.getSession().invalidate();
//从应用上下文中获取在线用户名列表
List<String> online = (List<String>)getServletContext().getAttribute("online");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<html>");
out.println("<head><title>用户列表</title></head>");
out.println("<body>");
out.print("<h3>在线用户列表</h3>");
int size = ((online == null) ? 0 : online.size());
for (int i = 0; i < size; i++) {
if (i > 0) {
out.println("<br />");
}
out.println(i + 1 + "." + online.get(i));
}
out.println("<hr><a href=\"index.jsp\">主页</hr>");
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
@Override
public void destroy() {
//空
}
@Override
public void init() throws ServletException {
//空
}
}
登录页面:index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<form action="login" method="post">
用户名:<input type="text" name="username">
<input type="submit" value="登录">
<br />
<br />
</form>
</body>
</html>
属性名 | 类型 | 是否可选 | 描述 |
fileSizeThreshold | int | 是 | 当数据量大于该值时,内容将被写入文件 |
location | String | 是 | 存放生成的文件地址 |
maxFileSize | long | 是 | 允许上传的文件最大值。默认值为-1,表示没有限制 |
maxRequestSize | long | 是 | 针对该multipart/form-data请求的最大数量,默认值为-1,表示没有限制 |
文件上传页面upload.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":"
+ request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Servlet3.0 上传文件</title>
</head>
<body>
<form action="uploadfile" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>
选择文件:
</td>
<td>
<input type="file" name="file"/>
</td>
</tr>
<tr>
<td>描述:
</td>
<td>
<input type="text" name="description"/>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="提交"/>
<input type="reset" value="重置"/>
</td>
</tr>
</table>
</form>
</body>
</html>
处理上传文件的Servlet:
package com.yyq.servlet3.multipartconfig;
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;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.UUID;
/**
* Created by gao on 16-4-14.
*/
@WebServlet(name = "upFile", urlPatterns = {"/uploadfile"})
@MultipartConfig(maxFileSize = 500000, maxRequestSize = -1)
public class FileUploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//resp.setContentType("text/html;charset=utf-8");
//获取请求参数值
Part part = req.getPart("file");
//存储路径
String storePath = req.getServletContext().getRealPath("/temp");
//Servlet3没有提供直接获取文件名,后缀名的方法,需要从请求头中解析出来
//获取请求头
String header = part.getHeader("content-disposition");
//获取文件后缀名
//String suffix = parseFileName(header);
String name = parseFileName(header);
//重新命名
//String name = UUID.randomUUID() + suffix;
//把文件写到指定路径
part.write(storePath + File.separator + name);
// PrintWriter out = resp.getWriter();
// out.println("上传成功");
// out.flush();
// out.close();
//获得文件描述信息
String description = req.getParameter("description");
req.setAttribute("f", name);
req.setAttribute("des", description);
req.getRequestDispatcher("info.jsp").forward(req, resp);
}
/*
*根据请求头解析出上传文件的后缀名称
*/
/**
* 根据请求头解析出文件名
* 请求头的格式:火狐和google浏览器下:form-data; name="file"; filename="snmp4j--api.zip"
* IE浏览器下:form-data; name="file"; filename="E:\snmp4j--api.zip"
*
* @param header 请求头
* @return 文件名
*/
public String parseFileName(String header) {
//return header.substring(header.lastIndexOf("."), header.length() - 1);
/**
* String[] tempArr1 = header.split(";");代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别
* 火狐或者google浏览器下:tempArr1={form-data,name="file",filename="snmp4j--api.zip"}
* IE浏览器下:tempArr1={form-data,name="file",filename="E:\snmp4j--api.zip"}
*/
String[] tempArr1 = header.split(";");
/**
*火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"}
*IE浏览器下:tempArr2={filename,"E:\snmp4j--api.zip"}
*/
String[] tempArr2 = tempArr1[2].split("=");
//获取文件名,兼容各种浏览器的写法
String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\") + 1).replaceAll("\"", "");
return fileName;
}
@Override
public void destroy() {
//空
}
@Override
public void init() throws ServletException {
//空
}
}
显示上传文件和描述信息的页面info.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":"
+ request.getServerPort() + path +"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Servlet3.0 上传文件</title>
</head>
<body>
<h3><%=request.getAttribute("des")%></h3>
<img alt = "servlet3" src="<%=basePath %>temp/<%=request.getAttribute("f")%>">
</body>
</html>
<servlet>
<servlet-name>DemoServlet</servlet-name>
<servlet-class>com.yyq.servlet3.asyncsupported.AsyncDemoServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
2)对于使用Servlet3.0提供的@WebServlet和@WebFilter进行Servlet或过滤器配置的情况,这两个标注都提供了asyncSupported属性,默认该属性的取值为false,要启动异步处理支持,只需将该属性设置为true即可。
package com.yyq.servlet3.asyncsupported;
import javassist.bytecode.analysis.Executor;
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;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* Created by gao on 16-4-15.
*/
@WebServlet(urlPatterns = {"/asyncdemo"}, asyncSupported = true)
public class AsyncDemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("进入Servlet的时间:" + new Date() + ".");
out.flush();
//在子线程中执行业务调用,并由其负责输出响应,主线程退出
AsyncContext ctx = req.startAsync();
new Thread(new Executor(ctx)).start();
out.println("结束Servlet的时间:" + new Date() + ".");
out.flush();
}
public class Executor implements Runnable {
private AsyncContext ctx = null;
public Executor(AsyncContext ctx) {
this.ctx = ctx;
}
public void run() {
try {
//等待10秒钟,以模拟业务方法的执行
Thread.sleep(10000);
PrintWriter out = ctx.getResponse().getWriter();
out.println("业务处理完毕的时间:" + new Date() + ".");
out.flush();
ctx.complete();
}catch (Exception e){
e.printStackTrace();
}
}
}
@Override
public void destroy() {
//空
}
@Override
public void init() throws ServletException {
//空
}
}
启动Tomcat,输入:http://localhost:8080/asyncdemo
package com.yyq.servlet3.pluggability;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by gao on 16-4-15.
*/
public class FragmentDemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("这是我Servlet3.0的第一个可插性示例");
out.flush();
}
@Override
public void destroy() {
//空
}
@Override
public void init() throws ServletException {
//空
}
}
2)在web目录下新建一个目录META-INF,在该目录下新建一个web-fragment.xml模块部署描述符文件片段:
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
metadata-complete="true">
<!--给当前配置文件定义一个名称-->
<name>FragmentA</name>
<servlet>
<servlet-name>fragmentDemo</servlet-name>
<servlet-class>com.yyq.servlet3.pluggability.FragmentDemoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>fragmentDemo</servlet-name>
<url-pattern>/fragment</url-pattern>
</servlet-mapping>
</web-fragment>
Servlet3.0的新特性的更多相关文章
- servlet3.0 的新特性之二注解代替了web.xml配置文件
servlet3.0 的新特性: 注解代替了 web.xml 文件 支持了对异步的处理 对上传文件的支持 1.注解代替了配置文件 1.删除了web.xml 文件 2. 在Servlet类上添加@Web ...
- 项目支持Servlet3.0的新特性
一.Servlet3.0介绍 Servlet3.0是Java EE6规范的一部分,Servlet3.0提供了注解(annotation),使得不再需要在web.xml文件中进行Servlet的部署描述 ...
- php5.3到php7.0.x新特性介绍
<?php /*php5.3*/ echo '<hr>'; const MYTT = 'aaa'; #print_r(get_defined_constants()); /* 5.4 ...
- paip.php 5.0 5.3 5.4 5.5 -6.0的新特性总结与比较
paip.php 5.0 5.3 5.4 5.5 -6.0的新特性总结与比较 PHP5的新特性 2 · 对象的参照过渡是默认的(default) 3 · 引入访问属性的限制 3 · 引入访问方法的限 ...
- NodeJS 框架 Express 从 3.0升级至4.0的新特性
NodeJS 框架 Express 从 3.0升级至4.0的新特性 [原文地址:√https://scotch.io/bar-talk/expressjs-4-0-new-features-and-u ...
- 相比于python2.6,python3.0的新特性。
这篇文章主要介绍了相比于python2.6,python3.0的新特性.更详细的介绍请参见python3.0的文档. Common Stumbling Blocks 本段简单的列出容易使人出错的变动. ...
- MySQL 8.0 InnoDB新特性
MySQL 8.0 InnoDB新特性 1.数据字典全部采用InnoDB引擎存储,支持DDL原子性.crash safe,metadata管理更完善 2.快速在线加新列(腾讯互娱DBA团队贡献) 3. ...
- Atitit jquery 1.4--v1.11 v1.12 v2.0 3.0 的新特性
Atitit jquery 1.4--v1.11 v1.12 v2.0 3.0 的新特性 1.1. Jquery1.12 jQuery 2.2 和 1.12 新版本发布 - OPEN资讯.h ...
- [PHP] 从PHP 5.6.x 移植到 PHP 7.0.x新特性
从PHP 5.6.x 移植到 PHP 7.0.x 新特性: 1.标量类型声明 字符串(string), 整数 (int), 浮点数 (float), 布尔值 (bool),callable,array ...
随机推荐
- MySQL 多实例给root用户创建密码
DB:5.5.14 OS:CentOS 6.3 安装多实例MySQL数据库,安装完成后默认无密码,一次性给所有实例的root账户创建密码: #!/bin/bash for i in {3361..3 ...
- c语言调试接口
http://blog.chinaunix.net/uid-10106787-id-2985587.html 在C语言程序设计中,常会出现各种各样的bug:段错误.参数异常等等.我们需要尽快定位错误, ...
- OPatch failed with error code 73
前几天给一套LINUX下的RAC数据库打补丁升级,有一台机器更新失败了,相关的异常内容如下: Restoring "/u01/app/oracle/11.2.0/db_1" to ...
- docker 感性介绍
Docker 允许开发者们将他们的应用打包放在云端的“容器”中,无需再修改就可以发布到任何流行的 Linux 机器上.由于采用沙盒机制,各应用之间没有任何接口,所以不用担心它们会相互干扰.也同样因为这 ...
- mac下wget用来仿站
wget -c -r -np -k -L -p http://www.domain.com 参考 http://www.v2ex.com/t/147870
- [转]宏的高级使用--##,__VA_ARGS__, __FILE__, __FUNCTION__等
[转]宏的高级使用--##,__VA_ARGS__, __FILE__, __FUNCTION__等 http://blog.csdn.net/yiya1989/article/details/784 ...
- ASP.NET MVC +EasyUI 权限设计(二)环境搭建
请注明转载地址:http://www.cnblogs.com/arhat 今天突然发现博客园出问题了,老魏使用了PC,手机,平板都访问博客园了,都是不能正常的访问,原因是不能加载CSS,也就是不能访问 ...
- InnoDB与UUID
CakePHP本身有一个uuid实现,所以一直以来,我都在尝试使用uuid做主键的可能性.虽然MySQL是我最常用的数据库,但是和 auto_increment_int主键相比,我对uuid主键更有好 ...
- HTML特殊转义字符对照表
字符 十进制 转义字符 字符 十进制 转义字符 字符 十进制 转义字符 ? ¡ ¡ Á Á Á á á á ¢ ¢ ¢ Â Â ˆ â â £ £ £ Ã Ã Ã ã ã ã ¤ ¤ ¤ Ä Ä &a ...
- 【转】KM匹配题集
转自:http://blog.csdn.net/shahdza/article/details/7779324 [HDU]2255 奔小康赚大钱 模板题★1533 Going Home 模板题★242 ...