java学习笔记-JavaWeb篇三

63 JSTL_表达式操作
64 JSTL_流程控制操作 
65 JSTL_迭代操作 
66 JSTL_URL操作
67 JSTL_改写MVC案例
68 Filter概述 
69 创建HttpFilter 
70 理解多个Filter代码 
71 配置Filter的dispatcher节点
72 禁用浏览器缓存的过滤器 
73 字符编码过滤器 
74 检查用户是否登录的过滤器
75 Filter小结(1)
76 权限管理思路分析 
77 权限管理代码实现
78 权限过滤思路分析
79 权限过滤代码实现 
80 HttpServletRequest
81 Filter小结(2)
82 监听域对象创建和销毁的Listener
83 通过Listener理解域对象生命周期
84 其他的Servlet监听器 
85 Servlet监听器小结

63 JSTL_表达式操作

讲了3个标签<c:out><c:set><c:remove>

所有JSTL部分可以参考:http://www.cnblogs.com/lihuiyy/archive/2012/02/24/2366806.html  总结的非常好,值得学习

64 JSTL_流程控制操作 

 <c:if>:没有else功能,但是可以将判断结果保存下来,留以后备用

 <c:choose><c:when><c:otherwise>:when和otherwise是choose的子标签,不能脱离choose而存在;otherwise必须在最后且仅能有1个

65 JSTL_迭代操作 

<c:forEach>:可以对数组,Collection(对于集合,begin属性从0开始),Map进行遍历

<c:forTokens>:处理字符串的,类似于String 的split() 方法

 

66 JSTL_URL操作

 <c:import>

<c:redirect>

<c:url>标签

67 JSTL_改写MVC案例

 将jsp页面中的java代码全部用EL和JSTL代替,示例:

01 改进前:

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8" import="java.util.List" import="com.test.mvc.domain.Customer" %>
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 4 <html>
 5 <%
 6     List<Customer> customers = (List<Customer>)request.getAttribute("customers");
 7     if(customers != null && customers.size() > 0){
 8 %>
 9     <table cellpadding="10" border="1" cellspacing="0">
10         <tr>
11             <th>id</th>
12             <th>name</th>
13             <th>address</th>
14             <th>phone</th>
15             <th>操作</th>
16         </tr>
17         <%
18         for(Customer customer:customers){
19         %>
20             <tr>
21                 <td><%= customer.getId() %></td>
22                 <td><%= customer.getName() %></td>
23                 <td><%= customer.getAddress() %></td>
24                 <td><%= customer.getPhone() %></td>
25                 <td>
26                     <a href="editCustomer.do?customerId=<%= customer.getId() %>">update</a>
27                     <!-- class关联到jquery -->
28                      <a href="deleteCustomer.do?customerId=<%= customer.getId() %>" class="delete">delete</a>
29                 </td>
30             </tr>
31         <%        
32         }
33         %>
34     </table>
35 
36 <%
37     }
38     
39 %>
40 </body>
41 </html>
View Code

01 改进后:

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8" import="java.util.List" import="com.test.mvc.domain.Customer" %>
 3 <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
 4 
 5     <c:if test="${! empty requestScope.customers}">
 6         <table cellpadding="10" border="1" cellspacing="0">
 7         <tr>
 8             <th>id</th>
 9             <th>name</th>
10             <th>address</th>
11             <th>phone</th>
12             <th>操作</th>
13         </tr>
14         <c:forEach items="${requestScope.customers}" var="cust">
15             <tr>
16                 <td>${cust.id}</td>
17                 <td>${cust.name }</td>
18                 <td>${cust.address}</td>
19                 <td>${cust.phone}</td>
20                 <td>
21                     <c:url value="/editCustomer.do" var="editCustomer">
22                         <c:param name="customerId" value="${cust.id}"></c:param>
23                     </c:url>
24                     <a href="${editCustomer}">update</a>
25                     <c:url value="/deleteCustomer.do" var="deleteCustomer">
26                         <c:param name="customerId" value="${cust.id}"></c:param>
27                     </c:url>
28                      <a href="${deleteCustomer}" class="delete">delete</a>
29                 </td>
30             </tr>
31         </c:forEach>
32         </table>
33     </c:if>
34 
35 
36 </body>
37 </html>
View Code

  02 改进前和改进后

<a><%= request.getAttribute("message") == null ? "":request.getAttribute("message") %></a>
<td><input type="text" name="name"
        value="<%= request.getParameter("name") == null ? "":request.getParameter("name") %>"/></td>

 03 改进前和改进后

 1 <a><%= request.getAttribute("message") == null ? "":request.getAttribute("message") %></a>
 2 
 3 <%
 4     String id = null;
 5     String oldName = null;
 6     String name = null;
 7     String address = null;
 8     String phone = null;
 9     
10     Customer customer = (Customer)request.getAttribute("customer");
11     
12     if(customer != null){
13         id = customer.getId() + "";
14         oldName = customer.getName();
15         name = customer.getName();
16         address = customer.getAddress();
17         phone = customer.getPhone();
18     }else{
19         id = request.getParameter("id");
20         oldName = request.getParameter("oldName");
21         name = request.getParameter("oldName");
22         address = request.getParameter("address");
23         phone = request.getParameter("phone");
24         
25     }
26 %>
View Code
 1 <c:if test="${! empty requestScope.message}">
 2     ${requestScope.message}
 3 </c:if>
 4 
 5 <c:set var="cust" value="${requestScope.customer}"></c:set>
 6 <c:set var="id" value="${cust != null ? cust.id : param.id }"></c:set>
 7 <c:set var="oldName" value="${cust != null ? cust.name : param.oldName }"></c:set>
 8 <c:set var="name" value="${cust != null ? cust.name : param.oldName }"></c:set>
 9 <c:set var="address" value="${cust != null ? cust.address : param.address }"></c:set>
10 <c:set var="phone" value="${cust != null ? cust.phone : param.phone }"></c:set>
11 
12 <form action="updateCustomer.do" method="post">
13 <input type="hidden" name="id" value="${cust.id}"/>
14 <input type="hidden" name="oldName" value="${cust.oldName}"/>
15 <table>
16     <tr>
17         <td>name:</td>
18         <td><input type="text" name="name"
19         value="${name != null ? name : '' }"/></td>
20     </tr>
21     
22     <tr>
23         <td>address:</td>
24         <td><input type="text" name="address"
25         value="${address != null ? address : '' }"/></td>
26     </tr>
27     
28     <tr>
29         <td>phone:</td>
30         <td><input type="text" name="phone"
31         value="${phone != null ? phone : '' }"/></td>
32     </tr>
33     
34     <tr>
35         <td><input type="submit" value="保存修改"/></td>
36     <tr>
37 </table>
38 </form>
View Code

 中文编码问题还是没有解决,工程 / jsp页面 / tomcat的server.xml / 数据库 编码都统一为UTF-8  但是request.getParameter()仍然在存入数据库后为乱码

问题已解决,解决步骤:

1)在servlet的参数获取前(即request.getParamter())加上一句代码  (缺点是,在每次获取参数前,都需要增加这个代码,暂未其他办法)后来使用filter过滤器可以解决这个问题

request.setCharacterEncoding("UTF-8");

 2)由于本项目中使用c3p0数据库连接池,因此需要修改配置文件c3p0config.xml

<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/mytest?useUnicode=true&amp;characterEncoding=UTF8</property>

按以上两个步骤操作,表单中提交的中文参数,再次读取到页面时,也不会出现乱码情况。

68 Filter概述 

 1. Filter

1)Filter是什么

① JavaWeb的一个重要组件,可以对发送到Servlet的请求进行拦截,并对响应也进行拦截

② Filter是实现了Filter接口的java类

③ Filter需要在web.xml文件中进行配置和映射

2)如何创建一个Filter,并把他跑起来

① 创建一个Filter类,实现Filter接口:public class HelloFilter implements Filter

② 在web.xml文件中配置并映射该Filter 其中 url-pattern 指定该Filter可以拦截哪些资源,即可以通过哪些url访问到该Filter

<!--注册Filter-->

<filter>

  <filter-name>helloFilter</filter-name>

  <filter-class>com.test.HelloFilter<filter-class>

</filter>

<!--注册Filter-->

<filter-mapping>

  <filter-name>helloFilter</filter-name>

  <url-pattern>/test.jsp</url-pattern>

</filter-mapping>

3)Filter相关的API

 > public void init(FilterConfig arg0):类似于servlet的init方法,在创建filter对象的时候立即被调用,且只被调用一次,该方法用于对当前的Filter进行初始化操作。Filter实例是单例的。

* FilterConfig类似于ServletConfig

* 可以在web.xml文件中配置当前Filter的初始化参数 配置方式也和Servlet类似

<filter>
     <filter-name>MyFilter</filter-name>
     <filter-class>com.test.hyl.MyFilter</filter-class>
     <init-param>
         <param-name>name</param-name>
         <param-value>value</param-value>
     </init-param>
 </filter>

 > public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2):真正filter的逻辑代码要写在这里,每次拦截都会调用该方法

  * FilterChain:Filter链,多个Filter可以构成一个Filter链

    -doFilter(ServletRequest arg0, ServletResponse arg1):把请求传给Filter链的下一个Filter,若当前Filter是Filter链的最后一个Filter,将把请求给到目标Servlet(或jsp)

    -多个Filter拦截的顺序和<filter-mapping>配置的顺序有关,靠前的先被调用

> public void destroy():释放当前Filter所占用的资源的方法,在Filter被销毁之前调用,且只被调用一次

下面是一个完整的filter例子;实现:录入指定用户名和密码,否则提示录入错误

web.xml:

<context-param>
      <param-name>password</param-name>
      <param-value>123456</param-value>
  </context-param>
  
  <!-- 定义两个filter,一个filter用来对用户名是否正确进行过滤,一个用来对密码是否正确进行过滤 -->
  <filter>
    <filter-name>UsernameFilter</filter-name>
    <filter-class>com.test.filter.UsernameFilter</filter-class>
    <!-- 将已知量定义为参数 -->
    <init-param>
        <param-name>username</param-name>
        <param-value>Tom</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>UsernameFilter</filter-name>
    <url-pattern>/hello.jsp</url-pattern>
  </filter-mapping>
  <filter>
    <filter-name>PwdFilter</filter-name>
    <filter-class>com.test.filter.PwdFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>PwdFilter</filter-name>
    <url-pattern>/hello.jsp</url-pattern>
  </filter-mapping>
View Code

 login.jsp和hello.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<!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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
        <!-- 输入错误时的提示信息 -->
        <font color="red">${msg1}</font>   
    
        <font color="red">${msg2}</font>
    
    <form action="${pageContext.request.contextPath}/hello.jsp" method="post">
        <!-- value实现了回显 -->
        username: <input type="text" name="username" value="${param.username}">
        <br>
        password: <input type="password" name="password" value="${param.password}">
        <br>
        <input type="submit" name="loginBtn" value="登录">
    </form>

</body>
</html>
View Code
<body>

<font color="green">Hello,Tom!!!</font>

</body>
View Code

UsernameFilter.java:

public class UsernameFilter  implements Filter  {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //获取web.xml文件中配置的初始参数
        String initUsername = filterConfig.getInitParameter("username");
        String username = request.getParameter("username");
        
        if(! username.equals(initUsername)){
            //未通过过滤器验证
            request.setAttribute("msg1", "用户名输入错误,请重新输入");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }else{
            //说明通过了过滤器 进行下一个过滤
            chain.doFilter(request, response);
        }
        
    }
    //定义一个filterConfig对象
    private FilterConfig filterConfig;
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        this.filterConfig = arg0;
    }

}
View Code

PwdFilter.java:

public class PwdFilter implements Filter {
    

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String initPassword = filterConfig.getServletContext().getInitParameter("password");
        String pwd = request.getParameter("password");
        
        if(! pwd.equals(initPassword)){
            request.setAttribute("msg2", "输入的密码不正确,请重新输入");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }else{
            chain.doFilter(request, response);
        }
        
    }
    private FilterConfig filterConfig;
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        this.filterConfig = arg0;
    }

}
View Code

 以上为全部相关代码。

69 创建HttpFilter 

 HttpFilter的代码,但是还不知道该怎么用 这是个类 只需要继承这个类 并实现doFilter()方法即可

/**
 * 自定义的HttpFilter 实现Filter接口
 */
@WebFilter("/httpFilter")
public abstract class HttpFilter implements Filter {
    /*
     * 用于保存filterConfig对象
     */
    private FilterConfig filterConfig;

    /**
     * Default constructor. 
     */
    public HttpFilter() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * 原生的doFilter()方法 在方法内部将ServletRequest和ServletResponse转化为HttpServletRequest
     * 和HttpServletResponse,并调用doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)
     * 方法
     * 
     * 若编写Filter的过滤方法 不建议直接继承该方法,而建议直接继承
     * doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)方法
     */
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;
        
        doFilter(request,response,chain);
    }
    
    
    /**
     * 抽象方法,为http请求定制,必须实现的方法
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    public abstract void doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)throws IOException, ServletException;

    /**
     * 不建议子类直接覆盖,若直接覆盖,将可能导致filterConfig成员变量初始化失败
     */
    public void init(FilterConfig fConfig) throws ServletException {
        this.filterConfig = fConfig;
        init();
    }
    /*
     * 供子类继承的初始化方法,可以通过getFilterConfig()获取filterConfig对象
     */
    protected void init() {}
    
    /*
     * 直接返回init(FilterConfig) 的FilterConfig对象
     */
    public FilterConfig getFilterConfig(){
        return filterConfig;
    }

}
View Code

 

70 理解多个Filter代码 

 chain.doFilter()  代码执行顺序 理解filter chain  


71 配置Filter的dispatcher节点

<dispatcher>元素:指定过滤器所拦截的资源被servlet容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认为REQUEST。

可以设置多个<dispatcher>子元素用来指定Filter对资源的多种调用方式进行拦截

<dispatcher> 子元素可以设置的值及其意义:

REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。

INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。

ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

 

72 禁用浏览器缓存的过滤器

response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");

 这个过滤器直接继承之前自定义的HttpFilter,代码如下:

@WebFilter("/cache/*")
public class NoCacheFilter extends HttpFilter {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("NoCacheFilter's doFilter...");
        
        response.setDateHeader("Expires", -1);
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        
        chain.doFilter(request, response);
        
    }

}
View Code

73 字符编码过滤器 

 编写一个EncodingFilter

 1 读取web.xml文件中配置的当前WEB应用的初始化参数encoding

 2 指定请求的字符编码为第一步读取到的编码

 3 调用chain.doFilter()方法“放行”请求

web.xml:

<context-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
  </context-param>
View Code

74 检查用户是否登录的过滤器

 doLogin.jsp:

<body>
    <!-- 获取登录名 写入session -->
    <%
        String user = request.getParameter("username");
        //用户输入的登录名不为空
        if(user != null && ! user.trim().equals("")){
            //写入session 重定向页面到list.jsp
            request.getSession().setAttribute("userSession", user.trim());
            response.sendRedirect(request.getContextPath() + "/login/list.jsp");
        //否则直接重定向到login.jsp
        }else{
            response.sendRedirect(request.getContextPath() + "/login/login.jsp");
        }
    %>
</body>
View Code

 web.xml:

 <!-- 用户标志session -->
  <context-param>
    <param-name>userSession</param-name>
    <param-value>userTag</param-value>
  </context-param>
  <!-- 检查不到用户标志时,需要重定向的页面 -->
  <context-param>
    <param-name>redirectPage</param-name>
    <param-value>/login/login.jsp</param-value>
  </context-param>
  <!-- 不需要过滤器筛选的url -->
  <context-param>
    <param-name>unCheckedUrls</param-name>
    <param-value>/login/a.jsp,/login/login.jsp,/login/doLogin.jsp,/login/list.jsp</param-value>
  </context-param>
View Code

 LoginFilter.java:

@WebFilter("/loginFilter")
public class LoginFilter extends HttpFilter implements Filter {
    private String userSession;
    private String redirectPage;
    private String unCheckedUrls;
    
    @Override
    protected void init() {
        //初始化取出web.xml文件中配置的参数
        ServletContext servletContext = getFilterConfig().getServletContext();
        userSession = servletContext.getInitParameter("userSession");
        redirectPage = servletContext.getInitParameter("redirectPage");
        unCheckedUrls = servletContext.getInitParameter("unCheckedUrls");
    }
    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //将不需要检查的url存为list
        List<String> unCkUrls = Arrays.asList(unCheckedUrls.split(","));
        //获取当前请求url
        String requestUrl = request.getServletPath();
        //从session中获取用户标志
        Object user = request.getSession().getAttribute("userSession");
        
        //用户标志不匹配,但是属于不需要过滤的目标地址,也放行
        if(unCkUrls.contains(requestUrl)){
            chain.doFilter(request, response);
        //用户标志匹配,则放行
        }else if(user != null && user.toString().equals(userSession)){
            chain.doFilter(request, response);
        //用户标志不匹配,且需要过滤,则进行重定向
        }else{
            response.sendRedirect(request.getContextPath() + redirectPage);
        }
        
    }
View Code

 

75 Filter小结(1)

 参考以上蓝色字体,为重点内容

76 权限管理思路分析 

 1. 使用Filter过滤器完成一个简单的权限模型:

1)需求:

① 管理权限

  >查看某人的权限

  >修改某人的权限

② 对访问进行权限控制:有权限则可以访问,没有对应的权限 请返回

2)实现:

① 管理权限

  > 封装权限信息:Authority

  Authorty{

  private String displayName;

  //权限对应的url 一个权限对应1个url

  private String url;

  }

  > 封装用户信息:User

  User{

  private String username;

  private List<Authorty> authorties;

  }

  > 创建一个UserDao

  User get(String username);

  void update(String username,List<Authority>);

  > 页面

  authority-manager.jsp:有一个text文本框,供输入username,提交后,使用checkbox显示当前用户所有的权限信息

  检查request中是否有user信息,若有,则显示

  xxx的权限为:对应的权限的checkbox打上对号,提示页面上需要通过两层循环的方式来筛选出选择的权限

  > servlet

  authority-manager.jsp 查看的button提交表单后:获取表单的请求参数:usename,放入request中,转发到authorty-manager.jsp页面

  authority-manager.jsp 修改权限的button提交后,获取请求参数:username,将authority封装为list,调用userDao的get()方法修改权限,然后重定向到authority-manager.jsp页面

77 权限管理代码实现

 见79小节

78 权限过滤思路分析

 ② 对访问进行权限控制:

> 使用filter对权限进行过滤:检查用户是否有权限,若有,则直接响应目标页面;若没有则重定向到403.jsp

使用Filter如何进行过滤:

——获取servletPath

——在用户已经登录(可使用 用户是否登录 的过滤器)的情况下,获取用户信息,session.getAttribute()

——再获取用户所具有的权限的信息:List<Authority>

——检验用户是否有请求 servletPath 的权限:可以思考除了遍历以外,有没有更好的实现方式

——若有权限:响应

——若没有权限:重定向到403.jsp

其他:

——用户若登录,需要把用户信息放入到HttpSession中

——在检验权限之前,需要判断用户是否已经登录

> 用户登录后才能看到list页面 首先检验是否登录(用户登录时需要将用户信息放入session) 然后检查各article页面是否有权限

79 权限过滤代码实现 

 包括权限管理部分功能,整个工程的结构如下图所示:

@WebFilter("/authorityFilter")
public class AuthorityFilter extends HttpFilter implements Filter {
       
    private UserDao userDao = new UserDao();

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String reqUrl = request.getServletPath();
        List<Authority> authorities = userDao.getAuthorities();
//        //获取需要进行权限验证的页面列表
//        List<String> checkedUrls = new ArrayList<>();
//        for(Authority authority:authorities){
//            checkedUrls.add(authority.getUrl());
//        }
//        
//        if(!checkedUrls.contains(reqUrl)){
//            chain.doFilter(request, response);
//            return;
//        }
        Authority authority = new Authority(null, reqUrl);
        if(!authorities.contains(authority)){
            chain.doFilter(request, response);
            return;
        }
        //根据当前session获取当前已登录用户信息
        String userSession = (String) request.getSession().getAttribute("userSession");
        User user = userDao.getUser(userSession);
        //根据已登录用户 获取权限列表
        List<Authority> authorities2 = user.getAuthorities();
//        List<String> authUrls = new ArrayList<>();
//        for(Authority authority:authorities2){
//            authUrls.add(authority.getUrl());
//        }
//        //若有该页面权限,则放行
//        if(authUrls.contains(reqUrl)){
//            chain.doFilter(request, response);
//            return;
//        }
        //这几行代码可以替换以上几行,对象的contain()方法需要给Authority重写equals()方法
        Authority authority2 = new Authority(null, reqUrl);
        if(authorities2.contains(authority2)){
            chain.doFilter(request, response);
            return;
        }
        //若没有权限,则重定向到403页面
        response.sendRedirect(request.getContextPath() + "/403.jsp");
        
    }
       

}
AuthorityServlet.java
public class Authority {
    
    private String name;
    private String url;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public Authority(String name, String url) {
        super();
        this.name = name;
        this.url = url;
    }
    
    public Authority() {
        // TODO Auto-generated constructor stub
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Authority other = (Authority) obj;
        if (url == null) {
            if (other.url != null)
                return false;
        } else if (!url.equals(other.url))
            return false;
        return true;
    }
    
}
Authority.java
@WebFilter("/authorityFilter")
public class AuthorityFilter extends HttpFilter implements Filter {
       
    private UserDao userDao = new UserDao();

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String reqUrl = request.getServletPath();
        List<Authority> authorities = userDao.getAuthorities();
//        //获取需要进行权限验证的页面列表
//        List<String> checkedUrls = new ArrayList<>();
//        for(Authority authority:authorities){
//            checkedUrls.add(authority.getUrl());
//        }
//        
//        if(!checkedUrls.contains(reqUrl)){
//            chain.doFilter(request, response);
//            return;
//        }
        Authority authority = new Authority(null, reqUrl);
        if(!authorities.contains(authority)){
            chain.doFilter(request, response);
            return;
        }
        //根据当前session获取当前已登录用户信息
        String userSession = (String) request.getSession().getAttribute("userSession");
        User user = userDao.getUser(userSession);
        //根据已登录用户 获取权限列表
        List<Authority> authorities2 = user.getAuthorities();
//        List<String> authUrls = new ArrayList<>();
//        for(Authority authority:authorities2){
//            authUrls.add(authority.getUrl());
//        }
//        //若有该页面权限,则放行
//        if(authUrls.contains(reqUrl)){
//            chain.doFilter(request, response);
//            return;
//        }
        //这几行代码可以替换以上几行,对象的contain()方法需要给Authority重写equals()方法
        Authority authority2 = new Authority(null, reqUrl);
        if(authorities2.contains(authority2)){
            chain.doFilter(request, response);
            return;
        }
        //若没有权限,则重定向到403页面
        response.sendRedirect(request.getContextPath() + "/403.jsp");
        
    }
}
AuthorityFilter.java
public class LoginFilter extends HttpFilter {
    private static List<String> unCheckedUrls;
    static{
        unCheckedUrls = new ArrayList<>();
        unCheckedUrls.add("/article/articleList.jsp");
        unCheckedUrls.add("/login.jsp");
    }
    public static List<String> getUnCheckedUrls() {
        return unCheckedUrls;
    }

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String userSession = (String) request.getSession().getAttribute("userSession");
        String reqUrl = request.getServletPath();
        if(unCheckedUrls.contains(reqUrl)){
            chain.doFilter(request, response);
            return;
        }
        
        if(userSession != null){
            chain.doFilter(request, response);
            return;
        }
        
        response.sendRedirect(request.getContextPath() + "/login.jsp");
        
        
    }

}
LoginFilter.java
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }

    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        String methodName = request.getParameter("method");
        
        try {
            Method method = getClass().getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
            method.invoke(this,request,response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private UserDao userDao = new UserDao();
    
    public void login(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
        String username = request.getParameter("username");
        User user = userDao.getUser(username);
        //如果匹配到了用户,则生成session
        if(user != null){
            request.getSession().setAttribute("userSession",username);
            request.getRequestDispatcher("/article/articleList.jsp").forward(request, response);
            return;
        }
        //若未匹配到用户,提示用户不存在
        request.setAttribute("msg2", "用户不存在");
        request.getRequestDispatcher("/login.jsp").forward(request, response);
    }
    
    //登出时  移除session
    public void logout(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
        request.getSession().removeAttribute("userSession");
        response.sendRedirect(request.getContextPath() + "/article/articleList.jsp");
    }

}
LoginServlet.java
public class User {
    private String username;
    private List<Authority> authorities;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public List<Authority> getAuthorities() {
        return authorities;
    }
    public void setAuthorities(List<Authority> authorities) {
        this.authorities = authorities;
    }
    public User(String username, List<Authority> authorities) {
        super();
        this.username = username;
        this.authorities = authorities;
    }
    public User() {
        // TODO Auto-generated constructor stub
    }
    
}
User.java
public class UserDao {
    private static Map<String,User> users;
    private static List<Authority> authorities;
    static{
        authorities = new ArrayList<>();
        authorities.add(new Authority("article-1","/article/article-1.jsp"));
        authorities.add(new Authority("artilce-2", "/article/article-2.jsp"));
        authorities.add(new Authority("article-3", "/article/article-3.jsp"));
        authorities.add(new Authority("article-4", "/article/article-4.jsp"));
        
        users = new HashMap<String,User>();
        
        User user1 = new User("A", authorities.subList(0, 2));
        users.put("A", user1);
        
        User user2 = new User("B",authorities.subList(2, 4));
        users.put("B",user2);
    }
    public User getUser(String username){
        return users.get(username);
    }
    
    public static List<Authority> getAuthorities() {
        return authorities;
    }
    public void updateAthority(String username,List<Authority> athorities){
        users.get(username).setAuthorities(athorities);
    }
}
UserDao.java
/**
 * 自定义的HttpFilter类 实现Filter接口
 */
public abstract class HttpFilter implements Filter {
    /*
     * 用于保存filterConfig对象
     */
    private FilterConfig filterConfig;

    /**
     * Default constructor. 
     */
    public HttpFilter() {
   
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {

    }

    /**
     * 原生的doFilter()方法 在方法内部将ServletRequest和ServletResponse转化为HttpServletRequest
     * 和HttpServletResponse,并调用doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)
     * 方法
     * 
     * 若编写Filter的过滤方法 不建议直接继承该方法,而建议直接继承
     * doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)方法
     */
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;
        
        doFilter(request,response,chain);
    }
    
    
    /**
     * 抽象方法,为http请求定制,必须实现的方法
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    public abstract void doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)throws IOException, ServletException;

    /**
     * 不建议子类直接覆盖,若直接覆盖,将可能导致filterConfig成员变量初始化失败
     */
    public void init(FilterConfig fConfig) throws ServletException {
        this.filterConfig = fConfig;
        init();
    }
    /*
     * 供子类继承的初始化方法,可以通过getFilterConfig()获取filterConfig对象
     */
    protected void init() {}
    
    /*
     * 直接返回init(FilterConfig) 的FilterConfig对象
     */
    public FilterConfig getFilterConfig(){
        return filterConfig;
    }

}
HttpFilter.java
<body>
<font color="blue">Article-111111111111</font>
<br><br>
<a href="${pageContext.servletContext.contextPath}/article/articleList.jsp">返回列表页</a>
</body>
article-1.jsp
<body>
<a href="${pageContext.servletContext.contextPath}/article/article-1.jsp">article-1</a>
<br><br>
<a href="${pageContext.servletContext.contextPath}/article/article-2.jsp">article-2</a>
<br><br>
<a href="${pageContext.servletContext.contextPath}/article/article-3.jsp">article-3</a>
<br><br>
<a href="${pageContext.servletContext.contextPath}/article/article-4.jsp">article-4</a>

<c:set var="isDisplay" value="${sessionScope.userSession}"></c:set>
<c:if test="${isDisplay != null }">
    <br> <br>
    <a href="${pageContext.servletContext.contextPath}/loginServlet?method=logout">登出</a>
</c:if>
</body>
articleList.jsp
<body>

<font color="red">对不起,您没有权限访问该页面</font>
<a href="${pageContext.servletContext.contextPath}/article/articleList.jsp">返回列表页</a>

</body>
403.jsp
<body>
    <center>
    
    <form action="${pageContext.servletContext.contextPath}/athorityServlet?method=QueryAthority" method="post">
       username:<input type="text"  name="username">
       <input type="submit" name="submit" value="查询此人权限">
       <br><br>
    </form>
    <c:if test="${requestScope.msg1 != null }">
        <font color="red">${requestScope.msg1}</font>
        <br><br>
    </c:if>
    
    <c:if test="${requestScope.user != null }">
        <font color="purple">${requestScope.user.username}的权限列表如下:</font>
        <br><br>
        <form action="${pageContext.servletContext.contextPath}/athorityServlet?method=UpdateAthority" method="post">
            <input type="hidden" name="username" value="${requestScope.user.username }">
            <c:forEach items="${requestScope.authorities}" var="auth">
            <c:set var="flag" value="false"></c:set>
                <c:forEach items="${requestScope.user.authorities}" var="userauth">
                    <c:if test="${userauth.url == auth.url }">
                        <c:set var="flag" value="true"></c:set>
                    </c:if>
                </c:forEach>
                
            <c:if test="${flag == true}">
                <input name="authority" type="checkbox" value="${auth.url }" checked="checked">${auth.name}
                <br><br>
            </c:if>
            <c:if test="${flag == false}">
                <input name="authority" type="checkbox" value="${auth.url }" >${auth.name}
                <br><br>
            </c:if>
            </c:forEach>
            <input type="submit" name="submit" value="更新权限">
        </form>    
    
    </c:if>    
    </center>
    
    
</body>
authorityManager.jsp
<body>
<font color="red">您需要登录才能看到相关页面</font>
<br><br>
<form action="${pageContext.servletContext.contextPath}/loginServlet?method=login" method="post">
    username: <input type="text" name="username">
    <input type="submit" name="btn1" value="登录">
</form>
<c:if test="${requestScope.msg2 != null}">
    <font color="red">用户不存在</font>
</c:if>
</body>
login.jsp

80 HttpServletRequest

 2. HttpServletRequestWrapper和HttpServletResponseWrapper

1)原理 XXXwrapper是一个包装类,实现了一些接口

2)作用:可以自定义一个类,继承XXXWrapper类,用于对HttpServletRequest或HttpServletResponse的某一个方法进行修改,如

public class MyServletRequest extends HttpServletRequestWrapper{

    public MyServletRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getParameter(String name) {
        String val = super.getParameter("content");
        if(val != null && val.contains("love")){
            val = val.replace("love", "****");
        }
        return val;
    }

}
修改HttpServletRequest的getParameter方法

3)使用:在Filter,将HttpServletRequest替换为自定义的request

@WebFilter("/contentFilter")
public class ContentFilter extends HttpFilter {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        MyServletRequest myServletRequest = new MyServletRequest(request);
        chain.doFilter(myServletRequest, response);
    }
       
}
Filter

 以上例子实现了对用户输入文本的过滤

81 Filter小结(2)

对filter部分进行总结:

1 . 使用Filter实现简单的权限操作

1)MVC设计模式实现权限管理:

 > 页面完全使用JSTL和EL

 > Servlet受理请求,调用方法,转发或重定向页面

 > 面向对象的基本逻辑: Authority User 分别封装了权限和User信息

2)equals()方法的使用:List是否包含有指定的元素使用的是equals方法进行比较

因此list元素对象必须重写equals方法

2. HttpServletRequestWrapper

1)Why:

需要改变从Servlet容器(可能是任何的Servlet容器)中传入的HttpServletRequest 对象的某个行为,怎么办

① 继承HttpServletRequest接口的Servlet容器的实现类,但就和具体的容器相耦合了

② 提供HttpServletRequest接口的实现类,很麻烦,而且也需要和具体的容器相耦合

③ 使用装饰器设计模式:

  > 提供一个类,该类实现HttpServletRequest接口

  > 传入具体的一个容易实现的HttpServletRequest接口的实现类作为上述类的一个成员变量

  >使用HttpServletRequest成员变量来实现HttpServletRequest接口的所有方法

  > 再提供上述类的实现类,重写具体的方法即可

2)what:

servletRequestWrapper

3)How:

如何用在以上已说明

82 监听域对象创建和销毁的Listener

 3. ServletContextListener

1) what:监听ServletContext 对象被创建或销毁时的Servlet监听器

2)how:

  >创建一个实现了ServletContextListener接口的类,并且实现其中的两个方法

  public class MyServletContextListener implements Servlet

  >在web.xml文件中配置Listener

  <listener>

    <listener-class>com.test.listener.MyServletContextListener</listener-class>
  </listener>

3) why:ServletContextListener是最常见的Listener,可以在当前WEB应用被加载时对当前WEB应用的相关资源进行初始化操作:创建数据库连接池,创建Spring的IOC

容器,读取当前WEB应用的初始化参数...

4)API:

// ServletContext 对象被创建(即当前WEB应用被加载时)的时候,Servlet容器调用该方法

public void contextInitialized(ServletContextEvent arg0)

// ServletContext 对象被销毁之前(即当前WEB应用被卸载时)的时候,Servlet容器调用该方法

public void contextDestroyed(ServletContextEvent arg0)

ServletContextEvent中的:getServletContext() 获取ServletContext

4. ServletRequestListener & HttpSessionListener

1)和ServletContextListener一样

83 通过Listener理解域对象生命周期

2)利用ServletRequestListener、HttpSessionListener及ServletContextListener可以把request、session以及application的生命周期做更详细一步的了解

>request:是一个请求,当一个响应返回时,即被销毁。当发送一个请求时被创建,注意,请求转发的过程是一个request对象,重定向是两个请求

>session:当第一次访问WEB应用的一个jsp或Servlet时,且该jsp或Servlet中还需要创建session,此时服务器会创建一个session对象

session销毁:session过期,直接调用session的invalidate方法,当前WEB应用被卸载(session可以被持久化)

* 关闭浏览器,并不意味着session被销毁,还可以通过sessionid找到服务器中的session对象

>application:贯穿于当前WEB应用的生命周期。当前WEB应用被加载时创建application对象,当前WEB应用被卸载时销毁

84 其他的Servlet监听器 

 5. XxxAttributeListener

1). 监听ServletContext,HttpSession,ServleRequest 中添加属性,替换属性,移除属性的事件监听器

2). 以ServletRequestAttributeListener为例:

//添加属性的监听方法
@Override
public void attributeAdded(ServletRequestAttributeEvent arg0) {
// TODO Auto-generated method stub
}

//移除属性的监听方法

@Override
public void attributeRemoved(ServletRequestAttributeEvent arg0) {
// TODO Auto-generated method stub
}

//替换属性的监听方法

@Override
public void attributeReplaced(ServletRequestAttributeEvent arg0) {
// TODO Auto-generated method stub
}

3). 这三个监听器用的较少,了解即可

4). API:

ServletRequestAttributeListener: getName()获取属性的名字   getValue()获取属性的值   其他两个监听器的API跟这个是类似的

6. HttpSessionBindingListener

1)监听实现了该接口的Java类的对象被绑定到session或从session中解除绑定的事件

// 当前对象被绑定session时调用该方法

@Override
public void valueBound(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}

// 当前对象从session中解除绑定时调用该方法

@Override
public void valueUnbound(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}

2)该监听器不需要注册到web.xml中

3)HttpSessionBindingEvent :

getName()

getValue()

getSession()

4) 该监听器较少使用

7. HttpSessionActivationListener

1)监听实现了该接口和Serializable接口(若不实现该接口,则只能写到磁盘上,而不能读取出来)的Java类的对象随session钝化和活化事件

> 活化:从磁盘中读取session对象

> 钝化:向磁盘中写入session对象

> session对象存储在tomcat服务器的workCatalinacontextPath目录下

2)该监听器不需要注册在web.xml中

3)

//在活化之后被调用

@Override
public void sessionDidActivate(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}

//在钝化之前被调用

@Override
public void sessionWillPassivate(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}

HttpSessionEvent:getSession()

4) 该监听器较少使用

85 Servlet监听器小结

1. 监听器:专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监听的对象发生情况时,立即采取相应的行动

2. 监听器的分类:

1)监听域对象(HttpSession,request,application)自身的创建和销毁的事件监听器

2)监听域对象中的属性的增加和删除的事件监听器

3)监听绑定到HttpSession域中的某个对象的状态的事件监听器

3. 如何编写监听器:

1)编写实现监听器接口的Java类

public class HelloServletContextListener implements ServletContextListener

2) 对于第一种和第二种监听器需要在web.xml中进行注册:

<listener>
<listener-class>com.test.listener.MyServletContextListener</listener-class>
</listener>

4. 监听域对象(HttpSession,request,application)自身的创建和销毁的事件监听器

ServletContextListener:最常用的listener

ServletRequestListener

HttpSessionListener

在每一个监听器中都有两个方法:

  > 在域对象创建之后立即被调用的方法

  > 在域对象销毁前被调用的方法

方法的参数:以ServletContextEvent为例,该对象可以返回ServletContext对象

5. 一个例子:统计在线访客,可以把访客踢出其所在的session(略)

原文地址:https://www.cnblogs.com/hnini/p/5667067.html