Servlet中的url-pattern配置
匹配方法只有三种,要么是路径匹配(以“/”字符开头,并以“/*”结尾),要么是扩展名匹配(以“*.”开头),要么是精确匹配,三种匹配方法不能进行组合,不要想当然使用通配符或正则规则。
如<url-pattern>/user/*.action</url-pattern>是非法的;
另外注意:<url-pattern>/aa/*/bb</url-pattern>是精确匹配,合法,这里的*不是通配的含义。
当servlet容器接收到浏览器发起的一个url请求后,容器会用url减去当前应用的上下文路径,以剩余的字符串作为servlet映射,假如url是http://localhost:8080/appDemo/index.html,其应用上下文是appDemo,容器会将http://localhost:8080/appDemo去掉,用剩下的/index.html部分拿来做servlet的映射匹配
"/*"和"/"含义并不相同
- “/*”属于路径匹配,并且可以匹配所有request,由于路径匹配的优先级仅次于精确匹配,所以“/*”会覆盖所有的扩展名匹配,很多404错误均由此引起,所以这是一种特别恶劣的匹配模式,一般只用于filter的url-pattern
- “/”是servlet中特殊的匹配模式,且该模式有且仅有一个实例,优先级最低,不会覆盖其他任何url-pattern,只是会替换servlet容器的内建default servlet ,该模式同样会匹配所有request。
在使用springmvc时,如果将dispatcherServlet配置为“/*”就会出现问题,此时所有请求都会经过dispatcherServlet(除了精确路径),如果请求的是一个jsp,我们并没有Controllor与之对应,这是dispatcherServlet就会将请求forword到defaultServlet,但defaultServlet是只能处理静态文件,所以经过defaultServlet处理的jsp只能以纯文本的形式返回给客户端,而不会进经过jsp引擎解析。
server.xml配置
1 <?xml version='1.0' encoding='utf-8'?> 2 <Server port="8007" shutdown="SHUTDOWN"> 3 <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> 4 5 <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> 6 <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --> 7 <Listener className="org.apache.catalina.core.JasperListener" /> 8 <!-- Prevent memory leaks due to use of particular java/javax APIs--> 9 <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> 10 <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> 11 <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> 12 13 <!-- Global JNDI resources 14 Documentation at /docs/jndi-resources-howto.html 15 --> 16 <GlobalNamingResources> 17 <!-- Editable user database that can also be used by 18 UserDatabaseRealm to authenticate users 19 --> 20 <Resource name="UserDatabase" auth="Container" 21 type="org.apache.catalina.UserDatabase" 22 description="User database that can be updated and saved" 23 factory="org.apache.catalina.users.MemoryUserDatabaseFactory" 24 pathname="conf/tomcat-users.xml" /> 25 </GlobalNamingResources> 26 27 <!-- A "Service" is a collection of one or more "Connectors" that share 28 a single "Container" Note: A "Service" is not itself a "Container", 29 so you may not define subcomponents such as "Valves" at this level. 30 Documentation at /docs/config/service.html 31 --> 32 <Service name="Catalina"> 33 <Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/> 34 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> 35 <Engine name="Catalina" defaultHost="localhost"> 36 <Realm className="org.apache.catalina.realm.LockOutRealm"> 37 <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> 38 </Realm> 39 40 <!-- 访问路径:www.zyong.com --> 41 <Host name="www.zyong.com" appBase="webapps" unpackWARs="true" autoDeploy="true"> 42 <Context path="/" docBase="D: omcatwebappszyong" allowLinking="true" /> 43 44 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" 45 prefix="localhost_access_log." suffix=".txt" 46 pattern="%h %l %u %t "%r" %s %b" /> 47 48 </Host> 49 50 <!-- 访问路径:www.zhangy.com --> 51 <Host name="www.test2.com.cn" appBase="webapps" unpackWARs="true" autoDeploy="true"> 52 <Context path="/" docBase="D: omcatwebappszhangy" allowLinking="true" /> 53 54 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" 55 prefix="localhost_access_log." suffix=".txt" 56 pattern="%h %l %u %t "%r" %s %b" /> 57 58 </Host> 59 60 61 </Engine> 62 </Service> 63 </Server>
tomcat组件
由上图可以看到tomcat由server(tomcat)、service、connector(一个service可以有多个connector,connector直接面对socket,将字节流反序列化成httpRequest对象)、engine(engine用于处理处理请求、响应,engine中又包括host、context、Servlet)等组成。
connector在指定端口监听,连接到来时就可以确定哪个connector服务,connector accept到socket后就会启动一个线程,从socket中读取字节流并反序列化为httpRequest对象;engine通过识别http请求中的host头部,将请求传给对应的host组件;host组件根据请求的上下文,将请求传给对应的context;context的下一级就是Servlet了,web.xml中配置的Servlet的url-pattern这时就起作用了,context根据请求的路径(去掉host和上下文部分)找到对应的Servlet;Servlet调用service进行服务。
keep-alive
1 <Connector executor="tomcatThreadPool" 2 port="8080" protocol="HTTP/1.1" 3 keepAliveTimeout = “30000” 4 connectionTimeout="30000" maxKeepAliveRequests="10" 5 redirectPort="8443" bufferSize="8192" sockedBuffer="65536" acceptCount="200"/>
注意:我们关闭writer或outputStream时,其实并没有关闭socket通路,而只是关闭一个缓冲区,这是连接仍然存在,只有socket.close时才真正的关闭了一端。
线程池
在Connector中可以配置executor,executor就是一个线程池(ThreadPoolExecutor),线程池有几个重要参数:coreSize、maxSize、idleTime、threadFactory、blockingQueue,tomcat中的executor也不例外,当线程数大于coreSize且有空闲线程时,这些空闲线程会阻塞在blockingQueue上,当到达idleTime且没有新请求(任务)到来时,这些空闲线程就会自动消亡(这些线程阻塞在blockingQueue的定时poll上,当timeout时自动唤醒,没有从blockingQueue中得到请求任务,worker线程就会退出循环结束运行)。
bio的线程模型比较简单,一个或多个acceptor线程用于serverSocket.accept,多个worker线程(executor)用于处理socket;
nio的线程模型要复杂一些,同样有一个或多个acceptor线程用于serverSocket.accept,一个或多个poller线程用于select,多个worker线程(executor)处理select后的事件。
参考:http://www.cnblogs.com/canger/p/6084846.html
http://tomcat.apache.org/tomcat-8.0-doc/config/http.html
https://stackoverflow.com/questions/896789/java-is-serversocket-accept-threadsafe