JShop简介:jshop是一套使用Java语言开发的B2C网店系统,致力于为个人和中小企业提供免费、好用的网店系统。
项目主页:http://git.oschina.net/dinguangx/jshop
在线演示:
- 前台: http://jshop.ofmall.org:81/jshop
- 后台: http://jshop.ofmall.org:81/jshop/manage/user/login (admin/123456)
在spring mvc中,为了随时都能取到当前请求的request对象,可以通过RequestContextHolder的静态方法getRequestAttributes()获取Request相关的变量,如request, response等。
在jshop中,对RequestContextHolder的使用进一步封装,简化为RequestHolder类,如下:
public class RequestHolder {
public static HttpServletRequest getRequest(){
HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return req;
}
public static HttpServletResponse getResponse(){
HttpServletResponse resp = ((ServletWebRequest)RequestContextHolder.getRequestAttributes()).getResponse();
return resp;
}
}
在大部分的情况下,它都能很好地工作,但在商品管理编辑中,新增商品时,却出现了意外的问题:通过RequestHolder.getRequest().getParameter()得不到参数值,通过debug发现,通过spring mvc的method注入的request对象实际为MultipartHttpServletRequest,而通过RequestHolder.getRequest()获取到的request对象却是RequestFacfade的实例。
原来在商品新增时,由于使用了文件上传,form表单的enctype类型为”multipart/form-data”,spring mvc对文件上传的处理类实际却为spring-mvc.xml文件中配置的CommonsMultipartResolver, 该类先判断当前请求是否为multipart类型,如果是的话,将request对象转为MultipartHttpServletRequet,相关的源码见DisptcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
......
processedRequest = checkMultipart(request);
multipartRequestParsed = processedRequest != request;
......
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
......
}
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (request instanceof MultipartHttpServletRequest) {
logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
"this typically results from an additional MultipartFilter in web.xml");
}
else {
return this.multipartResolver.resolveMultipart(request);
}
}
// If not returned before: return original request.
return request;
}
那么,RequestContextHolder中的request又是从哪来的呢?
继续翻看DispatcherServlet的源码,从其父类FrameworkServlet中找到的processRequest()以相关方法源码:
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
......
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
initContextHolders(request, localeContext, requestAttributes);
try {
doService(request, response);
}
......
}
protected ServletRequestAttributes buildRequestAttributes(
HttpServletRequest request, HttpServletResponse response, RequestAttributes previousAttributes) {
if (previousAttributes == null || previousAttributes instanceof ServletRequestAttributes) {
return new ServletRequestAttributes(request);
}
else {
return null; // preserve the pre-bound RequestAttributes instance
}
}
private void initContextHolders(
HttpServletRequest request, LocaleContext localeContext, RequestAttributes requestAttributes) {
if (localeContext != null) {
LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
}
if (requestAttributes != null) {
RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
}
if (logger.isTraceEnabled()) {
logger.trace("Bound request context to thread: " + request);
}
}
从这里可以看到,initContextHolder()方法中完成了RequestContextHolder的requestAttributes设置,而doService()在这之后调用,DispatcherServlet中的processRequest()方法即在doService()之中,所以从RequestContextHolder中获取到的就是原来的RequestFacade对象,而不是经过spring mvc处理之后的MultipartHttpServletRequest对象,其后果就是,从RequestContextHolder获取request后,无法直接通过getParameter()获取参数值。
最便捷的解决办法:
直接将HttpServletRequest作为spring mvc的方法入参,即可以正确获取参数值。
相关推荐
文件中包含的是HTN规划器JSHOP2源码,用于配置JSHOP2环境,详细的教程请参考个人博客内容,JSHOP2环境配置
主要是有关jshop2的介绍以及使用的一篇文档,因为使用jshop2的人不是很多,所以资源找起来相对比较困难,这是我看jshop2主要的文档信息,很有用
jshop3完美的界面
#JShop JShop是Jeeshop的分支版本,与Jeeshop最大的区别在于技术选型上的差异:使用spring mvc替换strutus2使用freemarker替换jsp使用maven替换传统的项目结构管理将免费进行得更彻底:使用 ()替换easyui(因为...
前台使用uni-app开发,适配性多,在页面的打开和渲染效率上更快,下单流程流畅自然,可大大增加用户体验,提升订单量。 强大的促销引擎,多种促销方式自由搭配,满足各种场景的促销方式需求,做活动更灵活简单,...
Jshop是开源的springMVC B2C电商系统
jshop2-master.zip 全的
京东JSHOP店铺装修右侧悬浮代码。可调整为左侧悬浮。
附带make.bat文件,并做了自己的修改。可以直接运行bat文件,添加环境变量即可exe中运行。详细配置过程见我的一篇博客《JSHOP2的环境配置——详细教程(原创)》中
JSHOP2_1.0.3规划器下载,最新版
JSHOP2为SHOP的Java版本,智能规划系统,可用于服务任务规划
开源的Jshop微信小程序源码1.1版,包括微信小程序前端和后端接口源码。Jshop小程序商城,是一款开源的电商系统,为中小企业提供移动电子商务解决方案。后台采用Thinkphp5.1框架开发,执行效率、扩展性、稳定性值得...
文件中包含有GitHub上的JSHOP2资源的源代码,以及我自己整理的能够直接运行的代码(在justRun文件夹下,里面的readme有详细的操作说明)。
Jshop短信插件_小程序商城短信接口开发_B2B商城短信发送设置
Jeeshop独立网店系统(B2C)jar包齐全,可运行,欢迎各位热爱java的朋友学习spring,Mybatis,Framemaker,bootStrap
sdywcd-ostocy-jshop 是Android平台下的在线商城程序,内有详细介绍!
并且Jshop小程序商城上手难度低,可大量节省定制化开发周期。 前台H5使用Vue开发,在页面的打开和渲染效率上更快,下单流程流畅自然,可大大增加用户体验,提升订单量。 强大的促销引擎,多种促销方式自由搭配,满足...
Jshop_V小程序商城发送验证码功能,插件下载即可用,简单易上手
开源商城Jshop的后台多页签功能,请按文件中操作说明操作,做好备份。
Jshop小程序商城,是一款开源的电商系统,为中小企业提供移动电子商务解决方案。后台采用Thinkphp5.1框架开发,执行效率、扩展性、稳定性值得信赖,前台H5采用VUE开发,增加用户体验。 Jshop小程序商城关于开源 这...