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 改进前:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.List" import="com.test.mvc.domain.Customer" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<%
List<Customer> customers = (List<Customer>)request.getAttribute("customers");
if(customers != null && customers.size() > 0){
%>
<table cellpadding="10" border="1" cellspacing="0">
<tr>
<th>id</th>
<th>name</th>
<th>address</th>
<th>phone</th>
<th>操作</th>
</tr>
<%
for(Customer customer:customers){
%>
<tr>
<td><%= customer.getId() %></td>
<td><%= customer.getName() %></td>
<td><%= customer.getAddress() %></td>
<td><%= customer.getPhone() %></td>
<td>
<a href="editCustomer.do?customerId=<%= customer.getId() %>">update</a>
<!-- class关联到jquery -->
<a href="deleteCustomer.do?customerId=<%= customer.getId() %>" class="delete">delete</a>
</td>
</tr>
<%
}
%>
</table> <%
} %>
</body>
</html>
01 改进后:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.List" import="com.test.mvc.domain.Customer" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %> <c:if test="${! empty requestScope.customers}">
<table cellpadding="10" border="1" cellspacing="0">
<tr>
<th>id</th>
<th>name</th>
<th>address</th>
<th>phone</th>
<th>操作</th>
</tr>
<c:forEach items="${requestScope.customers}" var="cust">
<tr>
<td>${cust.id}</td>
<td>${cust.name }</td>
<td>${cust.address}</td>
<td>${cust.phone}</td>
<td>
<c:url value="/editCustomer.do" var="editCustomer">
<c:param name="customerId" value="${cust.id}"></c:param>
</c:url>
<a href="${editCustomer}">update</a>
<c:url value="/deleteCustomer.do" var="deleteCustomer">
<c:param name="customerId" value="${cust.id}"></c:param>
</c:url>
<a href="${deleteCustomer}" class="delete">delete</a>
</td>
</tr>
</c:forEach>
</table>
</c:if> </body>
</html>
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 改进前和改进后
<a><%= request.getAttribute("message") == null ? "":request.getAttribute("message") %></a> <%
String id = null;
String oldName = null;
String name = null;
String address = null;
String phone = null; Customer customer = (Customer)request.getAttribute("customer"); if(customer != null){
id = customer.getId() + "";
oldName = customer.getName();
name = customer.getName();
address = customer.getAddress();
phone = customer.getPhone();
}else{
id = request.getParameter("id");
oldName = request.getParameter("oldName");
name = request.getParameter("oldName");
address = request.getParameter("address");
phone = request.getParameter("phone"); }
%>
<c:if test="${! empty requestScope.message}">
${requestScope.message}
</c:if> <c:set var="cust" value="${requestScope.customer}"></c:set>
<c:set var="id" value="${cust != null ? cust.id : param.id }"></c:set>
<c:set var="oldName" value="${cust != null ? cust.name : param.oldName }"></c:set>
<c:set var="name" value="${cust != null ? cust.name : param.oldName }"></c:set>
<c:set var="address" value="${cust != null ? cust.address : param.address }"></c:set>
<c:set var="phone" value="${cust != null ? cust.phone : param.phone }"></c:set> <form action="updateCustomer.do" method="post">
<input type="hidden" name="id" value="${cust.id}"/>
<input type="hidden" name="oldName" value="${cust.oldName}"/>
<table>
<tr>
<td>name:</td>
<td><input type="text" name="name"
value="${name != null ? name : '' }"/></td>
</tr> <tr>
<td>address:</td>
<td><input type="text" name="address"
value="${address != null ? address : '' }"/></td>
</tr> <tr>
<td>phone:</td>
<td><input type="text" name="phone"
value="${phone != null ? phone : '' }"/></td>
</tr> <tr>
<td><input type="submit" value="保存修改"/></td>
<tr>
</table>
</form>
中文编码问题还是没有解决,工程 / 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&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>
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>
<body> <font color="green">Hello,Tom!!!</font> </body>
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;
} }
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;
} }
以上为全部相关代码。
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;
} }
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); } }
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>
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>
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>
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);
} }
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服务器的work\Catalina\contextPath目录下
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(略)
java学习笔记-JavaWeb篇三的更多相关文章
- java学习笔记-JavaWeb篇一
JavaWEB篇一 1 Tomcat的安装和配置 2 JavaWeb开发的目录结构 3 使用Eclipse开发JavaWeb项目 4 第一个Servlet程序 5 Servlet 的配置及生命周期方法 ...
- java学习笔记-JavaWeb篇二
JavaWEB篇二 45 HttpSession概述46 HttpSession的生命周期 47 HttpSession常用方法示例48 HttpSessionURL重写 49 HttpSession ...
- java学习笔记-JavaWeb篇四
86 文件上传基础 87 使用 fileupload 组件 88 文件上传案例_需求 89 文件上传案例_JS代码 90 文件上传案例_约束的可配置性 91 文件上传案例_总体步骤分析 92 文件上传 ...
- Java菜鸟学习笔记--数组篇(三):二维数组
定义 //1.二维数组的定义 //2.二维数组的内存空间 //3.不规则数组 package me.array; public class Array2Demo{ public static void ...
- 20145316许心远《Java学习笔记》第三周总结
20145316许心远<Java程序设计>第3周学习总结 教材学习内容总结 一.定义类: 类定义时使用class关键字 如果要将x绑定到新建的对象上,可以使用"="制定 ...
- Java学习笔记——基础篇
Tips1:eclipse中会经常用到System.out.println方法,可以先输入syso,然后eclipse就会自动联想出这个语句了!! 学习笔记: *包.权限控制 1.包(package) ...
- Java 学习笔记提高篇
Java笔记(提高篇)整理 主要内容: 面向对象 异常 数组 常用类 集合 IO流 线程 反射 Socket编程 1. 面向对象 1.1包 用来管理Java中的类, 类似文件夹管理文件一样. 因 ...
- java学习笔记-基础篇
Java基础篇 1—12 常识 13 this关键字 14参数传递 16 继承 17 访问权限 28—31异常 1—12 常识 1.文件夹以列表展示,显示扩展名,在地址栏显示全路径 2.javac编译 ...
- java学习笔记(基础篇)—面向对象编程之封装、继承、多态
一. OOP中的基本概念 Java的编程语言是面向对象的,采用这种语言进行编程称为面向对象编程(Object-Oriented Programming, OOP), 它允许设计者将面向对象设计实现为一 ...
随机推荐
- Ubuntu14.04安装Torch7笔记
Ubuntu14.04安装Torch7笔记 利用快捷键Ctrl+Alt+T打开Ubuntu终端 第一步: 获取安装LuauJIT(C语言编写的Lua的解释器)和Torch所必需的依赖包. 代码如下: ...
- opencv3.2.0图像处理之中值滤波medianBlur API函数
/*中值滤波:medianBlur函数是非线性滤波 函数原型:void medianBlur(inputArray src,OutputArray dst,int ksize) 参数详解: input ...
- Spring Boot—21Actuator--监控
https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/htmlsingle/ pom.xml <dependency&g ...
- iOS如何解析crash文件中的地址
1.目录中存放app文件 2.打开文件 3.执行命令otool -arch arm64 -l ./QQStock | grep -B 1 -A 10 "LC_SEGM" | gr ...
- Python爬虫实战---抓取图书馆借阅信息
Python爬虫实战---抓取图书馆借阅信息 原创作品,引用请表明出处:Python爬虫实战---抓取图书馆借阅信息 前段时间在图书馆借了很多书,借得多了就容易忘记每本书的应还日期,老是担心自己会违约 ...
- idea常用到的命令
idea大小写转换:ctr+shift+u ctrl+alt+b,跳转到接口的方法实现处
- EF的连表查询Lambda表达式和linq语句
select c; ), b=> b.Id, p=> p.BlogId, (b, p) => new {b}); public class Blog { public int Id ...
- 解决python2和python3的pip冲突
最近突然出现了一种情况当电脑上同时安装python2和python3的时候会导致我的pip冲突 . 最终经过我的发现是因为其环境没有配置好 还有就是没有找到精准的包导致的 1.下载python2.7, ...
- UIWindow的windowLevel详解
UIWindow的windowLevel详解
- Python学习---爬虫学习[scrapy框架初识]
Scrapy Scrapy是一个框架,可以帮助我们进行创建项目,运行项目,可以帮我们下载,解析网页,同时支持cookies和自定义其他功能. Scrapy是一个为了爬取网站数据,提取结构性数据而编写的 ...