!必看 ?了解 %进阶
1.1) JSP和Servlet的区别
- 二者联系:
- JSP在本质上就是SERVLET。
- JSP会被Web容器转译为Servlet的“.java”源文件,编译为“.class”文件,然后加载容器之中,所以最后提供服务的还是Servlet实例(Instance)。
- 主要区别:
- Servlet在Java代码中通过HttpServletResponse对象动态输出HTML内容
- JSP在静态HTML内容中嵌入Java代码,Java代码被动态执行后生成HTML内容
- 各自的优缺点:
- Servlet能够很好地组织业务逻辑代码,但是在Java源文件中通过字符串拼接的方式生成动态HTML内容会导致代码维护困难、可读性差
- JSP虽然规避了Servlet在生成HTML内容方面的劣势,但是在HTML中混入大量、复杂的业务逻辑同样也是不可取的
- 解决方案:
- 使用MVC模式规避JSP与Servlet各自的短板,提高代码的可读性和可维护性;
- Servlet只负责业务逻辑而不会通过 out.append()动态生成HTML代码;
- JSP中也不会充斥着大量的业务代码。
1.2) Servlet的概念
- Servlet是什么?
Java Servlet 是运行在 Web 服务器或应用服务器上的程序。
- Servlet在架构中的位置:
Web 浏览器或其他 HTTP 客户端的请求
中间层(servlet)
HTTP 服务器上的数据库或应用程序
- Servlet作用:
- 读取客户端请求:
-- 显式数据:包括网页上的HTML 表单,applet 或自定义的HTTP 客户端程序的表单。
-- 隐式数据:包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
- 处理数据并生成结果,这个过程可能需要:
-- 访问数据库
-- 执行 RMI 或 CORBA 调用
-- 调用 Web 服务
-- 直接计算
- 发送数据到客户端(浏览器):
-- 显式文档:格式包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
-- 隐式响应:包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。
a) Jsp和Servlet有什么区别?
b) jsp与servlet有什么区别?
c) Servlet、Filter、Listener深入理解
d) Servlet 简介(w3cschool)
e) 《JSP&Servlet学习笔记(第2版)》作者林信良
2.1) Servlet 生命周期描述
Servlet 生命周期可被定义为从创建直到毁灭的整个过程
- Servlet 通过调用 init() 方法进行初始化
- Servlet 调用 service() 方法来处理客户端的请求
- Servlet 通过调用 destroy() 方法终止(结束)
- Servlet 最终由 JVM 的垃圾回收器进行垃圾回收
2.2) 一个典型的 Servlet 生命周期方案
- 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器
- Servlet 容器在调用 service() 方法之前加载 Servlet
- 然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的Servlet实例的 service() 方法
3.1) Session工作原理
- 一句话概述
每个HttpSession都有一个唯一的Session ID,
当浏览器访问应用程序时,会将Cookie中存放的Session ID一并发送给应用程序,
Web容器会根据Session ID找出对应的HttpSession对象,这样就能在不同请求中获取相同的数据。
- 为什么使用Session
Web应用程序的请求与响应基于Http,为无状态的通信协议,每次请求对服务器来说都是新请求。
- HttpSession对象:
当用户使用浏览器访问服务器的资源时,通过运行HttpServletRequest对象的 getSession()方法,Web容器就会获取已经存在的HttpSession实例或创建一个新HttpSession实例。
由于Web容器本身是执行于JVM中的一个Java程序,HttpSession是Web容器中的一个Java对象。
- Session ID:
每个HttpSession对象都有一个特殊的Session ID作为标识,可以通过执行HttpSession的 getId()方法取得这个Session ID。Session ID 默认使用Cookie存放在浏览器中。在Tomcat中,Cookie的名称是JSESSIONID(在PHP中为PHPSESSID)。
3.2) Session设置超时的方式
- 方式一:
在Servlet中执行HttpSession的 setMaxInactiveInterval()方法,参数单位是“秒”;
- 方式二:
<!-- 在程序中的web.xml里设置HttpSession默认失效时间,单位是“分钟” -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
- 方式三:
<!-- 在Tomcat的/conf/web.xml中session-config,单位也是分钟 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
- 注意:
默认关闭浏览器马上失效的是浏览器上的Cookie,不是HttpSession。
存在Cookie中的Session ID随着Cookie失效而丢失,
所以再次打开浏览器向服务器发送请求时,HttpSession尝试 getSession(),Web容器会产生新的HttpSession实例。
要让HttpSession立即失效必须调用 invalidate()方法,
否则HttpSession实例要等到失效时间过后才会被容器销毁回收。
a) Servlet中不可不知的Session技术
b) Java Web开发Session超时设置
c) 《JSP&Servlet学习笔记(第2版)》作者林信良
4.1) Filter应用场景
- 统一请求或响应的字符集
如将编码统一为UTF-8
- 替换特殊字符
如将请求参数中的一些HTML标签去掉
- 控制浏览器缓存页面中的静态资源
有些动态页面中引用了一些图片或css文件以修饰页面效果,
这些图片和css文件经常是不变化的,
所以为减轻服务器的压力,
可以使用filter控制浏览器缓存这些文件,
以提升服务器的性能。
- 使用Filter实现URL级别的权限认证
在实际开发中我们经常把一些执行敏感操作的servlet映射到一些特殊目录中,
并用filter把这些特殊目录保护起来,
限制只能拥有相应访问权限的用户才能访问这些目录下的资源。
从而在我们系统中实现一种URL级别的权限功能。
- 实现用户自动登陆
首先,在用户登陆成功后,
发送一个名称为user的cookie给客户端,
cookie的值为用户名和md5加密后的密码。
编写一个AutoLoginFilter,
这个filter检查用户是否带有名称为user的cookie,
如果有,则调用dao查询cookie的用户名和密码是否和数据库匹配,
匹配则向session中存入user对象(即用户登陆标记),
以实现程序完成自动登陆。
4.2) 更多细分过滤器
- 身份验证过滤器(Authentication Filters)。
- 数据压缩过滤器(Data compression Filters)。
- 加密过滤器(Encryption Filters)。
- 触发资源访问事件过滤器。
- 图像转换过滤器(Image Conversion Filters)。
- 日志记录和审核过滤器(Logging and Auditing Filters)。
- MIME-TYPE 链过滤器(MIME-TYPE Chain Filters)。
- 标记化过滤器(Tokenizing Filters)。
- XSL/T 过滤器(XSL/T Filters),转换 XML 内容。
4.3) 过滤器的使用
- 为什么使用过滤器:
类似性能评测、用户验证、字符替换、编码设置这类需求,
与应用程序的业务需求没有直接关系,
应该设计为独立的元件,可以随意插拔,
或者随意修改设置而无需修改业务代码。
- 过滤器概念:
过滤器是一个实现了 javax.servlet.Filter接口的Java类,
作用于浏览器和Servlet中间,过滤请求与响应。
- 过滤器的定义:
- Servlet/JSP要实现过滤器,必须实现Filter接口,并在web.xml中定义过滤器,让过滤器知道加载哪个过滤器类。
- Filter接口有三个要实现的方法, init()、 doFilter() 与 destroy()。
- 过滤器的执行过程:
- 当过滤器类被载入容器并实例化后,容器会运行 init()方法并传入FilterConfig对象作为参数。
- 当请求来到过滤器时,会调用 doFilter()方法, doFilter()上除了ServletRequest和ServletResponse之外,还有一个FilterChain参数;
- 如果调用了FilterChain的 doFilter()方法,就会运行下一个过滤器,如果没有下一个过滤器,就调用请求目标Servlet的 service()方法;
- 在到达 service()方法之后,流程会以堆栈顺序返回,所以在FilterChain的 doFilter()运行完毕后,就可以针对 service()方法做后续处理;
- 如果因为某个条件(如用户没有通过验证)而不调用FilterChain的 doFilter(),则请求就不会继续至目标Servlet,此时过滤器就起到了拦截请求的作用;
- Filter接口:
public interface Filter {
//用于完成Filter的初始化
//该方法由 Web 容器调用,指示一个过滤器被放入服务
public void init(FilterConfig filterConfig) throws ServletException;
//实现过滤功能
//该方法在每次一个请求/响应对因客户端在链的末端请求资源而通过链传递时由容器调用
public void doFilter ( ServletRequest request, ServletResponse response,
FilterChain chain ) throws IOException, ServletException;
//用于销毁Filter前,完成某些资源的回收
//该方法由 Web 容器调用,指示一个过滤器被取出服务。
public void destroy();
}
4.4) 过滤器的生命周期
web.xml 中声明的每个 filter 在每个虚拟机中仅有一个实例。
- (1) 加载和实例化
Web容器启动时,即会根据 web.xml中声明的 filter顺序依次实例化这些 filter。
- (2) 初始化
Web容器调用init(FilterConfig)来初始化过滤器。
容器在调用该方法时,向过滤器传递 FilterConfig对象,FilterConfig的用法和 ServletConfig类似。
利用 FilterConfig对象可以得到 ServletContext对象,以及在 web.xml 中配置的过滤器的初始化参数。
在这个方法中,可以抛出 ServletException 异常,通知容器该过滤器不能正常工作。
此时的 Web 容器启动失败,整个应用程序不能够被访问。
实例化和初始化的操作只会在容器启动时执行,而且只会执行一次。
- (3) doFilter
doFilter方法类似于Servlet接口的 service()方法。
当客户端请求目标资源的时候,容器会筛选出符合 filter-mapping中url-pattern的filter,
并按照声明filter-mapping的顺序依次调用这些 filter的doFilter方法。
在这个链式调用过程中,
可以调用 chain.doFilter(ServletRequest, ServletResponse)将请求传给下一个过滤器(或目标资源),
也可以直接向客户端返回响应信息,
或者利用 RequestDispatcher的forward和include方法,
以及 HttpServletResponse的sendRedirect方法将请求转向到其它资源。
需要注意的是,这个方法的请求和响应参数的类型是 ServletRequest和ServletResponse,
也就是说,过滤器的使用并不依赖于具体的协议。
- (4)销毁
Web容器调用 destroy()方法指示过滤器的生命周期结束。
在这个方法中,可以释放过滤器使用的资源。
4.5) 过滤器的运行原理
a) Servlet、Filter、Listener深入理解
b) Servlet 编写过滤器
c) 《JSP&Servlet学习笔记(第2版)》作者林信良
5.1) 概念:
- 5.1.1) 静态include:
- <%@include file=”xxx.jsp”%> 是JSP指示(或者指令)元素的一种,用于告知容器将其他JSP页面包括进来进行转译。
- 使用include来包括其他页面内容时,会在转译时就决定转译后的Servlet内容,所以说是一种静态的包括方式。
- 5.1.2) 动态include:
- <jsp:include page="xxx.jsp" /> 是JSP行为(或者动作)元素的一种,使用动态include将页面包含进来,当前页面会生成一个Servlet类,被include的页面也会独立生成一个Servlet类。
- 当前页面转译而成的Servlet中,会取得RequestDispatcher对象,并执行 include()方法,也就是请求时将动态include的页面转交给另一个Servlet,而后再回到自己的Servlet。
5.2) 区别
- 5.2.1) 执行时间不同:
- 静态include是在转译阶段执行
- 动态include在请求处理阶段执行.
- 5.2.2) 引入内容不同:
- 静态include引入静态文本(html,jsp),在JSP页面被转化成servlet之前和它融和到一起
- 动态include引入执行页面或servlet所生成的应答文本.
- 5.2.3) 属性区别:
- 静态include通过file属性指定被包含的文件,并且file属性不支持任何表达式;
- 动态include通过page属性指定被包含的文件,且page属性支持JSP表达式;
- 5.2.4) 编译区别:
- 静态include时,被包含的文件内容会原封不动的插入到包含页中,然后JSP编译器再将合成后的文件最终编译成一个Java文件,因此被导入页面甚至不需要是一个完整的页面;
- 动态inlcude时,当该标识被执行时,程序会将请求转发(不是请求重定向)到被包含的页面,并将执行结果输出到浏览器中,然后返回包含页继续执行后面的代码。因为服务器执行的是多个文件,所以JSP编译器会分别对这些文件进行编译;
- 5.2.5) 编译指令区别:
- 静态inlcude时被导入页面的编译指令会起作用;
- 而动态include时被导入页面的编译指令则失去作用,只是插入被导入页面的body内容。
- 5.2.6) 变量作用域区别:
- 静态include时,由于被包含的文件最终会生成一个文件,所以在被包含、包含文件中不能有重名的变量或方法;
- 动态include时,由于每个文件是单独编译的,所以在被包含文件和包含文件中重名的变量和方法是不相冲突的。
- 5.2.7) 传参区别:
- 静态include会导致两个jsp合并成为同一个java文件,所以不存在传参问题
- 动态include对被包含的jsp文件进行了一次独立的访问,通过在<jsp:include>标签中嵌入子标签<jsp:param>的形式传递参数
<jsp:include page="xxx.jsp">
<jsp:param name="参数名" value="参数值" />
</jsp:include>
在被包含的JSP页面中通request.getParameter("参数名")获取参数值
<p>获取的参数值在此显示:<%=request.getParameter("参数名")%></p>
a) JSP include
b) JSP之静态include指令、动态Include指令
c) JSP中动态INCLUDE与静态INCLUDE的区别
d) 《JSP&Servlet学习笔记(第2版)》作者林信良
6.1) 常用web.xml配置场景
- 6.1.1) 指定欢迎页面:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index1.jsp</welcome-file>
</welcome-file-list>
<!-- 上面的例子指定了2个欢迎页面,显示时按顺序从第一个找起 -->
<!-- 如果第一个存在,就显示第一个,后面的不起作用 -->
<!-- 如果第一个不存在,就找第二个,以此类推 -->
- 6.1.2) 命名与定制URL
<!-- 我们可以为Servlet和JSP文件命名并定制URL-->
<!-- 其中定制URL是依赖一命名的,命名必须在定制URL前-->
<!-- (1) 为Servlet命名 -->
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>net.test.TestServlet</servlet-class>
</servlet>
<!-- (2) 为Servlet定制URL -->
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
- 6.1.3) 定制初始化参数:
<!-- 可以定制servlet、JSP、Context的初始化参数 -->
<!-- 然后可以再servlet、JSP、Context中获取这些参数值 -->
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>net.test.TestServlet</servlet-class>
<init-param>
<param-name>userName</param-name>
<param-value>Tommy</param-value>
</init-param>
<init-param>
<param-name>E-mail</param-name>
<param-value>Tommy@163.com</param-value>
</init-param>
</servlet>
<!-- 经过上面的配置,在servlet中能够调用getServletConfig().getInitParameter("param1")获得参数名对应的值-->
- 6.1.4) 指定错误处理页面
<!-- 可以通过“异常类型”或“错误码”来指定错误处理页面 -->
<error-page>
<error-code>404</error-code>
<location>/error404.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception<exception-type>
<location>/exception.jsp<location>
</error-page>
- 6.1.5) 设置过滤器:
<!-- 比如设置一个编码过滤器,过滤所有资源 -->
<filter>
<filter-name>XXXCharaSetFilter</filter-name>
<filter-class>net.test.CharSetFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XXXCharaSetFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 6.1.6) 设置监听器:
<listener>
<listener-class>net.test.XXXLisenet</listener-class>
</listener>
- 6.1.7) 设置会话(Session)过期时间
<!-- 时间以分钟为单位,假如设置60分钟超时 -->
<session-config>
<session-timeout>60</session-timeout>
</session-config>
6.2) web.xml标签及说明
<web-app>
<!--定义了WEB应用的名字 -->
<display-name></display-name>
<!--声明WEB应用的描述信息 -->
<description></description>
<!--context-param元素声明应用范围内的初始化参数 -->
<context-param></context-param>
<!--过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联 -->
<filter></filter>
<!--一旦命名了一个过滤器,就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联 -->
<filter-mapping></filter-mapping>
<!--servlet API的版本2.3增加了对事件监听程序的支持,事件监听程序在建立、修改和删除会话或servlet环境时得到通知。 Listener元素指出事件监听程序类 -->
<listener></listener>
<!--在向servlet或JSP页面制定初始化参数或定制URL时,必须首先命名servlet或JSP页面。 Servlet元素就是用来完成此项任务的 -->
<servlet></servlet>
<!--服务器一般为servlet提供一个缺省的URL:http://host/webAppPrefix/servlet/ServletName。
但是,常常会更改这个URL,以便servlet可以访问初始化参数或更容易地处理相对URL。 在更改缺省URL时,使用servlet-mapping元素 -->
<servlet-mapping></servlet-mapping>
<!--如果某个会话在一定时间内未被访问,服务器可以抛弃它以节省内存。可通过使用HttpSession的 setMaxInactiveInterval方法明确设置单个会话对象的超时值,或者可利用session-config元素制定缺省超时值 -->
<session-config></session-config>
<!--如果Web应用具有想到特殊的文件,希望能保证给他们分配特定的MIME类型,则mime-mapping元素提供这种保证 -->
<mime-mapping></mime-mapping>
<!--指示服务器在收到引用一个目录名而不是文件名的URL时,使用哪个文件 -->
<welcome-file-list></welcome-file-list>
<!--在返回特定HTTP状态代码时,或者特定类型的异常被抛出时,能够制定将要显示的页面 -->
<error-page></error-page>
<!--对标记库描述符文件(Tag Libraryu Descriptor file)指定别名。此功能使你能够更改TLD文件的位置, 而不用编辑使用这些文件的JSP页面 -->
<taglib></taglib>
<!--声明与资源相关的一个管理对象 -->
<resource-env-ref></resource-env-ref>
<!--声明一个资源工厂使用的外部资源 -->
<resource-ref></resource-ref>
<!--制定应该保护的URL。它与login-config元素联合使用 -->
<security-constraint></security-constraint>
<!--指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用 -->
<login-config></login-config>
<!--给出安全角色的一个列表,这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。 分别地声明角色可使高级IDE处理安全信息更为容易 -->
<security-role></security-role>
<!--声明Web应用的环境项 -->
<env-entry></env-entry>
<!--声明一个EJB的主目录的引用 -->
<ejb-ref></ejb-ref>
<!--声明一个EJB的本地主目录的应用 -->
<ejb-local-ref></ejb-local-ref>
</web-app>
6.3) 更多web.xml配置
- 6.3.1) Web应用图标:
<!-- 指出IDE和GUI工具用来表示Web应用的大图标和小图标 -->
<icon>
<small-icon>/images/app_small.gif</small-icon>
<large-icon>/images/app_large.gif</large-icon>
</icon>
- 6.3.2) Web 应用名称:
<!-- 提供GUI工具可能会用来标记这个特定Web应用的一个名称 -->
<display-name>Tomcat Example</display-name>
- 6.3.3) Web 应用描述:
<!--给出与此相关的说明性文本 -->
<disciption>Tomcat Example servlets and JSP pages.</disciption>
- 6.3.4) 上下文参数:
<!--声明应用范围内的初始化参数 -->
<context-param>
<param-name>ContextParameter</para-name>
<param-value>test</param-value>
<description>It is a test parameter.</description>
</context-param>
<!-- 在servlet里面可以通过getServletContext().getInitParameter("context/param")得到 -->
- 6.3.5) 过滤器配置:
<!--将一个名字与一个实现javaxs.servlet.Filter接口的类相关联 -->
<filter>
<filter-name>setCharacterEncoding</filter-name>
<filter-class>com.myTest.setCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 6.3.6) 监听器配置
<listener>
<listerner-class>listener.SessionListener</listener-class>
</listener>
- 6.3.7) Servlet配置
<!--基本配置 -->
<servlet>
<servlet-name>snoop</servlet-name>
<servlet-class>SnoopServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>snoop</servlet-name>
<url-pattern>/snoop</url-pattern>
</servlet-mapping>
<!-- 高级配置-->
<servlet>
<servlet-name>snoop</servlet-name>
<servlet-class>SnoopServlet</servlet-class>
<init-param>
<param-name>foo</param-name>
<param-value>bar</param-value>
</init-param>
<run-as>
<description>Security role for anonymous access</description>
<role-name>tomcat</role-name>
</run-as>
</servlet>
<servlet-mapping>
<servlet-name>snoop</servlet-name>
<url-pattern>/snoop</url-pattern>
</servlet-mapping>
<!--元素说明 -->
<servlet></servlet> <!--用来声明一个servlet的数据,主要有以下子元素-->
<servlet-name></servlet-name> <!--指定servlet的名称 -->
<servlet-class></servlet-class> <!--指定servlet的类名称 -->
<jsp-file></jsp-file> <!--指定web站台中的某个JSP网页的完整路径-->
<init-param></init-param> <!--用来定义参数,可有多个init-param。在servlet类中通过getInitParamenter(String name)方法访问初始化参数 -->
<load-on-startup></load-on-startup> <!--指定当Web应用启动时,装载Servlet的次序。 当值为正数或零时:Servlet容器先加载数值小的servlet,再依次加载其他数值大的servlet. 当值为负或未定义:Servlet容器将在Web客户首次访问这个servlet时加载它 -->
<servlet-mapping></servlet-mapping> <!--用来定义servlet所对应的URL,包含两个子元素 -->
<servlet-name></servlet-name> <!--指定servlet的名称 -->
<url-pattern></url-pattern> <!--指定servlet所对应的URL -->
- 6.3.8) 会话超时配置(单位为分钟)
<session-config>
<session-timeout>120</session-timeout>
</session-config>
- 6.3.9) MIME类型配置
<mime-mapping>
<extension>htm</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
- 6.3.10) 指定欢迎文件页配置
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
- 6.3.11) 配置错误页面
<!-- 1. 通过错误码来配置error-page -->
<error-page>
<error-code>404</error-code>
<location>/NotFound.jsp</location>
</error-page>
<!-- 上面配置了当系统发生404错误时,跳转到错误处理页面NotFound.jsp -->
<!-- 2. 通过异常的类型配置error-page -->
<error-page>
<exception-type>java.lang.NullException</exception-type>
<location>/error.jsp</location>
</error-page>
<!--上面配置了当系统发生java.lang.NullException(即空指针异常)时,跳转到错误处理页面error.jsp -->
- 6.3.12) TLD配置
<taglib>
<taglib-uri>http://jakarta.apache.org/tomcat/debug-taglib</taglib-uri>
<taglib-location>/WEB-INF/jsp/debug-taglib.tld</taglib-location>
</taglib>
<!-- 如果IDE一直在报错,应该把<taglib> 放到 <jsp-config>中-->
<jsp-config>
<taglib>
<taglib-uri>http://jakarta.apache.org/tomcat/debug-taglib</taglib-uri>
<taglib-location>/WEB-INF/pager-taglib.tld</taglib-location>
</taglib>
</jsp-config>
- 6.3.13) 资源管理对象配置
<resource-env-ref>
<resource-env-ref-name>jms/StockQueue</resource-env-ref-name>
</resource-env-ref>
- 6.3.14) 资源工厂配置
<resource-ref>
<res-ref-name>mail/Session</res-ref-name>
<res-type>javax.mail.Session</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<!--配置数据库连接池就可在此配置 -->
<resource-ref>
<description>JNDI JDBC DataSource of shop</description>
<res-ref-name>jdbc/sample_db</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
- 6.3.15) 安全限制配置
<security-constraint>
<display-name>Example Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/jsp/security/protected/*</url-pattern>
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>tomcat</role-name>
<role-name>role1</role-name>
</auth-constraint>
</security-constraint>
- 6.3.16) 登陆验证配置
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Example-Based Authentiation Area</realm-name>
<form-login-config>
<form-login-page>/jsp/security/protected/login.jsp</form-login-page>
<form-error-page>/jsp/security/protected/error.jsp</form-error-page>
</form-login-config>
</login-config>
- 6.3.17) 安全角色
<!-- security-role元素给出安全角色的一个列表 -->
<!-- 这些角色将出现在servlet元素内security-role-ref元素的role-name子元素中-->
<!-- 分别地声明角色可使高级IDE处理安全信息更为容易 -->
<security-role>
<role-name>tomcat</role-name>
</security-role>
- 6.3.18) Web环境参数
<!-- env-entry元素声明Web应用的环境项 -->
<env-entry>
<env-entry-name>minExemptions</env-entry-name>
<env-entry-value>1</env-entry-value>
<env-entry-type>java.lang.Integer</env-entry-type>
</env-entry>
- 6.3.19) EJB 声明
<ejb-ref>
<description>Example EJB reference</decription>
<ejb-ref-name>ejb/Account</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.mycompany.mypackage.AccountHome</home>
<remote>com.mycompany.mypackage.Account</remote>
</ejb-ref>
- 6.3.20) 本地EJB声明
<ejb-local-ref>
<description>Example Loacal EJB reference</decription>
<ejb-ref-name>ejb/ProcessOrder</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>com.mycompany.mypackage.ProcessOrderHome</local-home>
<local>com.mycompany.mypackage.ProcessOrder</local>
</ejb-local-ref>
- 6.3.21) 配置DWR
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
- 6.3.22) 配置Struts
<display-name>Struts Blank Application</display-name>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>application</param-name>
<param-value>ApplicationResources</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- Struts Tag Library Descriptors -->
<taglib>
<taglib-uri>struts-bean</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>struts-html</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>struts-nested</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-nested.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>struts-logic</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-logic.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>struts-tiles</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-tiles.tld</taglib-location>
</taglib>
- 6.3.23) 配置spring
<!-- 指定spring配置文件位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<!--加载多个spring配置文件 -->
<param-value>
/WEB-INF/applicationContext.xml, /WEB-INF/action-servlet.xml
</param-value>
</context-param>
<!-- 定义SPRING监听器,加载spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
a) Java Web的web.xml文件作用及基本配置
b) 史上最全web.xml配置文件元素详解
Servlet规范中定义,默认情况下(Servlet不是在分布式的环境中部署),
Servlet容器对声明的每一个Servlet,只创建一个实例。
如果有多个客户端请求同时访问这个Servlet,Servlet容器如何处理多个请求呢?
答案是采用多线程,Servlet容器维护一个线程池来服务请求。
当容器接收到一个访问Servlet的请求,调度者线程从线程池中选取一个工作线程,
将请求传递给该线程,然后由这个线程执行Servlet的 service()方法。
7.2) 线程安全的Servlet
- 7.2.1) 变量的线程安全
Servlet是单实例多线程模型,多个线程共享一个Servlet实例,因此对于实例变量的访问是非线程安全的。
建议:在Servlet中尽可能的使用局部变量,应该只使用只读的实例变量和静态变量。
如果非得使用共享的实例变量或静态变量,在修改共享变量时应该注意线程同步。
- 7.2.2) 属性的线程安全
在Servlet中,可以访问保存在ServletContext、HttpSession和ServletRequest对象中的属性。
那么这三种不同范围的对象,属性访问是否是线程安全的呢?
- ServletContext:
该对象被Web应用程序的所有Servlet共享,多线程环境下肯定是非线程安全的。
- HttpSession:
HttpSession对象只能在同属于一个Session的请求线程中共享。
对于同一个Session,我们可能会认为在同一时刻只有一个用户请求。
因此,Session对象的属性访问是线程安全的。
但是,如果用户打开多个同属于一个进程的浏览器窗口,
在这些窗口中的访问请求同属于一个Session,对于多个线程的并发修改显然不是线程安全的。
- ServletRequest:
因为Servlet容器对它所接收到的每一个请求,
都创建一个新的ServletRequest对象,
所以ServletRequest对象只在一个线程中被访问,
因此对ServletRequest的属性访问是线程安全的。
但是,如果在Servlet中创建了自己的线程,
那么对ServletRequest的属性访问的线程安全性就得自己去保证。
此外,如果将当前请求的Servlet通过HttpSession或者ServletContext共享,
当然也是非线程安全的。
a) Servlet、Filter、Listener深入理解
Contributes: bigablecat
Reviewers : Hollis, Kevin Lee