JavaWeb(五)Filter过滤器
Filter过滤器
Fileter介绍
Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如图:
Filter接口中有一个doFilter方法,当开发人员编写好Filter,并配置对哪个web资源(拦截url)进行拦截后,WEB服务器每次在调用web资源之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
调用目标资源之前,让一段代码执行
是否调用目标资源(即是否让用户访问web资源)。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。
调用目标资源之后,让一段代码执行
开发Fileter步骤
Filter开发分为二个步骤:
- 编写java类实现Filter接口,并实现(三个方法)其doFilter方法。(现在也可以直接在Eclipse中创建Filter,可以不设置web.xml)
- 1 package com.filter; 2 3 import java.io.IOException; 4 import javax.servlet.Filter; 5 import javax.servlet.FilterChain; 6 import javax.servlet.FilterConfig; 7 import javax.servlet.ServletException; 8 import javax.servlet.ServletRequest; 9 import javax.servlet.ServletResponse; 10 import javax.servlet.annotation.WebFilter; 11 12 /** 13 * Servlet Filter implementation class FilterTest2 14 */ 15 @WebFilter("/FilterTest2")//可以直接在此设置属性,不配置xml 16 public class FilterTest2 implements Filter { 17 18 public FilterTest2() { 19 // TODO Auto-generated constructor stub 20 } 21 22 public void destroy() { 23 // TODO Auto-generated method stub 24 } 25 26 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 27 28 chain.doFilter(request, response); 29 } 30 31 /** 32 * @see Filter#init(FilterConfig) 33 */ 34 public void init(FilterConfig fConfig) throws ServletException { 35 36 } 37 38 }
- 在 web.xml 文件中使用<filter>和<filter-mapping>元素对编写的filter类进行注册,并设置它所能拦截的资源。
- 1 <filter> 2 <filter-name>TestFilTer1</filter-name> 3 <filter-class>com.filter.TestFilTer1</filter-class><!-- 完整的限定类名,可以直接在类名Ctrl点击复制 --> 4 </filter> 5 <filter-mapping> 6 <filter-name>TestFilTer1</filter-name> 7 <url-pattern>/*</url-pattern><!-- *代表所有 --> 8 </filter-mapping>
Filter链 --- FilterChain
- 在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。
- web服务器根据Filter在web.xml文件中的注册顺序<mapping>,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
Filter的生命周期
l init(FilterConfig filterConfig)throws ServletException:
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法进行初始化。需要注意的是:filter对象只会创建一次,init方法也只会执行一次。
- 开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
l doFilter(ServletRequest,ServletResponse,FilterChain)
- 每次filter进行拦截都会执行
- 在实际开发中方法中参数request和response通常转换为HttpServletRequest和HttpServletResponse类型进行操作
1 HttpServletRequest request = (HttpServletRequest)req;
2 HttpServletResponse response = (HttpServletResponse)resp;
l destroy():
- 在Web容器卸载 Filter 对象之前被调用。
FilterConfig接口
l 用户在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得:
- String getFilterName():得到filter的名称。
- String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
- Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。
- public ServletContext getServletContext():返回Servlet上下文对象的引用。
- Ø 注册
注册与映射Filter
l <filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
- <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
- <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
- <servlet-name>指定过滤器所拦截的Servlet名称。
- <dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截。
- <dispatcher> 子元素可以设置的值及其意义:
- REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
- INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
- FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
- ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
<filter-mapping>
<filter-name>testFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Filter示例
过程:
web.xml中设置给index设置过滤
在过滤器中,获取session,为空也就是直接登访问index.jsp会跳转到登录页面
denglu.jsp,点击登录,跳转到chuli.jsp,设置session,在定向到index.jsp,获取到相应的session,通过进入
1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
3 <display-name>0826</display-name>
4 <welcome-file-list>
5 <welcome-file>index.html</welcome-file>
6 <welcome-file>index.htm</welcome-file>
7 <welcome-file>index.jsp</welcome-file>
8 <welcome-file>default.html</welcome-file>
9 <welcome-file>default.htm</welcome-file>
10 <welcome-file>default.jsp</welcome-file>
11 </welcome-file-list>
12 <filter>
13 <filter-name>TestFilTer1</filter-name>
14 <filter-class>com.filter.TestFilTer1</filter-class><!-- 包名,可以直接在类名Ctrl点击复制 -->
15 </filter>
16 <filter-mapping>
17 <filter-name>TestFilTer1</filter-name>
18 <url-pattern>/index.jsp</url-pattern><!-- 访问index.jsp会启动过滤 -->
19 </filter-mapping>
20 </web-app>
1 package com.filter;
2
3 import java.io.IOException;
4 import javax.servlet.Filter;
5 import javax.servlet.FilterChain;
6 import javax.servlet.FilterConfig;
7 import javax.servlet.ServletException;
8 import javax.servlet.ServletRequest;
9 import javax.servlet.ServletResponse;
10 import javax.servlet.annotation.WebFilter;
11 import javax.servlet.http.HttpServletRequest;
12 import javax.servlet.http.HttpServletResponse;
13
14 /**
15 * Servlet Filter implementation class TestFilTer1
16 */
17 @WebFilter("/TestFilTer1")
18 public class TestFilTer1 implements Filter {
19
20 /**
21 * Default constructor.
22 */
23 public TestFilTer1() {
24 // TODO Auto-generated constructor stub
25 }
26
27 /**
28 * @see Filter#destroy()
29 */
30 public void destroy() {
31 // TODO Auto-generated method stub
32
33 }
34
35 /**
36 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
37 */
38 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
39 //先转型,可以使用转型后对象的方法
40 HttpServletRequest request = (HttpServletRequest)req;
41 HttpServletResponse response = (HttpServletResponse)resp;
42 //处理字符集
43 request.setCharacterEncoding("utf-8");
44 response.setCharacterEncoding("utf-8");
45 response.setContentType("text/html; charset=utf-8");
46
47 Object obj = request.getSession().getAttribute("currentUser");//获取session对象
48
49 if(obj == null) {
50 response.sendRedirect("denglu.jsp");
51 } else {
52 chain.doFilter(req, resp);
53 }
54 }
55
56 /**
57 * @see Filter#init(FilterConfig)
58 */
59 public void init(FilterConfig fConfig) throws ServletException {
60 // TODO Auto-generated method stub
61 }
62 }
1 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 pageEncoding="ISO-8859-1"%>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
7 <title>Insert title here</title>
8 </head>
9 <body>
10 <a href="chuli.jsp">登录</a>
11
12 </body>
13 </html>
1 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 pageEncoding="ISO-8859-1"%>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
7 <title>Insert title here</title>
8 </head>
9 <body>
10 <%
11 session.setAttribute("currentUser", "admin");
12 response.sendRedirect("index.jsp");
13 %>
14 </body>
15 </html>
1 <%@ page language="java" contentType="text/html; charset=utf-8"
2 pageEncoding="utf-8" import="java.util.ArrayList,com.util.User"%>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
7 <title>Insert title here</title>
8 </head>
9 <body>
10
11 当前
12
13 </body>
14 </html>
例子2
设置部分页面过滤
过滤器:
1 package com.hanqi.filter;
2
3 import java.io.IOException;
4
5 import javax.servlet.Filter;
6 import javax.servlet.FilterChain;
7 import javax.servlet.FilterConfig;
8 import javax.servlet.ServletException;
9 import javax.servlet.ServletRequest;
10 import javax.servlet.ServletResponse;
11 import javax.servlet.http.HttpServletRequest;
12 import javax.servlet.http.HttpServletResponse;
13
14 public class SessionFilterTest implements Filter {
15 //设置成员变量,获取需要过滤的页面
16 private String pages;
17
18 @Override
19 public void destroy() {
20
21 }
22
23 @Override
24 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
25 throws IOException, ServletException {
26 HttpServletRequest request = (HttpServletRequest)req;
27 HttpServletResponse response = (HttpServletResponse)resp;
28
29 // 获取当前请求
30 String uri = request.getRequestURI();
31 System.out.println("当前发送的请求: "+uri);
32
33 // 获取不需要判断session 的请求们
34 String[] _pages = pages.split(";");
35
36 // 判断当前请求是否在不需要判断的请求里面
37 if(checkString(_pages, uri)) {
38 // 放行
39 chain.doFilter(req, resp);
40 } else {
41 // 先判断session再放行
42 Object obj = request.getSession().getAttribute("currentUser");
43 if(obj==null) {
44 response.sendRedirect("login.jsp");
45 } else {
46 chain.doFilter(req, resp);
47 }
48 }
49 }
50
51 public static boolean checkString(String[] pages, String uri) {
52 for(String s : pages) {
53 if(uri.contains(s)) {//如果访问的地址包含了需要过滤的的页面
54 return true;
55 }
56 }
57 return false;
58 }
59
60 @Override
61 public void init(FilterConfig config) throws ServletException {
62 String str = config.getInitParameter("page");//获取当前参数,即需要过滤的页面
63 this.setPages(str);
64 System.out.println(str);
65 }
66
67 public String getPages() {
68 return pages;
69 }
70
71 public void setPages(String pages) {
72 this.pages = pages;
73 }
74
75 }
1 package com.hanqi.filter;
2
3 import java.io.IOException;
4
5 import javax.servlet.Filter;
6 import javax.servlet.FilterChain;
7 import javax.servlet.FilterConfig;
8 import javax.servlet.ServletException;
9 import javax.servlet.ServletRequest;
10 import javax.servlet.ServletResponse;
11
12 public class TestFilter implements Filter {
13
14 @Override
15 public void destroy() {
16 // TODO Auto-generated method stub
17
18 }
19
20 @Override
21 public void doFilter(ServletRequest request, ServletResponse response, FilterChain arg2)
22 throws IOException, ServletException {
23
24 request.setCharacterEncoding("utf-8");
25 response.setCharacterEncoding("utf-8");
26 response.setContentType("text/html; charset=utf-8");
27
28 arg2.doFilter(request, response);
29 }
30
31 @Override
32 public void init(FilterConfig arg0) throws ServletException {
33 // TODO Auto-generated method stub
34
35 }
36
37 }
web.xml文件
1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
5 id="WebApp_ID" version="3.0">
6 <filter>
7 <filter-name>EncodingFilter</filter-name>
8 <filter-class>com.hanqi.filter.TestFilter</filter-class>
9 </filter>
10 <filter-mapping>
11 <filter-name>EncodingFilter</filter-name>
12 <url-pattern>/*</url-pattern>
13 </filter-mapping>
14
15 <filter>
16 <filter-name>SessionFilter</filter-name>
17 <filter-class>com.hanqi.filter.SessionFilterTest</filter-class>
18 <init-param><!-- 设置可以放行的页面 -->
19 <param-name>page</param-name>
20 <param-value>login.jsp;LoginServlet;register.jsp;RegisterServlet</param-value>
21 </init-param>
22 </filter>
23 <filter-mapping>
24 <filter-name>SessionFilter</filter-name>
25 <url-pattern>/*</url-pattern>
26 </filter-mapping>
27 </web-app>
Servlet
1 package com.hanqi.servlet;
2
3 import java.io.IOException;
4 import javax.servlet.ServletException;
5 import javax.servlet.annotation.WebServlet;
6 import javax.servlet.http.HttpServlet;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9
10 /**
11 * Servlet implementation class LoginServlet
12 */
13 @WebServlet("/LoginServlet")
14 public class LoginServlet extends HttpServlet {
15 private static final long serialVersionUID = 1L;
16
17 /**
18 * @see HttpServlet#HttpServlet()
19 */
20 public LoginServlet() {
21 super();
22 // TODO Auto-generated constructor stub
23 }
24
25 /**
26 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
27 */
28 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
29 String username = request.getParameter("username");
30 String password = request.getParameter("password");
31 System.out.println(username);
32 System.out.println(password);
33 //简单验证如果指定的用户名和密码相同,设置session
34 if("admin".equals(username)&&"12345".equals(password)) {
35 request.getSession().setAttribute("currentUser", "admin");
36 response.sendRedirect("index.jsp");
37 } else {
38 response.sendRedirect("fail.jsp");
39 }
40 }
41
42 /**
43 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
44 */
45 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
46 // TODO Auto-generated method stub
47 doGet(request, response);
48 }
49
50 }
1 package com.hanqi.servlet;
2
3 import java.io.IOException;
4 import javax.servlet.ServletException;
5 import javax.servlet.annotation.WebServlet;
6 import javax.servlet.http.HttpServlet;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9
10 /**
11 * Servlet implementation class RegisterServlet
12 */
13 @WebServlet("/RegisterServlet")
14 public class RegisterServlet extends HttpServlet {
15 private static final long serialVersionUID = 1L;
16
17 /**
18 * @see HttpServlet#HttpServlet()
19 */
20 public RegisterServlet() {
21 super();
22 // TODO Auto-generated constructor stub
23 }
24
25 /**
26 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
27 */
28 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
29 String username = request.getParameter("username");
30 String password = request.getParameter("password");
31 String realname = request.getParameter("realname");
32
33 System.out.println(username);
34 System.out.println(password);
35 System.out.println(realname);
36 }
37
38 /**
39 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
40 */
41 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
42 // TODO Auto-generated method stub
43 doGet(request, response);
44 }
45 }
Jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>登录失败</h1>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="RegisterServlet" method="post">
用户名: <input type="text" name="username" /><br>
密码: <input type="text" name="password" /><br>
姓名: <input type="text" name="realname" /><br>
<input type="submit" value="注册" />
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="LoginServlet" method="post">
用户名: <input type="text" name="username" /><br> 密码: <input
type="text" name="password" /><br> <input type="submit"
value="登录" />
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
全站统一字符编码过滤器
1 request.setCharacterEncoding("utf-8");
2 response.setCharacterEncoding("utf-8");
3 response.setContentType("text/html; charset=utf-8");
禁用所有JSP页面缓存
因为动态页面数据,是由程序生成的,所以如果有缓存,就会发生,客户端查看数据不是最新数据情况 ,对于动态程序生成页面,设置浏览器端禁止缓存页面内容
1 response.setDateHeader("Expires",-1);
2
3 response.setHeader("Cache-Control","no-cache");
4
5 response.setHeader("Pragma","no-cache");
将禁用缓存代码,提起到过滤器中,通过url配置,禁用所有JSP页面的缓存
- Hadoop数据分析平台实战——060深入理解MapReduce 01(案例)离线数据分析平台实战——060深入理解MapReduce 01(案例)
- 利用向量积(叉积)计算三角形的面积和多边形的面积
- HDU 1556 Color the ball
- Hadoop数据分析平台实战——080HBase介绍和安装离线数据分析平台实战——080HBase介绍和安装
- Hadoop数据分析平台实战——130Hive Shell命令介绍 02(熟悉Hive略过)离线数据分析平台实战——130Hive Shell命令介绍 02(熟悉Hive略过)
- ECJTUACM16 Winter vacation training #4 题解&源码
- Hadoop数据分析平台实战——090HBase shell客户端和Java Api介绍离线数据分析平台实战——090HBase shell客户端和Java Api介绍
- Hadoop数据分析平台实战——140Hive函数以及自定义函数讲解离线数据分析平台实战——140Hive函数以及自定义函数讲解
- 深入理解树状数组
- Codeforces 712C Memory and De-Evolution
- Codeforces 712B Memory and Trident
- Hadoop数据分析平台实战——110Hive介绍和Hive环境搭建离线数据分析平台实战——110Hive介绍和Hive环境搭建
- 干货|普通反爬虫机制的应对策略
- python基础-字符串与编码
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Array - 299. Bulls and Cows
- Array - 189. Rotate Array
- Array - 277 Find the Celebrity
- Array - 80. Remove Duplicates from Sorted Array II
- Array - 508. Wiggle Sort
- Array - 376. Wiggle Subsequence
- Array - 283. Move Zeroes
- Array - 88. Merge Sorted Array
- Array - 228. Summary Ranges
- Array - 152. Maximum Product Subarray
- Focal Loss和它背后的男人RetinaNet
- Array - 53. Maximum Subarray
- Array - 295. Find Median from Data Stream
- Array - 239. Sliding Window Maximum
- Array - 164. Maximum Gap