tomcat study 第十一章

第十一章:StandardWrapper
 1.loadServlet方法:
if如果属性instance不为null则返回
else:
加载classClass = classLoader.loadClass(actualClass);
实例化servlet = (Servlet) classClass.newInstance();
调用init方法servlet.init(facade);
当if ((loadOnStartup > 0) && (jspFile != null)) 
{
调用service方法servlet.service(req, res);
	}
(其中监听事件触发这里省略[有调用service方法servlet.service(req, res);])
返回return servlet;
2.allocate方法:
根据singleThreadModel值判断走不同分支:一不是stm子类,一是stm子类
instance = loadServlet();	

instancePool.push(loadServlet());
(Servlet) instancePool.pop();

STM子类执行:(STM的思想作用)
synchronized (instancePool) {
 //当同时挤进来多个连接(wraperValue.invole没有结束)
        //当第一连接进来:
        	//maxInstances=2
        	//countAllocated=0
        	//nInstances=0
        	//第一次while后
        	//maxInstances=5
        	//countAllocated=0
        	//nInstances=1
        	//while条件不成立向下走:countAllocated(++)=1
        //当第二连接进来:
        	//maxInstances=2
        	//countAllocated=1
        	//nInstances=1
        	//第二次while后
        	//maxInstances=2
        	//countAllocated=2
        	//nInstances=2
        	//while条件不成立向下走:countAllocated(++)=2
        //当第三连接进来:
        	//maxInstances=2
        	//countAllocated=2
        	//nInstances=2
        	//没法进入if (nInstances < maxInstances) {}
        	//阻塞 当deallocate执行时
        	//maxInstances=2
        	//countAllocated=1
        	//nInstances=2
        	//while条件不成立向下走:countAllocated(++)=2
        	//再次阻塞可以说会一直阻塞;当执行unload时会等待(countAllocated是否为0)剩余执行完毕(此时countAllocated=0);
        	//最后wraperValue.invole结束
        	//nInstances当前STM 实例的个数
            while (countAllocated >= nInstances){
                // Allocate a new instance if possible, or else wait
                if (nInstances < maxInstances) {
                    try {
                        instancePool.push(loadServlet());
                        nInstances++;
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        throw new ServletException
                            (sm.getString("standardWrapper.allocate"), e);
                    }
                } else {
                    try {
                        instancePool.wait();
                    } catch (InterruptedException e) {
                        ;
                    }
                }
            }
            if (debug >= 2)
                log("  Returning allocated STM instance");
            countAllocated++;
            return (Servlet) instancePool.pop();
bug(或疑问):如上的“//当第三连接进来”只要nInstances的值达到maxInstances时说明本次invole只能等待结束,instancePool中的sevlet不能被继续使用。因为nInstances只有递增。只有结束才变为0(nInstances=0)

3.deallocate(servlet)方法:
主要instancePool.push(servlet)方法,进行回收;(适用stm子类)
4.unload();方法:
Thread.currentThread().setContextClassLoader(classLoader);
instance.destroy();
instance = null;

//如果是stm且instancePool池不为null
if (singleThreadModel && (instancePool != null))
{
((Servlet) instancePool.pop()).destroy();
instancePool = null;
}
问题:当StandardWrapperValve.invoke结束时:其他sevletclass(非STM)正在执行怎么办
答案:当执行unload时会等待(countAllocated是否为0)剩余执行完毕(此时countAllocated=0);
StandardWrapperValve
Invoke方法:
StandardWrapper wrapper = (StandardWrapper) getContainer(); 
servlet = wrapper.allocate();
ApplicationFilterChain filterChain = createFilterChain(request, servlet);

filterChain.doFilter(sreq, sres);

wrapper.deallocate(servlet);

wrapper.unload();
过滤器:
StandardWrapperValve.invoke():
调用createFilterChain方法生成ApplicationFilterChain filterChain;
调用filterChain.doFilter(sreq, sres);
createFilterChain:
获得所有的ApplicationFilterConfigs
StandardContext context = (StandardContext) wrapper.getParent();
      FilterMap filterMaps[] = context.findFilterMaps();
遍历ApplicationFilterConfigs
筛选合适的ApplicationFilterConfig
if (!matchFiltersURL(filterMaps[i], requestPath))
                continue;
if (!matchFiltersServlet(filterMaps[i], servletName))
                continue;
            ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
                context.findFilterConfig(filterMaps[i].getFilterName());
把合适的ApplicationFilterConfig放入filterChain中
filterChain.addFilter(filterConfig);
doFilter,internalDoFilter:
	从ApplicationFilterConfig中获得Filter
	filter = filterConfig.getFilter();通过FilterDef的描述生成new filter
执行Filter的doFilter方法
	filter.doFilter(request, response, this);
	最后执行servlet.service(request, response);
web.xml:
	<filter>
		<filter-name>httpOnlyFilter</filter-name>
		<filter-class>..cn.filter.HttpOnlyFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>httpOnlyFilter</filter-name>
		<url-pattern>/vl/*</url-pattern>
	</filter-mapping>
HttpOnlyFilter 实现Filter接口 。FilterDef一一对应的是web.xml中<filter>
Realm(138)
http://www.cnblogs.com/ansen/articles/2017360.html
LoginConfig和下面一一对应
•  <login-config>   
•    <auth-method>FORM</auth-method>   
•    <form-login-config>   
•       <form-login-page>/login/a.html   
•       </form-login-page>   
•       <form-error-page>/login/error.html   
•       </form-error-page>   
•    </form-login-config>   
•  </login-config>  
AuthenticatorBase 继承ValveBase
SimpleRealm中缓存ArrayList users数据
SimpleContextConfig监听器(context的监听器)加载阀门BasicAuthenticator
在BasicAuthenticator.invoke()中调用authenticate(hrequest, hresponse, config)
通过context.getRealm().authenticate(username, password) 进行获取Principal.如果存在进行register缓存失败根据LoginConfig中设置的数据进行处理
SecurityConstraint.addAuthRole("manager")加入授权角色, authConstraint的标志就变为true
Bootstrap1的main()中在Realm realm = new SimpleRealm(); context.setRealm(realm);
在SimpleRealm已经创建了数据并缓存在ArrayList users 属性中
private void createUserDatabase() {
    User user1 = new User("ken", "blackcomb");
    user1.addRole("manager");
    user1.addRole("programmer");
    User user2 = new User("cindy", "bamboo");
    user2.addRole("programmer");

    users.add(user1);
    users.add(user2);
  }
1.先在缓存中查找。
2.在BasicAuthenticator.invoke()中checkUserData方法
    protected SecurityConstraint = findConstraint(HttpRequest request) {
        SecurityConstraint constraints[] = context.findConstraints();
}
if ((constraint == null) /* &&//如果为null进入下一个阀门
     (!Constants.FORM_METHOD.equals(config.getAuthMethod())) */ ) {
            if (debug >= 1)
                log(" Not subject to any constraint");
            context.invokeNext(request, response);
            return;
        }
在BasicAuthenticator.invoke()中
if (!checkUserData(hrequest, hresponse, constraint)) {
            if (debug >= 1)
                log(" Failed checkUserData() test");
            // ASSERT: Authenticator already set the appropriate
            // HTTP status code, so we do not have to do anything special
            return;
        }
在checkUserData方法中进行userdataconstraint验证如果ok返回true 否则sendRedirect重定向
3.在BasicAuthenticator.invoke()中调用authenticate(hrequest, hresponse, config)方法
Bootstrap1的main()中constraint.addAuthRole("manager");
       if (constraint.getAuthConstraint()) {//返回true
            if (debug >= 1)
                log(" Calling authenticate()");
            if (!authenticate(hrequest, hresponse, config)) {
                if (debug >= 1)
                    log(" Failed authenticate() test");
                // ASSERT: Authenticator already set the appropriate
                // HTTP status code, so we do not have to do anything special
                return;
            }
        }
在authenticate(hrequest, hresponse, config)方法中通过context.getRealm().authenticate(username, password) 进行获取Principal.如果存在进行register缓存失败根据LoginConfig中设置的数据进行处理
4.在BasicAuthenticator.invoke()中accessControl方法
accessControl(hrequest, hresponse, constraint){
LoginConfig config = context.getLoginConfig()
Constants.FORM_METHOD.equals(config.getAuthMethod()
Principal principal =
            ((HttpServletRequest) request.getRequest()).getUserPrincipal();
hasRole(Principal principal, String role)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值