欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第16章 JAVA EE基础学习-MVC设计模式说明-过滤器概述等

程序员文章站 2022-05-23 08:38:22
...

1 基础的MVC理解图如下:

第16章 JAVA EE基础学习-MVC设计模式说明-过滤器概述等

我们在开发中,常常采用MVC模式进行开发程序,但是在web中,我们常常采用JSP、HTML做界面View,然后Servlet做控制器Control,最后是数据模型Data Model和业务模型Business Model。

2 过滤器的理解图:

第16章 JAVA EE基础学习-MVC设计模式说明-过滤器概述等

2.1 过滤器 :

     我们项目中的某些资源我们并不想让客户直接访问,简单来说我们希望用户在登录之后才能访问我们的资源。于是我们就开始权限控制的道路上奔跑。Servlet中,我们可以很简单的做到这一步,就是增加过滤器filter类。然后配置web.xml进行配合编码完成我们的权限控制业务。

    简单的过滤器案例:

       字符编码过滤器 

 

/**
 * 工  程   名:SMS-20180522	<br>
 * 文  件   名:CharacterEncodeFilter.java	<br>
 * 工具包名:edu.fjnu.training.filter	<br>
 * 功能描述:TODO	<br>
 * 创建时间:2018年5月22日 下午9:13:57	<br>
 * 版本信息:V1.0
 * @创建人:周开伦	
 */
package edu.fjnu.training.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 类名:CharacterEncodeFilter	<br>
 * 功能描述:	<br> 
 * 创建日期:2018年5月22日 下午9:13:57	<br>
 * 修改备注:
 * @作者信息:Zhou kailun	<br>
 */
public class CharacterEncodeFilter implements Filter {

	/**<p>构造函数:</p><br><br>
	 * <p>描述:</p><br> 
	 */
	public CharacterEncodeFilter() { 
	}

	/* (非 Javadoc)
	 * <p>Title:destroy</p>
	 * <p>描       述:</p>
	 * @see javax.servlet.Filter#destroy()
	 */
	@Override
	public void destroy() { 
	}

	/* (非 Javadoc)
	 * <p>Title:doFilter</p>
	 * <p>描       述:</p>
	 * @param paramServletRequest
	 * @param paramServletResponse
	 * @param paramFilterChain
	 * @throws IOException
	 * @throws ServletException
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	@Override
	public void doFilter(ServletRequest request,
			ServletResponse response, FilterChain filterChain)
			throws IOException, ServletException {
	         //控制字符编码必须为utf-8过滤器
		request.setCharacterEncoding("utf-8");
		filterChain.doFilter(request, response);//放行继续下一步过滤操作直到访问到资源
	}

	/* (非 Javadoc)
	 * <p>Title:init</p>
	 * <p>描       述:</p>
	 * @param paramFilterConfig
	 * @throws ServletException
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	@Override
	public void init(FilterConfig paramFilterConfig) throws ServletException {
	}

}

       身份验证过滤器:

/**
 * 工  程   名:SMS-20180522	<br>
 * 文  件   名:AuthenFilter.java	<br>
 * 工具包名:edu.fjnu.training.filter	<br>
 * 功能描述:TODO	<br>
 * 创建时间:2018年5月22日 下午9:27:31	<br>
 * 版本信息:V1.0
 * @创建人:周开伦	
 */
package edu.fjnu.training.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 类名:AuthenFilter	身份验证过滤器<br>
 * 功能描述:	<br> 
 * 创建日期:2018年5月22日 下午9:27:31	<br>
 * 修改备注:
 * @作者信息:Zhou kailun	<br>
 */
public class AuthenFilter implements Filter {

	/**<p>构造函数:</p><br><br>
	 * <p>描述:</p><br> 
	 */
	public AuthenFilter() { 
	}

	/* (非 Javadoc)
	 * <p>Title:init</p>
	 * <p>描       述:</p>
	 * @param paramFilterConfig
	 * @throws ServletException
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	@Override
	public void init(FilterConfig paramFilterConfig) throws ServletException { 
	}

	/* (非 Javadoc)
	 * <p>Title:doFilter</p>
	 * <p>描       述:</p>
	 * @param paramServletRequest
	 * @param paramServletResponse
	 * @param paramFilterChain
	 * @throws IOException
	 * @throws ServletException
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	@Override
	public void doFilter(ServletRequest request,
			ServletResponse response, FilterChain filterChain)
			throws IOException, ServletException {
		 HttpServletRequest req=(HttpServletRequest)request;
		 HttpServletResponse res=(HttpServletResponse)response;
		 
		 String uri=req.getRequestURI();
		 String resource=uri.substring(uri.lastIndexOf("/")+1);
		 System.out.println("resource:"+resource);
		 if(resource.contains("smsMgr")){
			 Object obj=(Object)req.getSession().getAttribute("loginedUser");
			 if(obj==null){ 
				 res.sendRedirect("securityMgr?act=toLogin");
			 }
			 else{
				 filterChain.doFilter(request, response);
			 }
		 }
		 else
			 filterChain.doFilter(request, response);
	}

	/* (非 Javadoc)
	 * <p>Title:destroy</p>
	 * <p>描       述:</p>
	 * @see javax.servlet.Filter#destroy()
	 */
	@Override
	public void destroy() { 
	}

}

web.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
 
  <filter>
  	<filter-name>AuthenFilter</filter-name>
  	<description>这是我自己写的过滤器,拦截所有访问路径的操作,只要对我这个程序进行访问的请求我都进行身份验证</description>
  	<filter-class>edu.fjnu.training.filter.AuthenFilter</filter-class>
  </filter>
  
  <filter>
  	<filter-name>CharacterEncodeFilter</filter-name>
  	<description>这是我自己写的过滤器,拦截所有访问路径的操作,只要对我这个程序进行访问的请求我都拦截</description>
  	<filter-class>edu.fjnu.training.filter.CharacterEncodeFilter</filter-class>
  </filter>
  
  <filter-mapping>
  	<filter-name>CharacterEncodeFilter</filter-name>
 	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <filter-mapping>
  	<filter-name>AuthenFilter</filter-name>
 	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <servlet>
    <servlet-name>StudentMgrServlet</servlet-name>
    <display-name>This is the display name of my J2EE component</display-name>
    <description>This is the description of my J2EE component</description>
    <servlet-class>edu.fjnu.training.conrtoller.StudentMgrServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>SecurityMgrServlet</servlet-name>
    <display-name>This is the display name of my J2EE component</display-name>
    <description>This is the description of my J2EE component</description>
    <servlet-class>edu.fjnu.training.conrtoller.SecurityMgrServlet</servlet-class>
  </servlet>


  <servlet-mapping>
    <servlet-name>StudentMgrServlet</servlet-name>
    <url-pattern>/smsMgr</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>SecurityMgrServlet</servlet-name>
    <url-pattern>/securityMgr</url-pattern>
  </servlet-mapping>
  <!-- 设置所有jsps文件夹下的jsp文件不能直接被访问 -->
  <security-constraint>
  	<web-resource-collection>
  		<web-resource-name>jsp-pages</web-resource-name>
  		<url-pattern>/jsps/*</url-pattern><!-- 所有/jsps/文件下的文件都不能别访问 -->
  	</web-resource-collection>
  	<auth-constraint/>
  </security-constraint>
  
  <login-config>
  	<auth-method>BASIC</auth-method>
  </login-config>
</web-app>

filter过滤器的先后顺序:

依据其在web.xml 中的filter-mapping顺序有关,排在前面的优先级最先验证。以上是先进行编码认证,在进行身份认证。


然后我们看一些辅助代码:

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page"> 
  </head>
  
  <body>
   	<jsp:forward page="securityMgr?act=toLogin"></jsp:forward>
  </body>
</html>

login.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8" isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>登录操作</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
	<style type="text/css">
		.error{
			border:1px groove yellow;
			color:red;
			width:200px;
		}
	</style>
  </head>
  
  <body>
    <h3>登录界面请登录</h3>
    <form action="<c:url value="/securityMgr"></c:url>?act=login" method="post">
    	<div>
    		<span>账号:</span>
    		<input type="text" name="userNo" value="${param.userNo }">
    	</div>
    	<div>
    		<span>密码:</span>
    		<input type="password" name="userPwd">
    	</div>
    	<c:if test="${not empty errMsg}">
    		<div class="error">${errMsg }</div>
    	</c:if>
    	<div>
    		<input type="submit" value="登录">
    	</div>
    </form>
    <%@ include file="/jsps/footer.jsp" %>
  </body>
</html>
main.jsp  

 

<%@ page language="java" import="java.util.*" pageEncoding="utf-8" isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
	
	<script>
		function exitSys(){
			if(confirm("您确定要退出系统吗?")){   
				 
				location.href="<c:url value="/securityMgr"></c:url>?act=logout";
			}
		}
	</script>
  </head>
  
  <body>
    <h3>学生管理系统</h3>
    <div style="text-align:right;float:right;padding-right:10px;">
    	操作员:${loginedUser.userName }<button style="margin-left:5px;" onclick="exitSys();">退出</button>
    </div>
    <ul>
    	<li><a href="<c:url value="/smsMgr"/>?act=toReg">新生注册登记</a></li>
    	<li><a href="<c:url value="/smsMgr"/>?act=loadall">学生列表</a></li>
    	 
    </ul>
  </body>
</html>

footer.jsp:

<%@ page language="java" import="java.util.*,edu.fjnu.training.config.VersionInfo" pageEncoding="utf-8"%>
<hr>
<div style="text-align:center;color:gray;font-size:12px;">
	<%=VersionInfo.buildFooterStr() %>
</div>

SecurityMgrServlet.java  安全登录管理Servlet

package edu.fjnu.training.conrtoller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.fjnu.training.domain.User;
import edu.fjnu.training.exception.DataAccessException;
import edu.fjnu.training.exception.SMSException;
import edu.fjnu.training.service.UserService;
import edu.fjnu.training.service.UserServiceImpl;

public class SecurityMgrServlet extends HttpServlet {
	/**默认编码方式:*/
	private static final String ENCODE="utf-8"; 
	/**
	 * Constructor of the object.
	 */
	public SecurityMgrServlet() {
		super();
	}

	/**
	 * The doGet method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to get.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//request.setCharacterEncoding(ENCODE);
		
		String act=request.getParameter("act");
		
		if("toLogin".equals(act)){
			request.getRequestDispatcher("jsps/security/login.jsp").forward(request, response);
		}
		else if("login".equals(act)){
			String userNo=request.getParameter("userNo");
			String userPwd=request.getParameter("userPwd");
			 
			UserService userService=new UserServiceImpl(); 
			User user=null;
			
			try{
				user=userService.checkUser(userNo, userPwd);
				request.getSession().setAttribute("loginedUser", user);
				response.sendRedirect("securityMgr?act=main");;
			}catch(SMSException e){
				request.setAttribute("errMsg", e.getMessage());
				request.getRequestDispatcher("/jsps/security/login.jsp").forward(request, response);
			}
		}
		else if("main".equals(act)){
			request.getRequestDispatcher("/jsps/main.jsp").forward(request, response);
		}
		else if("logout".equals(act)){ 
			request.getSession().removeAttribute("loginedUser");
			request.getSession().invalidate();
			response.sendRedirect("securityMgr?act=toLogin");
		}
		
	}

	/**
	 * The doPost method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to post.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}

重点:

filter过滤器会出现一些异常。filter不能对同一个response多次重复重定向,也就是不能多次sendRedirect(“page.jsp”);否则会报错。