企業項目中---頁面留痕處理的問題


在企業中,我們經常會對使用我們系統的用戶進行分析,比如:他喜歡瀏覽系統的什么頁面即瀏覽的頻率,使用什么功能最多。對此我們需要進行頁面留痕處理操作!

處於公司保密協議,我不貼圖。只能記錄一下自己在寫這個功能遇到的一些棘手的問題,僅供新手參考,少走彎路!

提示:在看本文前,你需要對攔截器和過濾器有所了解!

准備工作:

過濾器:通俗的說就是濾網。在訪問目標資源前加上濾網,提前做一些處理工作,然后再讓程序去訪問目標資源。

定義一個過濾器:編寫一個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;
    }

 

 

 以上僅供參考學習

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM