zoukankan      html  css  js  c++  java
  • 企业项目中---页面留痕处理的问题

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

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

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

    准备工作:

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

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

     以上仅供参考学习

  • 相关阅读:
    关于 RuntimeBinderException 异常
    IE 跨域session丢失问题
    一个简单的方法去掉angular application中URLs的hashtag
    ASP.NET MVC:通过 FileResult 向 浏览器 发送文件
    (转载)Why you shouldn't use Entity Framework with Transactions
    angular自启动过程
    HTML中的IE条件注释,让低版本IE也能正常运行HTML5+CSS3网站的3种解决方案
    angualrjs 总结 随记(三)
    angualrjs 总结 随记(二)
    angualrjs 总结 随记(一)
  • 原文地址:https://www.cnblogs.com/julinhuitianxia/p/7551437.html
Copyright © 2011-2022 走看看