淺談JavaWeb中監聽器、過濾器、攔截器
阿新 • • 發佈:2019-01-11
執行順序:
Javaweb
context-param-->listener-->filter-->servlet
Springmvc
context-param-->listener-->filter-->servlet-->interceptor(指的是攔截器),為什麼攔截器是在servlet執行之後,因為攔截器本身就是在servlet內部的
使用技巧:
需要監聽到專案中的一些資訊,並且不需要對流程做更改時,用監聽器;當需要過濾掉其中的部分資訊,只留一部分時,就用過濾器;當需要對其流程進行更改,做相關的記錄時用攔截器。過濾器是處於客戶端與伺服器資原始檔之間的一道過濾網,在訪問資原始檔之前,通過一系列的過濾器對請求進行修改、判斷等,把不符合規則的請求在中途攔截或修改。也可以對響應進行過濾,攔截或修改響應
(ps:類似aop)
過濾器
public class urlEncodeFilter implements Filter{ Logger logger = LoggerFactory.getLogger(urlEncodeFilter.class); Map<String,Object> paramMap = new HashMap<String,Object>(); @Override public void destroy() { } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("urlEncodeFilter doFilter..."+paramMap.get("urlEncode").toString()); arg0.setCharacterEncoding(paramMap.get("urlEncode").toString()); arg2.doFilter(arg0, arg1); } @Override public void init(FilterConfig arg0) throws ServletException { String urlEncode = arg0.getInitParameter("urlEncode"); paramMap.put("urlEncode",urlEncode); } }
<filter> <filter-name>urlEncodeFilter</filter-name> <filter-class>com.mycompany.mvc.filter.urlEncodeFilter</filter-class> <init-param> <param-name>urlEncode</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>urlEncodeFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
攔截器:
<mvc:interceptors>
<!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 -->
<bean class="com.host.app.web.interceptor.AllInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/test/number.do"/>
<!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 -->
<bean class="com.host.app.web.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
public class LogsInterceptor extends HandlerInterceptorAdapter {
private static final Logger logger = LoggerFactory.getLogger(LogsInterceptor.class);
private NamedThreadLocal<String> logContext = new NamedThreadLocal<String>("log-id");
@Autowired
private TLogDao logDao;
/**
* preHandle方法是進行處理器攔截用的,顧名思義,該方法將在Controller處理之前進行呼叫,
* SpringMVC中的Interceptor攔截器是鏈式的,可以同時存在多個Interceptor,
* 然後SpringMVC會根據宣告的前後順序一個接一個的執行,
* 而且所有的Interceptor中的preHandle方法都會在Controller方法呼叫之前呼叫。
* SpringMVC的這種Interceptor鏈式結構也是可以進行中斷的,
* 這種中斷方式是令preHandle的返回值為false,當preHandle的返回值為false的時候整個請求就結束了。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String host = request.getRemoteHost();
String url = request.getRequestURI();
TLogEntity entity = new TLogEntity();
entity.setCreateTime(new Timestamp(System.currentTimeMillis()));
entity.setCreateUser("admin");
entity.setIpAddress(host);
entity.setLogUrl(url);
entity.setIsSuccess("N");
logDao.save(entity);
logContext.set(entity.getLogId());
logger.debug("IP為---->>> " + host + " <<<-----訪問了系統");
return true;
}
/**
* 這個方法只會在當前這個Interceptor的preHandle方法返回值為true的時候才會執行。
* postHandle是進行處理器攔截用的,它的執行時間是在處理器進行處理之 後, 也就是在Controller的方法呼叫之後執行,
* 但是它會在DispatcherServlet進行檢視的渲染之前執行,也就是說在這個方法中你可以對ModelAndView進行操作。
* 這個方法的鏈式結構跟正常訪問的方向是相反的,也就是說先宣告的Interceptor攔截器該方法反而會後呼叫,
* 這跟Struts2裡面的攔截器的執行過程有點像,
* 只是Struts2裡面的intercept方法中要手動的呼叫ActionInvocation的invoke方法,
* Struts2中呼叫ActionInvocation的invoke方法就是呼叫下一個Interceptor或者是呼叫action,
* 然後要在Interceptor之前呼叫的內容都寫在呼叫invoke之前,要在Interceptor之後呼叫的內容都寫在呼叫invoke方法之後。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 該方法也是需要當前對應的Interceptor的preHandle方法的返回值為true時才會執行。
* 該方法將在整個請求完成之後,也就是DispatcherServlet渲染了檢視執行, 這個方法的主要作用是用於清理資源的,
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
String host = request.getRemoteHost();
String logId = logContext.get();
TLogEntity entity = logDao.findOne(logId);
entity.setIsSuccess("Y");
logDao.save(entity);
logger.debug("IP為---->>> " + host + " <<<-----訪問成功");
}
}
監聽器:
按監聽的物件劃分,可以分為
ServletContext物件監聽器
HttpSession物件監聽器
ServletRequest物件監聽器
按監聽的事件劃分
物件自身的建立和銷燬的監聽器
物件中屬性的建立和消除的監聽器
session中的某個物件的狀態變化的監聽器
<listener> <listener-class>
com.mycompany.mvc.listener.myServletContextListener
</listener-class>
</listener>
<listener>
<listener-class>
com.mycompany.mvc.listener.myServletContextAttributeListener
</listener-class>
</listener>
public class myHttpSessionListener implements HttpSessionListener{
public static int peopleOnLine = 0;
@Override
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("myHttpSessionListener.sessionCreated():"+arg0);
peopleOnLine++;
arg0.getSession().setAttribute("peopleOnLine",peopleOnLine);
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
System.out.println("myHttpSessionListener.sessionDestroyed():"+arg0);
peopleOnLine--;
arg0.getSession().setAttribute("peopleOnLine",peopleOnLine);
}
}
攔截器例項:
public class AdminLoginHandlerInterceptor extends LoginHandlerInterceptor {
@Autowired
private BaseService baseService;
@Override
@SuppressWarnings("unchecked")
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
if(request.getServletPath().matches(".*/((assets)|(js)|(images)|(common)|(public)).*") || request.getServletPath().contains("/api")){
super.postHandle(request, response, handler, modelAndView);
return;
}
Object hd = request.getSession().getAttribute(Constant.SESSION_MENU);
if(modelAndView != null && hd != null) {
Map<String,String> subsetMap = this.checkSubset();
modelAndView.addObject("hd", hd);
Map<String, Boolean> authMap = new HashMap<String, Boolean>();
Map<String, Object> headerInfo = (Map<String, Object>)hd;
Object obj = headerInfo.get("menuList");
if(obj != null) {
for(Menu menu : (List<Menu>)obj) {
menu.setActive(false);
if(request.getServletPath().endsWith(menu.getUrl()) || (subsetMap.containsKey(menu.getUrl()) && subsetMap.get(menu.getUrl()).contains(request.getServletPath()))) {
addAuthButton(authMap, menu);
menu.setActive(true);
break;
}
boolean isEnd = false;
if(menu.getSubMenu() != null && menu.getSubMenu().size() > 0) {
for(Menu subMenu : menu.getSubMenu()) {
if(StringUtils.isBlank(subMenu.getUrl())) {
continue;
}
if(request.getServletPath().endsWith(subMenu.getUrl())) {
addAuthButton(authMap, subMenu);
menu.setActive(true);
isEnd = true;
break;
}
}
}
if(isEnd) {
break;
}
}
}
modelAndView.addObject("auth", authMap);
List<SysSystemConfig> configList = baseService.getList(
SysSystemConfig.class,
Collections.singletonList(Where.in(SysSystemConfigDomain.NID, new String[]{"site_logo", "site_name", "site_keywords", "site_discription", "site_copyright"})),
Parameter.queryColumn(new String[] {SysSystemConfigDomain.NID,SysSystemConfigDomain.VALUE})
);
if(configList != null && configList.size() > 0) {
for(SysSystemConfig config : configList) {
if("site_logo".equals(config.getNid())) {
modelAndView.addObject(config.getNid(), PropertiesUtil.getImageHost() + config.getValue());
} else {
modelAndView.addObject(config.getNid(), config.getValue());
}
}
}
}
super.postHandle(request, response, handler, modelAndView);
}
private void addAuthButton(Map<String, Boolean> authMap, Menu menu) {
if(menu == null || menu.getSubMenu() == null) {
return;
}
for(Menu btn : menu.getSubMenu()) {
if(!btn.getUrl().startsWith("btn:") || !btn.isChecked() ) {
continue;
}
authMap.put(btn.getUrl().replace("btn:", ""), true);
}
}
private Map<String, String> checkSubset() {
Map<String, String> subsetMap = new HashMap<String, String>();
subsetMap.put("platform/manager/list", "/platform/manager/detail,");
subsetMap.put("project/loan/list", "/project/loan/detail,");
subsetMap.put("loan/loan/list", "/loan/loan/detail,");
return subsetMap;
}
}
public class LoginHandlerInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String path = request.getServletPath();
if ("/".equals(path))
return true;
if (path.matches(".*/((assets)|(js)|(images)|(common)|(public)).*"))
return true;
for (String newPath : list) {
if (path.matches(newPath)) {
return true;
}
}
if (request.getSession().getAttribute(Constant.SESSION_USER) == null) {
System.out.println("---------------");
response.sendRedirect(request.getContextPath() + Constant.LOGIN_URL);
return false;
}
return true;
}
/**
* 免攔截的url
*/
public static List<String> list = new ArrayList<String>();
static {
//備案平臺管理
list.add("/platform/list");
list.add("/platform/toList");
list.add("/platform/listpage");
list.add("/platform/detail");
list.add("/platform/detailpage");
list.add("/system/platform/checkNum");
list.add("/system/platform/info");
list.add("/system/platform/toIndex");
list.add("/platform/listDetail");
list.add("/platform/statistics/risk");
//使用者中心
list.add("/member/member/memberInfo");
list.add("/api/project") ;
list.add("/api/repay") ;
list.add("/phone/location/get") ;
}
}