企业项目中---页面留痕处理的问题

在企业中,我们经常会对使用我们系统的用户进行分析,比如:他喜欢浏览系统的什么页面即浏览的频率,使用什么功能最多。对此我们需要进行页面留痕处理操作!

处于公司保密协议,我不贴图。只能记录一下自己在写这个功能遇到的一些棘手的问题,仅供新手参考,少走弯路!

提示:在看本文前,你需要对拦截器和过滤器有所了解!

准备工作:

过滤器:通俗的说就是滤网。在访问目标资源前加上滤网,提前做一些处理工作,然后再让程序去访问目标资源。

定义一个过滤器:编写一个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;
    }

 

 

 以上仅供参考学习

 

posted @ 2017-09-19 13:44  懒得烧蛇吃  阅读(1776)  评论(2编辑  收藏  举报