In the enterprise, we often analyze the users who use our system, such as: what pages he likes to browse the system, that is, the frequency of browsing, and what functions he uses most. We need to do page marking!
In the company confidentiality agreement, I do not map. I can only record some thorny problems I encountered in writing this function, just for novice reference, avoid detours!
Tip: Before reading this article, you need to know something about interceptors and filters!
Dead work:
Filter: Generally speaking, it is a filter. Before accessing the target resources, add a filter, do some processing work in advance, and then let the program access the target resources.
Define a filter: Write a java class implements Filter interface and rewrite three methods: destroy, doFilter and init.
/** * * @ClassName:InterceptUrl * @Package:com.ly.filter * @Description:Filter * @author:ljl * @version:v0.1 * @data:2017 September 18, 10:52:01 * Remarks: */ public class FilterUrl implements Filter { @Override public void destroy() { System.out.println("The filter was destroyed..."); } @Override public void doFilter(ServletRequest param1, ServletResponse param2, FilterChain chain) throws IOException, ServletException { System.out.println("Entry filter..."); //Filter Processing Code System.out.println("Filtering end..."); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("Initialization filter..."); } }
Configuration in web.xml: Configuration in web.xml plays a global role. Any filter path that conforms to the filter path will be first filtered into the filter before accessing the target resource.
<filter> < filter-name > FilterUrl </filter-name > filter name <filter-class>com.ly.filter.FilterUrl</filter-class> defines the classpath of the filter </filter> <filter-mapping> < filter-name > FilterUrl </filter-name > filter name <url-pattern>/app/*</url-pattern> filtering path </filter-mapping>
Springmvc interceptor:
This kind of interceptor aims at processing before, during and after accessing the Controller method.
Interceptor interception requests in Spring MVC are implemented through Handler Interceptor. Defining an Interceptor in Spring MVC is very simple. There are two main ways. The first way is to define an Interceptor class to implement Spring's Handler Interceptor interface, or to inherit the class that implements Handler Interceptor interface, such as the abstract class Handler Interceptor Adapter that Spring has provided to implement Handler Interceptor interface. The second way is to implement Spring's WebRequestInterceptor interface, or to inherit classes that implement WebRequestInterceptor.
Definitions are as follows:
/** * * @ClassName:InterceptorUrl * @Package:com.ly.interceptor * @Description:Interceptor, intercept all requests * @author:ljl * @version:v0.1 * @data:2017 September 18, 2:21:38 p.m. * Remarks: */ public class InterceptorUrl extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // In execution Controller Processing before method //Return true To execute postHandle Method return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { super.postHandle(request, response, handler, modelAndView); //implement Controller Method... } @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); //implement Controller After the method... } }
Spring-servlet.xml is configured as follows:
<?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 Interceptor --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/app/**"/> Configuration of Interceptor Path <bean class="com.ly.interceptor.InterceptorUrl"/> Interceptor class </mvc:interceptor> </mvc:interceptors> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /> <!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/> --> <!-- This is to replace the line above. bean Following treatment ajax The problem of scrambling when returning data doesn't work (in my case, it doesn't work) <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>
After the preparations are finished, we will get to the main topic: writing page markings
I. thinking
1. How to judge whether a user is browsing a page? How to record?
Method: Interceptor, or filter (sometimes not applicable).
Intercept or filter requests, or url s, to obtain relevant information from HttpServletRequest objects: such as user IP; insert it into database tables, and use it for data analysis later.
Record the method of getting IP by hand:
import java.net.InetAddress; import javax.servlet.http.HttpServletRequest; /** * * @ClassName:RemoteAddress * @Package:cc.makalu.remoteaddr.util * @Description:Get the core class of visitor's IP address * @author:ljl * @version:v0.1 * @data:2017 September 15, 6:11:49 p.m. * Remarks: */ public class RemoteAddress { /** * * @Title: getIPAddress * @Description: The Method of Obtaining Ip Address from request * @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")) { //Acquisition based on network card IP InetAddress inet = null; try { inet = InetAddress.getLocalHost(); } catch(Exception e) { e.printStackTrace(); } ipAddress = inet.getHostAddress(); } } // For the case of multiple agents, the first IP Truthfulness for Clients IP,Multiple IP according to','Division if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length() // = 15 if (ipAddress.indexOf(",") > 0) { ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); } } return ipAddress; } }
If it is an interceptor, it can also get the class name, package, request path.
Two. Problem
Which way to choose: filter and interceptor can basically meet the needs, but the filter has a problem: I directly get the test results, but also hope not to take detours in the future.
1. The request.getParameter() method cannot be used to obtain parameter values in filter. (So choose the interceptor.) The target seems to be unsolvable!
2. The interface of mapper or service layer can be injected into filter.
For the second conclusion, the method is given:
public class FilterUrl implements Filter { //injection AccountMapper private AccountService accountService; @Override public void destroy() { System.out.println("The filter was destroyed..."); } @Override public void doFilter(ServletRequest param1, ServletResponse param2, FilterChain chain) throws IOException, ServletException { System.out.println("Entry filter..."); System.out.println("Filtering end..."); } @Override public void init(FilterConfig arg0) throws ServletException { ServletContext sc = arg0.getServletContext();
//The following code completes the mapper interface injection, that is to say, the method in the mapper interface can be accessed. XmlWebApplicationContext cxt = (XmlWebApplicationContext) WebApplicationContextUtils.getWebApplicationContext(sc); if(cxt != null && cxt.getBean("accountService") != null && accountService == null) accountService = (AccountService) cxt.getBean("accountService"); System.out.println("Initialization filter..."); } }
Then the interceptor is chosen for implementation, but two serious problems arise:
1.ajax accesses the controller layer method and reports 406 errors through the jackson handled json returned by @Response?
2. Resolve the problem of Chinese scrambling after 406 errors are returned to the past json string???
The first question is that:
First, an ajax method on the front page requests the controller layer method:
@RequestMapping(value="testCode")
@ ResponseBody jackson automatic conversion json
public Object testCode(String tellPhone,String code,HttpServletRequest request){
Map<String, Object> result = new HashMap<String,Object>();
result.put("info", "hello"); Does the front desk get the value in disorder?
result.put("code", code);
return result;
}
ajax method:
$.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); // Chinese scrambling appears here
$("#code").val("");
}else{
a = false;
}
}
});
Visit page directly reported 406 errors! The controller method is not executed.
406: This means that the content feature of the request can not be used to respond to the request. There was a mistake when json was sent to the front desk.
Looked for a lot of information, tried a lot of methods are not good.
Solution 406:
Before returning to result, the JSONObject.fromObject method is used to convert the json string again.
As follows:
@RequestMapping(value="testCode")
@ ResponseBody jackson automatic conversion json
public Object testCode(String tellPhone,String code,HttpServletRequest request){
Map<String, Object> result = new HashMap<String,Object>();
result.put("info", "hello"); Does the front desk get the value in disorder?
result.put("code", code);
JSONObject json = JSONObject.fromObject(result);
return json.toString(); Resolve 406 errors
}
Then came the second problem: to solve the 406 error and return the past json string in the page appeared Chinese scrambling problem???
Backstage json is normal, just go to the page?? I haven't met you before.
Find a way in the post bar:
@ Request Mapping (value = "testCode", method = RequestMethod. POST, produces = {"application/json; charset = UTF-8"}) // Add this sentence to solve perfectly
@ResponseBody
public Object testCode(String tellPhone,String code,HttpServletRequest request){
Map<String, Object> result = new HashMap<String,Object>();
result.put("info", "hello");
result.put("code", code);
return result;
}
The above is for reference only.