request包装的,实现request属性共享内存管理
过滤器包装request的,可以实现一些共享的属性,比如将request中的attr从redis中获取等有利于集群,
层次特性:在越下面的过滤器包在越外层
以前不用包的requets本地内存,后面包了的内层requets是redis内存,所有需要共享的放在内层request,一般的放在外层request即可
设计思路:
以前不用包的requets本地内存,后面包了的内层requets是redis内存,所有需要共享的放在内层,一般的放在外层即可,一般的项目都是开始用的是本地的requst,如果需要改造的话必定是大量已经用了本地内存的request,此时只要把新加的操作redis的requset放在内层即可--->体现在配置上就是放在内层的配置在前面,放在外层的配置在后面,外层的就是最常规的用法用的
shirohttprequest--->普通的request存在本地内存
remotequest--->内包了自定义的requst,这个requst用了代理模式,只要用到这个对象的session的set,getattribute()方式就进入代理,这个里面调用sessionmanager操作redis的内存
sessionmanager-->操作redis的内存工具
==================================
注意其中的RemoteSessionRequest以前用的是代理sessionid创建获取session,用这个会一次请求生成一个代理,所以又是不同的session,导致后面拿不到,这里改造直接用用户代码做id:
WebSessionid用用户代码,用户代码放在内存中,用jsession+"username"为key,详见后面的文章
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);
}
}
上一篇: 求一款好用的CMS