首页 > 编程知识 正文

urllib.request是什么模块,request.getheader()的使用

时间:2023-05-06 05:45:14 阅读:146924 作者:460

SpringMVC学习记录(九(-RequestContextHolder分析

选项卡(以空格分隔):javaWEB

最近面临的问题是在服务中获取请求和响应。 服务层通常没有请求。 但是,如果是直接从控制ller那里传来的话,解决方法太粗暴了。 然后,我们发现并分析了SpringMVC提供的RequestContextHolder,并将其借用

1 .使用1.RequestContextHolder

RequestContextHolder顾名思义,是具有上下文的Request容器。 使用简单,具体使用以下:

//两种方法在没有使用JSF的项目中是分不开的

requestattributesrequestattributes=requestcontextholder.currentrequestattributes (;

//requestcontextholder.getrequest attributes (;

从会话中获取对应的值

String str=(String ) request attributes.getattribute (' name ',request attributes.scope _ session );

htpservletrequestrequest=((servletrequestattributes ) requestattributes ).getRequest );

httpservletresponseresponse=((servletrequestattributes ) requestattributes ).getResponse );

看到这个,一般会想到几个问题:

1 .请求和响应如何与当前请求联系起来?

2 .请求和响应等是什么时候设置的?

2 .解决疑问

2.1请求和响应如何与当前请求联系起来?

首先分析一个名为RequestContextHolder的类时,两个ThreadLocal存储当前线程上的请求。 关于ThreadLocal,请参考我的另一篇博文Java学习记录thread local的使用案例

//获得保存的请求

privatestaticfinalthreadlocalrequestattributesrequestattributesholder=

newnamedthreadlocalrequestattributes (请求属性);

//被子线程可继承request

私密性staticfinalthreadlocalrequestattributesinheritablerequestattributesholder=

newnamedinheritablethreadlocalrequestattributes ('请求上下文);

另外,如果观察getRequestAttributes ()方法,则相当于直接取得ThreadLocal中的值,由此确保每次取得时Request都是该请求的Request。

publicstaticrequestattributesgetrequestattributes (

requestattributesattributes=requestattributesholder.get (;

if (属性==null ) {

attributes=inheritablerequestattributesholder.get (;

}

返回属性;

}

2.2请求、响应等是什么时候设置的?

要查找它,必须了解springMVC结构的dispatcher servlet的结构,才能准确地找到应该在哪里查找相关代码。

IDEA显示以下继承关系:

左边是servlet的接口和实现类。

右侧是使SpringMVC具有Spring的几个环境变量和Spring容器。 同样的xxxAware接口为这个类提供了Spring识别,简单来说,如果想使用Spring的XXX,就可以实现XXXAware,Spring会发送所需的东西。

剩下的是三个班

简单看下源码 
1. HttpServletBean 进行初始化工作 
2. FrameworkServlet 初始化 WebApplicationContext,并提供service方法预处理请求 
3. DispatcherServlet 具体分发处理.

那么就可以在FrameworkServlet查看到该类重写了service(),doGet(),doPost()…等方法,这些实现里面都有一个预处理方法processRequest(request, response);,所以定位到了我们要找的位置

查看processRequest(request, response);的实现,具体可以分为三步: 
1. 获取上一个请求的参数 
2. 重新建立新的参数 
3. 设置到XXContextHolder 
4. 父类的service()处理请求 
5. 恢复request 
6. 发布事件

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        long startTime = System.currentTimeMillis();
        Throwable failureCause = null;
        //获取上一个请求保存的LocaleContext
        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
        //建立新的LocaleContext
        LocaleContext localeContext = buildLocaleContext(request);
        //获取上一个请求保存的RequestAttributes
        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
        //建立新的RequestAttributes
        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);
        }
        catch (ServletException ex) {
            failureCause = ex;
            throw ex;
        }
        catch (IOException ex) {
            failureCause = ex;
            throw ex;
        }
        catch (Throwable ex) {
            failureCause = ex;
            throw new NestedServletException("Request processing failed", ex);
        }

        finally {
            //恢复
            resetContextHolders(request, previousLocaleContext, previousAttributes);
            if (requestAttributes != null) {
                requestAttributes.requestCompleted();
            }

            if (logger.isDebugEnabled()) {
                if (failureCause != null) {
                    this.logger.debug("Could not complete request", failureCause);
                }
                else {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        logger.debug("Leaving response open for concurrent processing");
                    }
                    else {
                        this.logger.debug("Successfully completed request");
                    }
                }
            }
            //发布事件
            publishRequestHandledEvent(request, response, startTime, failureCause);
        }
    }

再看initContextHolders(request, localeContext, requestAttributes)方法,把新的RequestAttributes设置进LocalThread,实际上保存的类型为ServletRequestAttributes,这也是为什么在使用的时候可以把RequestAttributes强转为ServletRequestAttributes.

    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);
        }
    }

因此RequestContextHolder里面最终保存的为ServletRequestAttributes,这个类相比RequestAttributes方法是多了很多.

项目示例可以参考: 
SSM框架整合: https://github.com/nl101531/JavaWEB

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。