Request wrapped, implement request attribute shared memory management

 

The filter wraps the request and can implement some shared attributes, such as getting the attr in the request from redis, which is beneficial to the cluster.

Hierarchical features: the lower filter is wrapped in the outer layer

 

 The local memory of requets that did not need to be packaged before, the inner requets that are packaged later is redis memory, all those that need to be shared are placed in the inner request, and generally placed in the outer request.

 

Design ideas:

The local memory of requets that did not need to be packaged in the past, the inner requets that have been packaged is redis memory. All the requets that need to be shared are placed in the inner layer, and generally in the outer layer. The general project starts with the local requst. If If it needs to be transformed, it must be a large number of requests that have already used local memory. At this time, you only need to put the newly added redis requset in the inner layer ---> It is reflected in the configuration that the configuration of the inner layer is placed in front of it. The configuration of the outer layer is at the back, and the outer layer is used for the most conventional usage.

 

shirohttprequest--->Ordinary requests exist in local memory

    remotequest---> contains a custom request, this request uses the proxy mode, as long as the set and getattribute() methods of the session of this object are used to enter the proxy, which calls sessionmanager to operate the memory of redis

         sessionmanager-->memory tools for operating redis

 

 

 ==================================

Note that the RemoteSessionRequest used to use the proxy sessionid to create and obtain the session. Using this will generate a proxy at a time, so it is a different session, so it cannot be obtained later. Here, the user code is directly used as the id:

 WebSessionid uses the user code, the user code is placed in the memory, and jsession+"username" is used as the key, see the following article for details

private HttpSession session = null;

 

private RemoteSessionHandler(HttpSession httpSession) {

this.session = httpSession;

};

 

public static HttpSession getInstance(HttpSession httpSession) {

InvocationHandler handler = new RemoteSessionHandler(httpSession);

return (HttpSession) Proxy.newProxyInstance(httpSession.getClass().getClassLoader(), httpSession.getClass().getInterfaces(), handler);

}

 

 

HttpServletRequest request1 =(HttpServletRequest) ((WebSubject)SecurityUtils.getSubject()).getServletRequest();

String id = session.getId();//用这个会一次请求生成一个代理,所以又是不同的session,导致后面拿不到

 

/if(args.length == 3){

id=shiroUser.getUserId();//创建一个固定的session

//}

WebSession webSession=WebSessionManager.getInstance().getSession(id);

 ================================================================

 

WebSessionManager就是session在redis内存中的具体操作

 

((RemoteSessionRequest)((ShiroHttpServletRequest)request).getRequest()).getSession().setAttribute("q","2");

((RemoteSessionRequest)((ShiroHttpServletRequest)request).getRequest()).getSession().getAttribute("q");

 



 

 

 另:

request在不同的代码包装的层次大同小异,比如由action获得的request里面有shirohttprequest再里面才有RemoteSessionRequest这种包装的request

 

ShiroHttpServletRequest srequest=(ShiroHttpServletRequest) ((StrutsRequestWrapper)ServletActionContext.getRequest()).getRequest();
Integer dispatchCustHQLForQueryCount =(Integer)(((RemoteSessionRequest)srequest.getRequest()).getSession().getAttribute("dispatchCustHQLForQueryCount"));//session.getAttribute("dispatchCustHQLForQueryCount");


 

 

<filter>

<filter-name>cors</filter-name>

<filter-class>com.common.CrossDomainFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>cors</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

 

 

 

 

<filter>

<filter-name>shiroFilter</filter-name>

<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

<init-param>

<param-name>targetFilterLifecycle</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>shiroFilter</filter-name>

<url-pattern>/*</url-pattern>

<dispatcher>REQUEST</dispatcher>

<dispatcher>FORWARD</dispatcher>

</filter-mapping>

<filter>

 

<filter>

        <filter-name>struts2</filter-name>

        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

    </filter>

 

    <filter-mapping>

        <filter-name>struts2</filter-name>

        <url-pattern>/*</url-pattern>

        <dispatcher>REQUEST</dispatcher>

<dispatcher>FORWARD</dispatcher>

    </filter-mapping>

 

 

    越在后面的被包在越外层

 

 

package com.common;

 

import core.session.filter.RemoteSessionRequest;

 

import java.io.IOException;

import java.util.Arrays;

import java.util.Enumeration;

import java.util.Vector;

 

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import javax.servlet.http.HttpServletResponse;

 

 

 

 

 

 

public final class CrossDomainFilter implements Filter {

private static final String VAL_ACCESS_CONTROL_ALLOW_ORIGIN = "*";

private static final String VAL_ACCESS_CONTROL_ALLOW_HEADERS = new StringBuilder(

"Origin,X-Requested-With,Content-Type,Accept").toString();

 

//    .append("," + AuthenticationConstants.X_AUTH_TOKEN)

//    .append("," + VersionDispatchFilter.HEADER_APP_VERSION)

 

    private static final String VAL_ACCESS_CONTROL_ALLOW_METHODS = "GET,POST,PUT,DELETE,OPTIONS";

 

@Override

public void init(FilterConfig filterConfig) throws ServletException {

 

}

 

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

HttpServletResponse httpResponse = (HttpServletResponse) response;

HttpServletRequest httpRequest = (HttpServletRequest) request;

 

httpResponse.addHeader("Access-Control-Allow-Origin", VAL_ACCESS_CONTROL_ALLOW_ORIGIN);

httpResponse.addHeader("Access-Control-Allow-Headers", VAL_ACCESS_CONTROL_ALLOW_HEADERS);

httpResponse.addHeader("Access-Control-Allow-Methods", VAL_ACCESS_CONTROL_ALLOW_METHODS);

httpResponse.addHeader("P3P", "CP=CAO PSA OUR");

if ("application/x-www-form-urlencoded".equals(httpRequest.getHeader("content-type"))) {

httpRequest = new CrossRequestWrapper(httpRequest);

}

 

try {

//if ("get".equals(httpRequest.getMethod().toLowerCase()) && StringUtils.isNotBlank(httpRequest.getParameter(AuthenticationConstants.X_AUTH_TOKEN))) {

//httpRequest.setAttribute(AuthenticationConstants.X_AUTH_TOKEN, httpRequest.getParameter(AuthenticationConstants.X_AUTH_TOKEN).trim());

//}

            if ("get".equals(httpRequest.getMethod().toLowerCase()) ) {

//                httpRequest.setAttribute(AuthenticationConstants.X_AUTH_TOKEN, httpRequest.getParameter(AuthenticationConstants.X_AUTH_TOKEN).trim());

            }

} catch (Throwable e) {

 

}

chain.doFilter(new RemoteSessionRequest((HttpServletRequest) httpRequest), response);

//chain.doFilter(httpRequest, response);

}

 

@Override

public void destroy() {

 

}

 

private class CrossRequestWrapper extends HttpServletRequestWrapper {

private CrossRequestWrapper(HttpServletRequest httpRequest) {

super(httpRequest);

}

 

@Override

public String getHeader(String name) {

if ("content-type".equals(name.toLowerCase())) {

return "application/json";

}

return super.getHeader(name);

}

 

@Override

public Enumeration<String> getHeaders(String name) {

if ("content-type".equals(name.toLowerCase())) {

return new Vector<String>(Arrays.asList("application/json")).elements();

}

return super.getHeaders(name);

}

 

 

public Enumeration<String> getHeaderNames() {

return super.getHeaderNames();

}

 

@Override

public String getContentType() {

return "application/json";

}

}

 

/*private class AuthTokenHttpServletRequest extends HttpServletRequestWrapper {

private final String requestBody;

public AuthTokenHttpServletRequest(HttpServletRequest request, String requestBody) {

super(request);

this.requestBody = requestBody;

}

 

public ServletInputStream getInputStream() {

try {

return new ByteServletInputStream(new ByteArrayInputStream(requestBody.getBytes("UTF-8")));

} catch (Throwable e) {

log.error("", e);

}

return null;

}

}

 

private class ByteServletInputStream extends ServletInputStream  {

private ByteArrayInputStream byteInputStream;

private ByteServletInputStream(ByteArrayInputStream byteInputStream) {

this.byteInputStream = byteInputStream;

}

 

@Override

public boolean isFinished() {

return byteInputStream.available() <= 0;

}

 

@Override

public boolean isReady() {

return true;

}

 

@Override

public void setReadListener(ReadListener readListener) {

// TODO Auto-generated method stub

 

}

 

@Override

public int read() throws IOException {

return byteInputStream.read();

}

 

}*/

}

 

 

 

 

 

 

package core.session.filter;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.util.HashMap;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import javax.servlet.http.HttpSession;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

 

import core.session.manager.RedisTemplateDelegate;

import core.session.manager.WebSession;

import core.session.manager.WebSessionManager;

import lombok.extern.log4j.Log4j2;

 

/**

 * 

 * <p>通过继承HttpServletRequestWrapper 来实现</p>

 * @author houzhanshan

 * @version $Id: RemoteSessionRequest.java, v 0.1 2017年5月26日 下午11:40:51 houzhanshan Exp $

 */

public class RemoteSessionRequest extends HttpServletRequestWrapper {

public RemoteSessionRequest(HttpServletRequest request) {

super(request);

}

 

@Override

public HttpSession getSession() {

return RemoteSessionHandler.getInstance(super.getSession());

}

}

@Log4j2

class RemoteSessionHandler implements InvocationHandler {

// 模拟远程Session服务器,Key表示SessionId,Value表示该Session的内容

private static Map<String, Map<String, Object>> map = new ConcurrentHashMap<String, Map<String, Object>>();

private static Logger log= LoggerFactory.getLogger(RedisTemplateDelegate.class);

private HttpSession session = null;

 

private RemoteSessionHandler(HttpSession httpSession) {

this.session = httpSession;

};

 

public static HttpSession getInstance(HttpSession httpSession) {

InvocationHandler handler = new RemoteSessionHandler(httpSession);

return (HttpSession) Proxy.newProxyInstance(httpSession.getClass().getClassLoader(), httpSession.getClass().getInterfaces(), handler);

}

 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if ("setAttribute".equals(method.getName())) {

String id = session.getId();

Map<String, Object> m = map.get(id);

if (m == null) {

m = new HashMap<String, Object>();

 

}

WebSession webSession=WebSessionManager.getInstance().getSession(id);

if(webSession==null){

webSession=WebSessionManager.getInstance().createSession(id);

}else{

webSession=WebSessionManager.getInstance().getSession(id);

 

}

webSession.setAttribute((String) args[0], args[1]);

log.info("[存入]key:" + args[0] + ",value:" + args[1]);

return null;

} else if ("getAttribute".equals(method.getName())) {

String id = session.getId();

WebSession webSession= WebSessionManager.getInstance().getSession(id);

if(webSession==null){

return null;

}

Object result = webSession.getAttribute((String) args[0]);

log.info("[取出]key:" + args[0] + ",value:" + result);

return result;

}

return method.invoke(session, args);

}

 

}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326034454&siteId=291194637