企业项目中---页面留痕处理的问题
在企业中,我们经常会对使用我们系统的用户进行分析,比如:他喜欢浏览系统的什么页面即浏览的频率,使用什么功能最多。对此我们需要进行页面留痕处理操作!
处于公司保密协议,我不贴图。只能记录一下自己在写这个功能遇到的一些棘手的问题,仅供新手参考,少走弯路!
提示:在看本文前,你需要对拦截器和过滤器有所了解!
准备工作:
过滤器:通俗的说就是滤网。在访问目标资源前加上滤网,提前做一些处理工作,然后再让程序去访问目标资源。
定义一个过滤器:编写一个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;
}
以上仅供参考学习