在企業中,我們經常會對使用我們系統的用戶進行分析,比如:他喜歡瀏覽系統的什么頁面即瀏覽的頻率,使用什么功能最多。對此我們需要進行頁面留痕處理操作!
處於公司保密協議,我不貼圖。只能記錄一下自己在寫這個功能遇到的一些棘手的問題,僅供新手參考,少走彎路!
提示:在看本文前,你需要對攔截器和過濾器有所了解!
准備工作:
過濾器:通俗的說就是濾網。在訪問目標資源前加上濾網,提前做一些處理工作,然后再讓程序去訪問目標資源。
定義一個過濾器:編寫一個java類implements Filter接口即可,重寫其中的三個方法:destroy(過濾器銷毀方法)、doFilter(過濾方法)、init(初始化過濾器)
/** * * @ClassName:InterceptUrl * @Package:com.ly.filter * @Description:過濾器 * @author:ljl * @version:v0.1 * @data:2017年9月18日 上午10:52:01 * 備注: */ public class FilterUrl implements Filter { @Override public void destroy() { System.out.println("過濾器銷毀了..."); } @Override public void doFilter(ServletRequest param1, ServletResponse param2, FilterChain chain) throws IOException, ServletException { System.out.println("進入過濾器..."); //過濾處理代碼 System.out.println("過濾結束..."); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("初始化過濾器..."); } }
在web.xml中的配置:在web.xml中配置的是起全局作用,任何符合過濾路徑的都會被先進入過濾器中,過濾一下才會去訪問目標資源。
<filter> <filter-name>FilterUrl</filter-name> 過濾器名稱 <filter-class>com.ly.filter.FilterUrl</filter-class> 定義過濾器的類路徑 </filter> <filter-mapping> <filter-name>FilterUrl</filter-name> 過濾器名稱 <url-pattern>/app/*</url-pattern> 過濾路徑 </filter-mapping>
Springmvc攔截器:
此類攔截器針對是在訪問Controller方法前、中、后做處理。
SpringMVC 中的Interceptor 攔截請求是通過HandlerInterceptor 來實現的。在SpringMVC 中定義一個Interceptor 非常簡單,主要有兩種方式,第一種方式是要定義的Interceptor類要實現了Spring 的HandlerInterceptor 接口,或者是這個類繼承實現了HandlerInterceptor 接口的類,比如Spring 已經提供的實現了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter ;第二種方式是實現Spring的WebRequestInterceptor接口,或者是繼承實現了WebRequestInterceptor的類。
定義如下:
/** * * @ClassName:InterceptorUrl * @Package:com.ly.interceptor * @Description:攔截器,攔截所有請求 * @author:ljl * @version:v0.1 * @data:2017年9月18日 下午2:21:38 * 備注: */ public class InterceptorUrl extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在執行Controller方法之前做處理 //返回true才能去執行postHandle方法 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { super.postHandle(request, response, handler, modelAndView); //執行Controller方法中。。。 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub super.afterCompletion(request, response, handler, ex); //執行Controller方法之后。。。。 } }
Spring-servlet.xml中配置如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- SpringMVC攔截器 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/app/**"/> 配置攔截器的路徑 <bean class="com.ly.interceptor.InterceptorUrl"/> 攔截器類 </mvc:interceptor> </mvc:interceptors> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /> <!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/> --> <!-- 這個是替換上面一行的bean 以下處理ajax返回數據時亂碼問題,但並不起作用(針對我的情況不起作用) <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name = "messageConverters"> <list> <bean class = "org.springframework.http.converter.StringHttpMessageConverter"> <property name = "supportedMediaTypes"><list><value>text/plain;charset=UTF-8</value></list></property> </bean> </list> </property> </bean> --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="interceptors"> <list> </list> </property> </bean> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> </beans>
准備工作完了,接下來進入正題:編寫頁面留痕
一.思路
1.如何判斷一個用戶正在瀏覽某個頁面?如何記錄?
方法:攔截器,或者過濾器(有時不適用)。
攔截或過濾請求即url,從HttpServletRequest對象中獲取相關信息:比如用戶IP;插入到數據庫表中即可,后期做數據分析使用。
順手記錄一下獲取IP的方法:
import java.net.InetAddress; import javax.servlet.http.HttpServletRequest; /** * * @ClassName:RemoteAddress * @Package:cc.makalu.remoteaddr.util * @Description:獲取訪問者的IP地址核心類 * @author:ljl * @version:v0.1 * @data:2017年9月15日 下午6:11:49 * 備注: */ public class RemoteAddress { /** * * @Title: getIPAddress * @Description: 從request獲取Ip地址的方法 * @return: String * @throws * @param request * @return */ public static String getIPAddress(HttpServletRequest request) { String ipAddress = request.getHeader("x-forwarded-for"); if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("Proxy-Client-IP"); } if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("WL-Proxy-Client-IP"); } if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) { //根據網卡獲取IP InetAddress inet = null; try { inet = InetAddress.getLocalHost(); } catch(Exception e) { e.printStackTrace(); } ipAddress = inet.getHostAddress(); } } // 對於通過多個代理的情況,第一個IP為客戶端真實IP,多個IP按照','分割 if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length() // = 15 if (ipAddress.indexOf(",") > 0) { ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); } } return ipAddress; } }
如果是攔截器:還能獲取類名、包、請求路徑。
二. 問題
選擇哪種方式:過濾器和攔截器基本都可以完成需要,但是過濾器存在一下問題:我直接給測試結果得出的,也希望以后不要走彎路
1.filter中無法通過request.getParameter()方法獲取參數值。(所以還是選擇攔截器吧)目標貌似無法解決!
2.在filter中是可以對mapper或service層的接口進行注入的。
對於第二個結論給出方法:
public class FilterUrl implements Filter { //注入AccountMapper private AccountService accountService; @Override public void destroy() { System.out.println("過濾器銷毀了..."); } @Override public void doFilter(ServletRequest param1, ServletResponse param2, FilterChain chain) throws IOException, ServletException { System.out.println("進入過濾器..."); System.out.println("過濾結束..."); } @Override public void init(FilterConfig arg0) throws ServletException { ServletContext sc = arg0.getServletContext();
//以下代碼完成mapper接口注入,就是說可以訪問mapper接口里的方法了。 XmlWebApplicationContext cxt = (XmlWebApplicationContext) WebApplicationContextUtils.getWebApplicationContext(sc); if(cxt != null && cxt.getBean("accountService") != null && accountService == null) accountService = (AccountService) cxt.getBean("accountService"); System.out.println("初始化過濾器..."); } }
然后選擇攔截器實現,但是出現了兩個嚴重的問題:
1.ajax訪問controller層方法,通過@Response返回的jackson處理的json,報406錯誤?
2.解決掉406錯誤之后回傳過去的json字符串中出現中文亂碼問題???
第一個問題,是這樣的情況:
首先前台頁面的一個ajax方法請求controller層方法:
@RequestMapping(value="testCode")
@ResponseBody jackson自動轉換json
public Object testCode(String tellPhone,String code,HttpServletRequest request){
Map<String, Object> result = new HashMap<String,Object>();
result.put("info", "你好"); 前台獲取該值出現亂碼??
result.put("code", code);
return result;
}
ajax方法:
$.ajax({
type: "post",
url: "${pageContext.request.contextPath}/app/order/testCode.html",
data: data1,
dataType: "json",
contentType: "application/x-www-form-urlencoded;charset=utf-8",
async : false,
success: function(data1){
if(data1.info != "ok"){
a = true;
alert(data1.info); //此處出現中文亂碼
$("#code").val("");
}else{
a = false;
}
}
});
訪問頁面直接報了406錯誤!就沒有執行到controller方法。
406:表示無法使用請求的內容特性來響應請求的網頁,json傳到前台出錯了。
找了很多資料,試了很多方法都不行。
解決406方法:
在返回result前,使用JSONObject.fromObject方法再次轉換成json字符串。
如下:
@RequestMapping(value="testCode")
@ResponseBody jackson自動轉換json
public Object testCode(String tellPhone,String code,HttpServletRequest request){
Map<String, Object> result = new HashMap<String,Object>();
result.put("info", "你好"); 前台獲取該值出現亂碼??
result.put("code", code);
JSONObject json = JSONObject.fromObject(result);
return json.toString(); 解決406錯誤
}
隨之出現了第二個問題:解決掉406錯誤之后回傳過去的json字符串在頁面中出現中文亂碼問題???
后台json是正常的,到了頁面就成??,以前沒遇到過。
在貼吧里找到方法:
@RequestMapping(value="testCode",method=RequestMethod.POST,produces = {"application/json;charset=UTF-8"}) //加上這一句完美解決
@ResponseBody
public Object testCode(String tellPhone,String code,HttpServletRequest request){
Map<String, Object> result = new HashMap<String,Object>();
result.put("info", "你好");
result.put("code", code);
return result;
}
以上僅供參考學習