Servlet 3.0新特性
与Servlet2.5相比Servlet3.0对我们的Web开发工作做了很多简化,主要体现在很多以前需要大段xml配置的地方,现在只需要一个简单的注解就可以搞定
第二点提现在文件上传上,Servlet3.0以前我们要实现文件上传需要借助apache的fileupload包,Servlet3.0之后官方增加了Part方式和@MultipartConfig注解,可以让我们不需要借助任何第三方的包就可以很简便的实现文件上传
Annotation(注解)支持
@WebServlet
用于将一个类声明为 Servlet,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet。该注解具有下表给出的一些常用属性(以下所有属性均为可选属性,但是 vlaue 或者 urlPatterns 通常是必需的,且二者不能共存,如果同时指定,通常是忽略 value 的取值):
属性名 | 类型 | 描述 |
---|---|---|
name | String | 指定 Servlet 的 name 属性,等价于 。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。 |
value | String[] | 该属性等价于 urlPatterns 属性。两个属性不能同时使用。 |
urlPatterns | String[] | 指定一组 Servlet 的 URL 匹配模式。等价于 标签。 |
loadOnStartup | int | 指定 Servlet 的加载顺序,等价于 标签。 |
initParams | WebInitParam[] | 指定一组 Servlet 初始化参数,等价于 标签。 |
asyncSupported | boolean | 声明 Servlet 是否支持异步操作模式,等价于 标签。 |
description | String | 该 Servlet 的描述信息,等价于 标签。 |
displayName | String | 该 Servlet 的显示名,通常配合工具使用,等价于 <dis |
简单示例代码:
@WebServlet(name="HelloServlet" ,urlPatterns={"/HelloServlet"},loadOnStartup=1,
initParams={
@WebInitParam(name="name",value="xiazdong"),
@WebInitParam(name="age",value="20")
})
相当于2.5中在web.xml中配置:
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.demo.HelloServlet</servlet-class>
<load-on-startup>-1</load-on-startup>
<async-supported>true</async-supported>
<init-param>
<param-name>name</param-name>
<param-value>xiazdong</param-value>
</init-param>
<init-param>
<param-name>age</param-name>
<param-value>20</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
@WebFilter
用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。该注解具有下表给出的一些常用属性 ( 以下所有属性均为可选属性,但是 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值 ):
属性名 | 类型 | 描述 |
---|---|---|
filterName | String | 指定过滤器的 name 属性,等价于 |
value | String[] | 该属性等价于 urlPatterns 属性。但是两者不应该同时使用。 |
urlPatterns | String[] | 指定一组过滤器的 URL 匹配模式。等价于 标签。 |
servletNames | String[] | 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 的取值。 |
dispatcherTypes | DispatcherType | 指定过滤器的转发模式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。 |
initParams | WebInitParam[] | 指定一组过滤器初始化参数,等价于 标签。 |
asyncSupported | boolean | 声明过滤器是否支持异步操作模式,等价于 标签。 |
description | String | 该过滤器的描述信息,等价于 标签。 |
displayName | String | 该过滤器的显示名,通常配合工具使用,等价于 < |
简单示例:
@WebFilter(filterName="",urlPattern={"/"});
@WebInitParam
该注解通常不单独使用,而是配合 @WebServlet 或者 @WebFilter 使用。它的作用是为 Servlet 或者过滤器指定初始化参数,这等价于 web.xml 中 <servlet> 和 <filter> 的 <init-param> 子标签。@WebInitParam 具有下表给出的一些常用属性:
属性名 | 类型 | 是否可选 | 描述 |
---|---|---|---|
name | String | 否 | 指定参数的名字,等价于 。 |
value | String | 否 | 指定参数的值,等价于 。 |
description | String | 是 |
@WebListener
原本需要在web.xml中配置的<listener>标签,在3.0中我们只要往Java类上面添加@WebListener注解就可以了
属性名 | 类型 | 是否可选 | 描述 |
---|---|---|---|
value | String | 是 | 该监听器的描述信息。 |
该注解用于将类声明为监听器,被 @WebListener 标注的类必须实现以下至少一个接口:
- ServletContextListener
- ServletContextAttributeListener
- ServletRequestListener
- ServletRequestAttributeListener
- HttpSessionListener
- HttpSessionAttributeListener
示例代码:
@WebListener("This is only a demo listener")
public class SimpleListener implements ServletContextListener{...}
相当于2.5中的
<listener>
<listener-class>footmark.servlet.SimpleListener</listener-class>
</listener>
@MultipartConfig
这个注解用于开启文件上传功能,属性值如下:
属性名 | 类型 | 是否可选 | 描述 |
---|---|---|---|
fileSizeThreshold | int | 是 | 当数据量大于该值时,内容将被写入文件。 |
location | String | 是 | 存放生成的文件地址。 |
maxFileSize | long | 是 | 允许上传的文件最大值。默认值为 -1,表示没有限制。 |
maxRequestSize | long | 是 | 针对该 multipart/form-data 请求的最大数量,默认值为 -1,表示没有限制。 |
具体用法,请参见文件上传
文件上传
在Servlet3.0之前我们要想实现文件上传必须借助common-fileupload或者SmartUpload,上传过程比较麻烦。而到了Servlet3.0,我们不需要导入任何第三方jar包,并且提供了很方便进行文件上传的功能
主要步骤如下:
- 在需要实现文件上传的Servlet类前加上@MultipartConfig注解
- 通过request.getPart()获得上传的文件,以及文件相关的各种属性
- 通过part.write()将上传的文件写到服务器
客户端代码:
<html>
<body>
<form method="post" enctype="multipart/form-data" action="upload">
<input type="file" id="file" name="file"/>
<input type="text" id="name" name="name"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
服务端代码:
package com.lanou3g.demo;
import java.io.IOException;
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;
/**
* Servlet3.0 上传方式 不需要依赖任何第三方jar包(fileupload、io)
*
* @author John
*/
@WebServlet("/Upload3Servlet")
@MultipartConfig(
// 设置内存临界值 - 超过后将会产生临时文件并存储于临时目录中
// 相当于2.5里面的 factory.setSizeThreshold(MAX_Threshold_SIZE);
fileSizeThreshold = 2 * 1024 * 1024,
// 设置临时存储目录
// 相当于2.5里的 factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
location = "",
// 设置能上传多大的文件(单位:byte)
// 相当于2.5里的 upload.setFileSizeMax(MAX_FILE_SIZE);
maxFileSize = 3 * 1024 * 1024,
// 设置最大请求值 (包含文件和表单数据)
// 相当于2.5里的 upload.setSizeMax(MAX_REQUEST_SIZE);
maxRequestSize = 5 * 1024 * 1024
)
@SuppressWarnings("serial")
public class Upload3Servlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Part part = req.getPart("myFile");
String fileName = part.getSubmittedFileName();
part.write(getUploadPath(fileName));
}
public String getUploadPath(String fileName) {
return getServletContext().getRealPath("/upload") + "/" + fileName;
}
}
附,文件上传工具类UploadUtil.java
import javax.servlet.http.*;
/**
* Servlet3.0中没有专门获取文件类型和名称的API,需要我们自己从请求头中截取
**/
public class UploadUtil{
public static String getFileType(Part p){
String name = p.getHeader("content-disposition");
String fileNameTmp = name.substring(name.indexOf("filename=")+10);
String type = fileNameTmp.substring(fileNameTmp.indexOf(".")+1,fileNameTmp.indexOf("\""));
return type;
}
public static String getFileName(Part p){
String name = p.getHeader("content-disposition");
String fileNameTmp = name.substring(name.indexOf("filename=")+10);
String fileName = fileNameTmp.substring(0,fileNameTmp.indexOf("\""));
return fileName;
}
}
JDK8新特性
Lambda 表达式
标准格式:
Lambda省去面向对象的条条框框,格式由3个部分组成:
一些参数
一个箭头
一段代码
Lambda表达式的标准格式为:
(参数类型 参数名称) -> { 代码语句 }
格式说明:
小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
-> 是新引入的语法格式,代表指向动作。
大括号内的语法与传统方法体要求基本一致。
省略格式:
省略规则
在Lambda标准格式的基础上,使用省略写法的规则为:
-
小括号内参数的类型可以省略;
-
如果小括号内有且仅有一个参,则小括号可以省略;
-
如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句
分号。
可推导即可省略
Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都可以省略。例
如上例还可以使用Lambda的省略写法:
Runnable接口简化:
1. () -> System.out.println("多线程任务执行!")
Comparator接口简化:
2. Arrays.sort(array, (a, b) -> a.getAge() - b.getAge());
Lambda的语法非常简洁,完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意:
-
使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。 无论是JDK内置的Runnable 、 Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
-
使用Lambda必须具有上下文推断。 也就是方法的参数或局部变量类型必须为Lambda对应的接口
类型,才能使用Lambda作为该接口的实例。
备注:有且仅有一个抽象方法的接口,称为“函数式接口”。
默认方法
接口中可以有默认方法
默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。
public interface InterFaceName {
public default void method() {
// 执行语句
}
public static void method2() {
// 执行语句
}
}
默认方法的使用
可以继承,可以重写,二选一,但是只能通过实现类的对象来调用.
定义接口:
public interface LiveAble {
public default void fly(){
System.out.println("天上飞");
}
}
1.不重写默认方法定义实现类:
public class Animal implements LiveAble {
// 继承,什么都不用写,直接调用
}
2.重写默认方法定义实现类:
public class Animal implements LiveAble {
@Override
public void fly() {
System.out.println("自由自在的飞");
}
}
1定义不重写默认方法测试类:
public class InterfaceDemo {
public static void main(String[] args) {
// 创建子类对象
Animal a = new Animal();
// 调用默认方法
a.fly();
}
}
输出结果: 天上飞
2.定义重写默认方法测试类:
public class InterfaceDemo {
public static void main(String[] args) {
// 创建子类对象
Animal a = new Animal();
// 调用重写方法
a.fly();
}
}
输出结果: 自由自在的飞
方法引用
概念:
方法引用使得开发者可以直接引用现存的方法、Java类的构造方法或者实例对象。方法引用和Lambda
表达式配合使用,使得java类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码。
方法引用使用一对冒号 :: 。
第一种方法引用的类型是构造器引用,语法是Class::new,或者更一般的形式:Class::new。注意:
这个构造器没有参数。
第二种方法引用的类型是静态方法引用,语法是Class::static_method。注意:这个方法接受一个Car
类型的参数。
第三种方法引用的类型是某个类的成员方法的引用,语法是Class::method,注意,这个方法没有定义入参:
第四种方法引用的类型是某个实例对象的成员方法的引用,语法是instance::method。注意:这个方法接受一个Car类型的参数:
剩下的以后在补充。