基于服务器端保存用户的查询参数

基于服务器端保存用户的查询参数

最近公司项目有一个新的需求, 希望用户在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来获取该用户上次的请求参数即可

posted on 2019-05-04 18:06  忘记送  阅读(289)  评论(0编辑  收藏  举报