直接复制新建 servlet 工程 的方式。
复制一个 servlet 工程,修改工程名和 .iml 名并保持一致,IDEA -> File -> Project Structure -> Modules + -> Import Module -> 选中 .iml 引入 -> 点开再点击 web -> 右下角 fix 创建Artifacts -> Apply。
这样新建 servlet 工程有几个隐患。Run 后需要 Redeploy 一次才会自动打开浏览器。每次更改代码后,运行的还是未更改之前的代码,需要先 Build Artifacts 可解决。
Filter,过滤器。是处于客户端与服务器目标资源之间的一道过滤技术。
执行地位在 Servlet 之前,客户端发送请求时,会先经过 Filter,再到达目标 Servlet 中;响应时,会根据执行流程再次反向执行Filter。可以解决多个Servlet共性代码的冗余问题(例如:乱码处理、登录验证)。
// 乱码处理
@WebFilter(filterName = "EncodeFilter", urlPatterns = "/*")
public class EncodeFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("encodeFilter.doFilter");
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf8");
// 放行,执行下一个过滤器 或 servlet
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
}
@WebFilter(filterName = "LoginFilter", urlPatterns = "/userManagerServlet", initParams = {
@WebInitParam(name = "username", value = "张三"),
@WebInitParam(name = "password", value = "123")
})
public class LoginFilter implements Filter {
private String username = null;
private String password = null;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("authFilter.doFilter");
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
String reqUsername = request.getParameter("username");
String reqPassword = request.getParameter("password");
if (reqUsername == null || reqPassword == null) {
response.getWriter().write("请输入用户名和密码");
return;
}
if (reqUsername.equals(username) && reqPassword.equals(password)) {
chain.doFilter(request, response);
} else {
response.getWriter().write("用户名和密码输入错误");
}
}
public void init(FilterConfig config) throws ServletException {
username = config.getInitParameter("username");
password = config.getInitParameter("password");
}
}
@WebServlet("/userManagerServlet")
public class userManagerServlet extends javax.servlet.http.HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("userManagerServlet.doGet");
response.getWriter().write("你在干什么");
}
}
多个过滤器。如果采用 web.xml 引入的方式,执行顺序是从上至下。如果采用注解方式,执行顺序按 ascii 码的顺序。web.xml 配置高于注解方式。如果注解和 web.xml 同时配置,会创建多个过滤器对象,造成过滤多次。
监听器。可以监听 servlet 工程运行或类的运行。常用的有监听 Session、servletRequest、ServletContext。
@WebListener
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
String username = (String)session.getAttribute("username");
System.out.println("创建 session" + "\t" + username);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
String username = (String)session.getAttribute("username");
System.out.println("session 过期或销毁了" + "\t" + username);
}
}
@WebListener
public class RequestListener implements ServletRequestListener,
ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
ServletRequest servletRequest = servletRequestAttributeEvent.getServletRequest();
Object reqValue = servletRequest.getAttribute(name);
System.out.println("添加 RequestAttribute" + "\t" + name + "\t" + value + "\t" + reqValue);
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
System.out.println("删除 RequestAttribute" + "\t" + name + "\t" + value);
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
ServletRequest servletRequest = servletRequestAttributeEvent.getServletRequest();
// 替换后的值
Object reqValue = servletRequest.getAttribute(name);
System.out.println("替换 RequestAttribute" + "\t" + name + "\t" + value + "\t" + reqValue);
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("请求完成");
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("收到请求");
}
}
@WebListener
public class ContextListener implements ServletContextListener, ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
String name = servletContextAttributeEvent.getName();
String value = (String) servletContextAttributeEvent.getValue();
ServletContext servletContext = servletContextAttributeEvent.getServletContext();
String contextValue = (String)servletContext.getAttribute("work");
System.out.println("添加 ServletContext" + "\t" + name + "\t" + value + "\t" + contextValue);
}
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
String name = servletContextAttributeEvent.getName();
String value = (String) servletContextAttributeEvent.getValue();
System.out.println("删除 ServletContext" + "\t" + name + "\t" + value);
}
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
String name = servletContextAttributeEvent.getName();
// 替换前的值
String value = (String) servletContextAttributeEvent.getValue();
ServletContext servletContext = servletContextAttributeEvent.getServletContext();
// 替换后的值
String contextValue = (String)servletContext.getAttribute(name);
System.out.println("替换 ServletContext" + "\t" + name + "\t" + value + "\t" + contextValue);
}
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("context 初始化");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("context 销毁");
}
}
@WebServlet("/ListenerServlet")
public class ListenerServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("进来了吗");
// request listener
request.setAttribute("work","程序员");
request.setAttribute("work","程序猿");
request.removeAttribute("work");
// session listener
HttpSession session = request.getSession();
session.setAttribute("username", "zs");
// 销毁session
session.invalidate();
// Context listener
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("work","程序员");
servletContext.setAttribute("work","程序猿");
servletContext.removeAttribute("work");
System.out.println("走完了吗");
response.getWriter().write("hhaa");
}
}
一个记录用户登陆、登出的例子。
<%-- index.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form method="post" action="LoginServlet?action=login">
用户名: <input type="text" name="username" value="张三"><br>
<input type="submit" value="登陆">
</form>
</body>
</html>
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp ;
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf8");
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
}
@WebListener
public class ContextListener implements ServletContextListener, HttpSessionListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
// 启动时 初始化一个集合
ArrayList<String> list = new ArrayList<>();
servletContextEvent.getServletContext().setAttribute("onlineNum", list);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("context 销毁");
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
// 获取集合
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
List<String> list = (List<String>) servletContext.getAttribute("onlineNum");
// 获取注销的用户
String user = (String)httpSessionEvent.getSession().getAttribute("user");
list.remove(user);
servletContext.setAttribute("onlineNum", list);
}
}
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action");
if (action.equals("login")) {
String username = request.getParameter("username");
if (username == null || username.length() == 0) {
response.getWriter().write("用户名不能为空");
return;
}
HttpSession session = request.getSession();
Object user = session.getAttribute("user");
// 首次打开浏览器
if (user == null) {
ServletContext servletContext = this.getServletContext();
List<String> list = (List<String>) servletContext.getAttribute("onlineNum");
list.add(username);
servletContext.setAttribute("onlineNum", list);
session.setAttribute("user", username);
response.getWriter().write("欢迎【" + username + "】登陆成功");
} else {
response.getWriter().write("你已经登陆了");
}
response.getWriter().write("<br><a href=\"LoginServlet?action=logout\">登出</a>");
response.getWriter().write("<br><a href=\"ViewOnlineServlet\">全部在线用户</a>");
} else if (action.equals("logout")) {
request.getSession().invalidate();
}
}
}
@WebServlet("/ViewOnlineServlet")
public class ViewOnlineServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<String> list = (List<String>)this.getServletContext().getAttribute("onlineNum");
StringBuffer buffer = new StringBuffer();
buffer.append("<html>");
buffer.append("<body>");
buffer.append("<h3>目前在线【 "+ list.size() + " 】人");
buffer.append("<ul>");
for (String username: list) {
buffer.append("<li>" + username + "</li>");
}
buffer.append("</ul>");
buffer.append("</body>");
buffer.append("</html>");
response.getWriter().write(buffer.toString());
}
}