基于服务器端保存用户的查询参数
基于服务器端保存用户的查询参数
最近公司项目有一个新的需求, 希望用户在PC查询的参数能够同步更新到APP端, 避免让用户在PC和APP端重复输入查询条件, 基于项目是前后端分离, APP和PC的请求参数都是一样的且都是POST请求, 因此考虑采用拦截器的方式拦截获取POST请求中的请求体, 同时前端请求后台时, 统一在Header中加入当前页面名称(pageName)的参数, 以用户Sessioin中的工号和pageName作为key, 将请求参数保存到Mongodb中, 基本的方案就是这样, 下面是具体实现
自定义线程池
/**
* 线程池配置
*
* @author Eric on 2019/5/4.
* @version 1.0
*/
@Configuration
public class ThreadPoolConfig {
private static final int PROCESSOR_NUM = Runtime.getRuntime().availableProcessors();
private static final int MIN_CORE_SIZE = PROCESSOR_NUM < 8 ? 16 : PROCESSOR_NUM * 2;
private static final String DEFAULT_THREAD = "default";
@Bean("default")
public ThreadPoolTaskExecutor executorService() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setThreadNamePrefix(DEFAULT_THREAD);
executor.setCorePoolSize(MIN_CORE_SIZE);
executor.setMaxPoolSize(PROCESSOR_NUM * 16);
executor.setQueueCapacity(PROCESSOR_NUM * 2);
executor.setKeepAliveSeconds(30);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
自定义拦截器
HelloService封装了保存到Mongodb或者更新到Mongodb的操作 用户信息是从session中获取, 具体用户信息的实体类可以自定义
/**
* 记录本次请求参数的拦截器
*
* @author wang.js on 2019/4/26.
* @version 1.0
*/
@Component
public class RequestParamInterceptor implements HandlerInterceptor {
@Resource
private HelloService helloService;
@Resource(name = "default")
private ThreadPoolTaskExecutor executor;
private static final Logger LOGGER = LoggerFactory.getLogger(RequestParamInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) {
HttpSession session = httpServletRequest.getSession();
if (session != null) {
String pageName = httpServletRequest.getHeader("pageName");
SystemUser user = (SystemUser) session.getAttribute("user");
String body = new RequestWrapper(httpServletRequest).getBody();
if (user != null && !StringUtils.isEmpty(pageName) && !StringUtils.isEmpty(body)) {
executor.submit(() -> {
helloService.saveOrUpdate(new MongoBean(pageName + user.getStaffCode(), body), "test");
LOGGER.info("保存成功, key:{}, value:{}", pageName + user.getStaffCode(), body);
});
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
}
}
HellService
HellService只是封装了Mongodb的保存和更新操作, 仅供参考
/**
* @author wang.js
* @date 2018/10/29
* @copyright yougou.com
*/
@Service
public class HelloService {
@Autowired
private MongoBeanDao mongoBeanDao;
/**
* 保存
* @param mongoBean
*/
public void save(MongoBean mongoBean) {
mongoBeanDao.insert(mongoBean, "test");
}
/**
* 查找
* @param id
*/
public MongoBean find(String id, String collectionName) {
Query query = new Query(Criteria.where("id").is(id));
return mongoBeanDao.findByQuery(query, MongoBean.class, collectionName);
}
/**
* 更新
*
* @param mongoBean
* @param collectionName
* @return
*/
public boolean update(MongoBean mongoBean, String collectionName) {
Update update = new Update().set("value", mongoBean.getValue());
Query query = new Query(Criteria.where("id").is(mongoBean.getId()));
mongoBeanDao.updateByQuery(update, query, MongoBean.class, collectionName);
return true;
}
public void saveOrUpdate(MongoBean mongoBean, String collectionName) {
MongoBean mongoBean1 = find(mongoBean.getId(), collectionName);
if (mongoBean1 == null) {
save(mongoBean);
} else {
update(mongoBean, collectionName);
}
}
}
自定义HttpServletRequestWrapper
因为HttpServletRequest的输入流只能读取一次, 所以这里使用自定义HttpServletRequestWrapper将body中的信息保存起来, 方便后续多次使用 /** * @author wang.js on 2019/4/26. * @version 1.0 */ public class RequestWrapper extends HttpServletRequestWrapper {
private final String body;
public RequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
String getBody() {
return this.body;
}
}
注册filter
/**
* 过滤器
*
* @author wang.js on 2019/4/26.
* @version 1.0
*/
@WebFilter(urlPatterns = "/*",filterName = "channelFilter")
public class ChannelFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(servletRequest instanceof HttpServletRequest) {
requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
}
if(requestWrapper == null) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
}
@Override
public void destroy() {
}
}
自定义webMvc的配置
/**
* 自定义webMvc的配置
*
* @author Eric on 2018/8/19.
* @version 1.0
*/
@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
@Resource
private RequestParamInterceptor requestParamInterceptor;
/**
* 加入到Spring MVC的拦截器链中
*
* @param registry 拦截器注册
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestParamInterceptor);
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
super.configurePathMatch(configurer);
}
}
以上操作就可以把在PC和APP端的请求参数保存到Mongodb中, 之后用户进入相应的页面时, 只需要根据当前页面的pageName来获取该用户上次的请求参数即可