相关学习资料

  1. http://my.oschina.net/chape/blog/170247
  2. http://docs.oracle.com/cd/E13222_01/wls/docs81/webapp/web_xml.html
  3. http://blog.csdn.net/liaoxiaohua1981/article/details/6761053
  4. http://computer.c.blog.163.com/blog/static/102524482012314537670/
  5. http://www.blogjava.net/w2gavin/articles/358641.html
  6. http://www.douban.com/note/310522851/
  7. http://mianhuaman.iteye.com/blog/1105522
  8. http://blog.csdn.net/li_jinjian2005/article/details/2915462
  9. http://210.44.193.6/JSP/07.htm
  10. http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/

目录

  1. . J2EE WEB应用文件目录结构
  2. . web.xml基础语法
  3. . JSP基础语法
  4. . Servlet基础语法

1. J2EE WEB应用文件目录结构

Java Web应用由一组静态HTML页、Servlet、JSP和其他相关的class组成,它们一起构成一个大的工程项目。每种组件在Web应用中都有固定的存放目录。Web应用的配置信息存放在web.xml文件中。在发布某些组件(如Servlet)时,必须在web.xml文件中添加相应的配置信息
Java Web应用程序必须使用规范的目录结构

  1. . 应用程序根目录,可以取任意的名字,所有的HTMLJSP文件都放在这个目录下
  2. 1.1 WEB-INF目录: 必须目录
  3. 1.1. web.xml: Web应用部署描述文件,必须文件
  4. 1.1. classes目录:
  5. ) 用于存放单个*.classes字节码文件,Servlet类文件也存放在这个目录下
  6. 1.1. lib目录:
  7. ) 存放第三方类库文件,即打包后的JAR文件
  8. 1.1. TLD文件: 标签库描述文件
  9. 1.2 其他静态文件:
  10. 1.2. HTML
  11. 1.2. CSS
  12. 1.2. JavaScript
  13. 1.2. 图片等
  14. 1.3 *.jsp: 存放任意多个JSP页面

2. web.xml基础语法

位于每个WEB应用的的WEB-INF路径下的web.xml文件被称为配置描述符,这个web.xml文件对于Java Web应用十分重要,总体来说,web.xml主要负责以下内容:

  1. . JSP环境参数初始化
  2. . 配置和管理Servlet
  3. . 配置和管理Listener
  4. . 配置和管理Filter
  5. . 配置和管理JNDI
  6. . Session配置
  7. . MIME TYPE配置
  8. . 错误处理
  9. . 配置标签库
  10. . 配置JSP属性
  11. . 配置和管理JAAS授权认证
  12. . 配置和管理资源引用
  13. . WEB应用默认首页(welcome文件)的设置

下面我尽量列出了一个完整的web.xml的结构,我使用了/**/注释符来说明某个项目的说明,要明白的是,在真实的web.xml中不允许使用/**/注释符的,只是我觉得直接在web.xml中插入解释说明能更好的说明问题

  1. /*
  2. <?xml version="1.0" encoding="GBK"?>是一个基本的XML文件的框架,不管是什么配置文件,只要是基于XML的,它的基本结构都是这样
  3. */
  4. <?xml version="1.0" encoding="GBK"?>
  5. /*
  6. web.xml文件的根元素是<web-app.../>元素,整个web.xml只有这个根元素,每个web.xml必须以这个<web-app>根元素作为开头,在Servlet 3.0规范中,该元素新增了
    metadata-complete属性,当该属性值为true时,该web应用"不会"加载Annotation配置的WEB组件(如Servlet、Filter、Listener等),反之则加载
  7. */
  8. <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  9. /*
  10. 1. icon信息: 用来指定web站点中小图标和大图标的路径
  11. 1) small-icon: 大小为16 X 16 pixel,但是图象文件必须为GIF或JPEG格式,扩展名必须为:.gif或
  12. .jpg.
  13. 2) large-icon: 大小为32 X 32 pixel,但是图象文件必须为GIF或JPEG的格式,扩展名必须为; gif
  14. 或jpg.
  15. */
  16. <small-icon>/路径/smallicon.gif</small-icon>
  17. <large-icon>/路径/largeicon-jpg</large-icon>
  18.  
  19. /*
  20. 2. 描述信息
  21. display-name: 定义站点的名称
  22. description: 对站点的描述
  23. */
  24. <display-name>站点名称</display-name>
  25. <description>站点描述</discription>
  26.  
  27. /*
  28. 3. distributable
  29. distributable元素为空标签,它的存在与否可以指定站台是否可分布式处理.如果web.xml中出现这个元素,则代表站台在开发时已经被设计为能在多个JSP Container之间分散执行
  30. */
  31. <distributable/>
  32.  
  33. /*
  34. 4. JSP环境参数: context-param
  35. context-param元素用来设定web站台的环境参数(context),它包含两个子元素:
  36. 1) param-name: 参数名称
  37. 2) param-value: 值
  38. 此所设定的参数,在JSP网页中可以使用下列方法来取得:
  39. ${initParam.param_name}
  40. 若在Servlet可以使用下列方法来获得:
  41. String param_name=getServletContext().getInitParamter("param_name");
  42. */
  43. <context-param>
  44. <param-name>param_name</param-name>
  45. <param-value>param_value</param-value>
  46. </context-param>
  47.  
  48. /*
  49. 5. filter过滤器、filter-mapping
  50. 用于指定WEB容器的过滤器,在请求和响应对象在Servlet处理之前和之后,可以通过此过滤器对这两个对象进行处理
  51. filter-class 中指定的过滤器类须继承 javax.servlet.Filter具有须有以下三种方法
  52. init(FilterConfig filterConfig):初始化;一般情况下时读取配置文件中的init-param参数值 如 filterConfig.getInitParameter("encoding")
  53. doFilter(...):用于对request,response进行处理,并能过chain.doFilter(...) 交过下一个控制器
  54. destroy():资源销毁
  55. filter-mapping则指示需要进行过滤器处理的URL访问模式,可以理解为当我们的URL匹配到指定的模式后,则对这个请求执行指定的"过滤处理流程"(可以把它理解为一种路由机制)
  56. */
  57. <filter>
  58. <small-icon>/路径/smallicon.gif</small-icon>
  59. <large-icon>/路径/largeicon-jpg</large-icon>
  60. <filter-name>encodingfilter</filter-name>
  61. <display-name>站点名称</display-name>
  62. <description>站点描述</discription>
  63. <filter-class>com.my.app.EncodingFilter</filter-class>
  64. <init-param>
  65. <param-name>encoding</param-name>
  66. <param-value>UTF-</param-value>
  67. </init-param>
  68. </filter>
  69. <filter-mapping>
  70. <filter-name>encodingfilter</filter-name>
  71. <url-pattern>/*</url-pattern>
  72. </filter-mapping>
  73.  
  74. /*
  75. 6. servlet、servlet-mapping
  76. 和filter过滤器类似,servlet也是用来配置映射处理机制的
  77. 和filter-mapping的作用类似,servlet-mapping用来定义servlet所对应URL.
  78. */
  79. <servlet>
  80. <small-icon>/路径/smallicon.gif</small-icon>
  81. <large-icon>/路径/largeicon-jpg</large-icon>
  82. <servlet-name>MyServletName</servlet-name>
  83. <display-name>站点名称</display-name>
  84. <description>站点描述</discription>
  85. /*
  86. servlet-class、jsp-file有且只能出现一个
  87. */
  88. <servlet-class>com.Little.MyServlet</servlet-class>
  89. <jsp-file>/path/index.jsp</jsp-file>
  90. <init-param>
  91. <param-name>name1</param-name>
  92. <param-value>value1</param-value>
  93. </init-param>
  94. /*
  95. 指定当Web应用启动时,装载Servlet的次序
  96. 1) 当值为正数或零时: 容器在应用启动时就加载这个servlet,Servlet容器先加载数值小的servlet,再依次加载其他数值大的servlet
  97. 2) 当值为负或未定义: 容器在该servlet被选择时才加载,即Servlet容器将在Web客户首次访问这个servlet时加载它
  98. */
  99. <load-on-startup></load-on-startup>
  100. /*
  101. 设定运行时角色,可以使当前Servlet以一个特定的角色运行,有利于安全权限控制
  102. */
  103. <run-as>
  104. <description>Security role for anonymous access</description>
  105. <role-name>tomcat</role-name>
  106. </run-as>
  107. /*
  108. security-role-ref子元素提供出现在服务器专用口令文件中的安全角色名的一个别名。例如,假如编写了一个调用 request.isUserInRole("boss")的servlet,
    但后来该servlet被用在了一个其口令文件调用角色manager而不 是boss的服务器中。下面的程序段使该servlet能够使用这两个名称中的任何一个
  109. */
  110. <security-role-ref>
  111. <role-name>boss</role-name> <!-- New alias -->
  112. <role-link>manager</role-link> <!-- Real name -->
  113. </security-role-ref>
  114. </servlet>
  115.  
  116. <servlet-mapping>
  117. <servlet-name>LoginChecker</servlet-name>
  118. <url-pattern>/LoginChecker</url-pattern>
  119. <servlet-name>MyServletName</<servlet-name>
  120. </servlet-mapping>
  121.  
  122. /*
  123. 7. security-role(虚拟安全用户)
  124. 给出安全角色的一个列表,这些角色将出现在servlet元素内的security-role-ref元素的role-name元素中。分别声明角色可使高级IDE处理安全信息更为容易。
  125. */
  126. <security-role>
  127. <description>安全账户描述</discription>
  128. <role-name>admin</role-name>
  129. </security-role>
  130.  
  131. /*
  132. 8. listener
  133. 监听器也叫Listener,是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,Servlet本身在一些特定的关键处理流程节点上增加Hook
    回调机制,使得我们可以在这些节点位置配置监听器
  134. 常见的监听器如下:
  135. Listener接口
  136. 1) ServletContextListener: ServletContextEvent
  137. 2) ServletContextAttributeListener: ServletContextAttributeEvent
  138. 3) HttpSessionListener: HttpSessionEvent
  139. 4) HttpSessionActivationListener: HttpSessionAttributeListener
  140. 5) HttpSessionBindingEvent: HttpSessionBindingListener
  141. 6) ServletRequestListener: ServletRequestEvent
  142. 7) ServletRequestAttributeListener: ServletRequestAttributeEvent
  143. */
  144. <listener>
  145. <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  146. </listener>
  147.  
  148. /*
  149. 9. session配置
  150. session-config包含一个子元素session-timeout.定义web站台中的session参数,定义这个web站台所有session的有效期限.单位为分钟
  151. */
  152. <session-config>
  153. <session-timeout></session-timeout>
  154. </session-config>
  155.  
  156. /*
  157. 10. mime-mapping
  158. mime-mapping包含两个子元素extension和mime-type.定义某一个扩展名和某一MIME Type做对映,和apache中的文件扩展处理器原理类似,对指定的扩展名指定相应的处理程序
  159. */
  160. <mime-mapping>
  161. <extension>doc</extension>
  162. <mime-type>application/vnd.ms-word</mime-type>
  163. </mime-mapping>
  164. <mime-mapping>
  165. <extension>xls</extension>
  166. <mime-type>application/vnd.ms-excel</mime-type>
  167. </mime-mapping>
  168.  
  169. /*
  170. 11. welcome-file-list
  171. welcome-file-list包含一个子元素welcome-file.用来定义首页列单,即当客户端的请求没有指定具体的页面时,服务区器默认指定的首页脚本
  172. */
  173. <welcome-file-list>
  174. <welcome-file>index.jsp</welcome-file>
  175. <welcome-file>index.htm</welcome-file>
  176. </welcome-file-list>
  177.  
  178. /*
  179. 12. error-page
  180. 错误处理机制,error-page元素包含三个子元素error-code,exception-type和location.将错误代码(Error Code)或异常(Exception)的种类对应到web站点资源路径。
    简单来说就是返回特定HTTP状态代码或者特定类型的异常被抛出时,制定响应将要显示的页面。
  181. */
  182. <error-page>
  183. <error-code></error-code>
  184. <exception-type>java.lang.Exception</exception-type>
  185. <location>/error404.jsp</location>
  186. </error-page>
  187. <error-page>
  188. <exception-type>java.lang.Exception</exception-type>
  189. <exception-type>java.lang.NullException</exception-type>
  190. <location>/except.jsp</location>
  191. </error-page>
  192.  
  193. /*
  194. 13. jsp-config
  195. JSP相关配置
  196. */
  197. <jsp-config>
  198. <taglib>
  199. /*
  200. taglib-uri定义TLD文件的URI,JSP网页的taglib指令可以经由这个URI存取到TLD文件
  201. */
  202. <taglib-uri>Taglib</taglib-uri>
  203. /*
  204. taglib-location定义TLD文件对应Web站台的存放位置
  205. */
  206. <taglib-location>/WEB-INF/tlds/MyTaglib.tld</taglib-location>
  207. </taglib>
  208. <jsp-property-group>
  209. <description>
  210. Special property group for JSP Configuration JSP example.
  211. </description>
  212. <display-name>JSPConfiguration</display-name>
  213. /*
  214. 设定值所影响的范围,如:/CH2 或者/*.jsp
  215. */
  216. <uri-pattern>/*</uri-pattern>
  217. /*
  218. 若为true,表示不支持EL语法
  219. */
  220. <el-ignored>true</el-ignored>
  221. /*
  222. 设定JSP网页的编码
  223. */
  224. <page-encoding>GB2312</page-encoding>
  225. /*
  226. 若为true表示不支持<%scription%>语法.
  227. */
  228. <scripting-inivalid>true</scripting-inivalid>
  229. /*
  230. 设置JSP网页的结尾,扩展名为.jspf
  231. */
  232. <include-coda>.jspf</include-coda>
  233. /*
  234. 设置JSP网页的抬头,扩展名为.jspf
  235. */
  236. <include-prelude>.jspf</include-prelude>
  237. </jsp-property-group>
  238. </jsp-config>
  239.  
  240. /*
  241. 14. resource-ref、resource-env-ref
  242. resource-ref声明资源工厂使用的外部资源
  243. resource-env-ref声明与资源相关的管理对象
  244. */
  245. <resource-ref>
  246. <description>JNDI JDBC DataSource of JSPBook</description> <!-- 资源说明 -->
  247. <res-ref-name>jdbc/sample_db</res-ref-name> <!-- 资源名称 -->
  248. <res-type>javax.sql.DataSoruce</res-type> <!-- 资源种类 -->
  249. <res-auth>Container</res-auth> <!-- 资源由ApplicationContainer来许可 -->
  250. <res-sharing-scope>Shareable|Unshareable</res-sharing-scope> <!-- 资源是否可以共享.默认值为 Shareable -->
  251. </resource-ref>
  252.  
  253. <resource-env-ref>
  254. <resource-env-ref-name>jms/StockQueue</resource-env-ref-name>
  255. </resource-env-ref>
  256.  
  257. /*
  258. 15. EJB配置
  259. ejb-ref用于声明一个EJB的主目录的引用
  260. 用于声明一个EJB的本地主目录的应用。
  261. */
  262. <ejb-ref>
  263. <description>Example EJB reference</decription>
  264. <ejb-ref-name>ejb/Account</ejb-ref-name>
  265. <ejb-ref-type>Entity</ejb-ref-type>
  266. <home>com.mycompany.mypackage.AccountHome</home>
  267. <remote>com.mycompany.mypackage.Account</remote>
  268. </ejb-ref>
  269.  
  270. <ejb-local-ref>
  271. <description>Example Loacal EJB reference</decription>
  272. <ejb-ref-name>ejb/ProcessOrder</ejb-ref-name>
  273. <ejb-ref-type>Session</ejb-ref-type>
  274. <local-home>com.mycompany.mypackage.ProcessOrderHome</local-home>
  275. <local>com.mycompany.mypackage.ProcessOrder</local>
  276. </ejb-local-ref>
  277.  
  278. /*
  279. 16. WEB应用环境参数配置
  280. */
  281. <env-entry>
  282. <description>环境参数说明</description>
  283. <env-entry-name>minExemptions</env-entry-name>
  284. <env-entry-value></env-entry-value>
  285. <env-entry-type>java.lang.Integer</env-entry-type>
  286. </env-entry>
  287.  
  288. /*
  289. 17. 安全配置、资源限制访问配置
  290. 在Web应用程序的web.xml中创建security-constraint、login-config和security-role元素
  291. */
  292. /*
  293. 配置对指定资源、指定角色的访问权限
  294. */
  295. <security-constraint>
  296. <web-resource-collection>
  297. <web-resource-name>HelloServlet</web-resource-name>
  298. <url-pattern>/HelloServlet</url-pattern>
  299. <http-method>GET</http-method>
  300. <http-method>POST</http-method>
  301. </web-resource-collection>
  302. <auth-constraint>
  303. <description>This applies only to the "tomcat" security role</description>
  304. <role-name>admin</role-name>
  305. </auth-constraint>
  306. <user-data-constraint>
  307. <transport-guarantee>NONE</transport-guarantee>
  308. </user-data-constraint>
  309. </security-constraint>
  310.  
  311. /*
  312. auth-method的方法有:
  313. 1) BASIC
  314. BASIC是一种常见的Web认证方式,浏览器给用户提示一个对话框,要求输入用户名和密码,随后Tomcat将给出的用户名和密码与tomcat-users.xml中的用户名和密码进行比较,
    然后使用前面的security-constraint配置来确定用户是否可访问受保护的servlet
  315. 2) FORM
  316. 3) CLIENT-CERT
  317. 4) DIGEST
  318. */
  319. <login-config>
  320. <realm-name>在HTTP验证返回包中的显示名称</<realm-name>
  321. <auth-method>BASIC</auth-method>
  322. <form-login-config>如果auth-method采用FORM,则这里填写form-login-config名称</form-login-config>
  323.  
  324. </login-config>
  325. /*
  326. 关于security-role,在前面的servlet已经说明过,这里要强调一下:
  327. web.xml中的HTTP认证方法实际上有两个步骤:
  328. 1) 检查提供的用户名和密码是否正确。
  329. 2) 判断用户是否映射到特定的安全角色。例如,用户可能提供了正确的用户名和密码,但没有映射到特定的安全角色,也将被禁止访问特定的Web资源。
  330. */
  331. <security-role>
  332. <role-name>admin</role-name>
  333. </security-role>
  334. </web-app>

以上就是web.xml的完整结构,需要注意的是,web.xml中有一些环境参数的加载配置,它们之间存在优先级的关系,我们在编写配置的时候需要注意这一点

  1. web.xml 的加载顺序是:context-param -> listener -> filter -> servlet ,而相同类型节点之间的程序调用的顺序是根据对应的mapping的顺序进行调用的

3. JSP基础语法

JSP的本质是Servlet,当用户向指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每一个静态的HTML标签和所有在HTML页面中出现的内容
JSP页面由如下两部分组成

  1. . 静态部分: 标准的HTML标签、静态的页面内容,也就是普通的HTML代码
  2. . 动态部分: java程序控制的内容,这些内容由Java程序来动态生成

  1. /*
  2. 1. JSP的编译指令
  3. */
  4. <%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
  5. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  6. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  7. <html xmlns="http://www.w3.org/1999/xhtml">
  8. <head>
  9. <title>learn j2ee</title>
  10. /*
  11. 2. JSP注释
  12. */
  13. </head>
  14. /*
  15. 3. JSP声明
  16. */
  17. <body>
  18. /*
  19. 4. JSP表达式
  20. */
  21. /*
  22. 5. JSP脚本
  23. */
  24. /*
  25. 6. JSP的动作指令
  26. */
  27. /*
  28. 7. JSP脚本中的内置对象
  29. */
  30. </body>
  31. </html>

0x1: JSP的编译指令

  1. JSP的编译指令是通过JSP引擎的消息,它不直接生成输出。编译指令都有默认值,我们并不需要为每个指令设置值。它的格式如下
  2. <%@ 编译指令名 属性名="属性值"...%>(不同属性名之间用空格分开)
  3. ) page: Page指令为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令
  4. 1.1) buffer: 指定缓冲区的大小。缓冲区是JSP内部对象"out",它用于缓存JSP页面对客户端浏览器的输出,默认值为8KB,可以设置为none,也可以设置为其他的值,单位为Kb
  5. 1.2) autoFlush: 当缓冲区即将满而溢出时,是否需要强制输出缓冲区的内容:
  6. 1.2.) 如果设置为true则正常输出
  7. 1.2.) 如果设置为false,则会在buffer溢出时产生一个异常
  8. 1.3) contentType: 用于设定生成网页的文件格式(MIME类型)、和编码字符集(页面字符集类型)(text/html;charSet=ISO--)
  9. 1.3.) 默认的MIME类型是text/html
  10. 1.3.) 默认的字符集类型为ISO--
  11. 1.4) errorPage: 指定错误处理页面,如果本页面产生了异常或错误,而该JSP页面没有对应的错误处理代码(没有用trycatch机制捕捉异常),则会自动调用该属性所指定的JSP
    页面。值得注意的是,为页面指定错误发生时的错误提示页面是一种安全的做法,能够在一定程度上组织error-based-sql-injection的攻击
  12. 1.5) isErrorPage: 指定当前页面是否可以作为另一个JSP页面的错误处理页面
  13. 1.6) extends: JSP程序编译时所产生的Java类,需要继承的父类,或者需要实现的接口的全限定类名(即包含包名在内的完整路径)
  14. 1.7) import: 用来导入包。默认自动导入的包(参数之间用逗号分隔)(java.lang.*,javax.servlet.*)
  15. 1.7.) java.lang.*
  16. 1.7.) javax.servlet.*
  17. 1.7.) javax.servlet.jsp.*
  18. 1.7.) javax.servlet.http.*
  19. 1.8) info: 定义JSP页面的描述信息
  20. 1.9) isThreadSafe: 指定对JSP页面的访问是否为线程安全
  21. 1.10) language: 定义JSP页面所用的脚本语言,默认是Java
  22. 1.11) session: 指定JSP页面是否使用session
  23. 1.12) isELIgnored: 指定是否执行EL表达式
  24. 1.13) isScriptingEnabled: 确定脚本元素能否被使用
  25. ) include: 用于指定包含另一个页面
  26. <%@include file="file.jsp"%>
  27. 可以将外部文件嵌入到当前JSP文件中,同时解析这个页面中的JSP语句(如果有的话),也就是说,它既可以包含静态的文本,也可以包含动态的JSP页面。包含页面在编译时将完全包含了被包
    含页面的代码,融合成一个页面。作用和PHP中的inlcuderequire类似。
  28. 需要注意的是,要指出的是,静态包含还会将被包含页面的编译指令也包含进来,如果两个页面的编译指令冲突,那么页面就会出错(即被包含的页面中不能重复定义
    pageincludetaglib)
  29. ) taglib: 用于定义和访问自定义标签
  30. 自定义标签库是一种非常优秀的表现层组件技术。通过使用自定义标签库,可以在简单的标签中封装复杂的功能,在JSP2中使用自定义标签需要以下步骤
  31. ) 开发自定义标签处理类
  32. JSP页面使用一个标签时,底层实际上由标签处理类提供支持,从而可以通过简单的标签来封装复杂的功能,从而使团队更好地协作开发。自定义标签类应该继承一个父类:
    javax.servlet.jsp.tagext.SimpleTagSupport,除此之外,JSP自定义标签类还有如下要求(通过接口来强制性保证):
  33. ) 如果标签包含属性,每个属性都有对应的gettersetter方法
  34. ) 重写doTag()方法,这个方法负责生成页面内容
  35. example1: 无属性、无标签体的最简单的标签处理类
  36. package lee;
  37. import javax.servlet.jsp.tagext.*;
  38. import javax.servlet.jsp.*;
  39. import java.io.*;
  40.  
  41. public class HelloWorldTag extends SimpleTagSupport
  42. {
  43. //重写doTag方法,该方法在标签结束生成页面内容
  44. public void doTag()throws JspException, IOException
  45. {
  46. //获取页面输出流,并输出字符串
  47. getJspContext().getOut().write("Hello World " + new java.util.Date());
  48. }
  49. }
  50. 这个标签处理类继承了SimpleTagSupport父类,并重写了doTag()方法,doTag()负责输出页面内容(即标签代表的内容)
  51.  
  52. example2: 带属性的标签处理类
  53. package lee;
  54. import javax.servlet.jsp.tagext.*;
  55. import javax.servlet.jsp.*;
  56. import java.io.*;
  57. import java.sql.*;
  58.  
  59. public class QueryTag extends SimpleTagSupport
  60. {
  61. //标签的属性
  62. private String driver;
  63. private String url;
  64. private String user;
  65. private String pass;
  66. private String sql;
  67.  
  68. //driver属性的setter和getter方法
  69. public void setDriver(String driver)
  70. {
  71. this.driver = driver;
  72. }
  73. public String getDriver()
  74. {
  75. return this.driver;
  76. }
  77.  
  78. //url属性的setter和getter方法
  79. public void setUrl(String url)
  80. {
  81. this.url = url;
  82. }
  83. public String getUrl()
  84. {
  85. return this.url;
  86. }
  87.  
  88. //user属性的setter和getter方法
  89. public void setUser(String user)
  90. {
  91. this.user = user;
  92. }
  93. public String getUser()
  94. {
  95. return this.user;
  96. }
  97.  
  98. //pass属性的setter和getter方法
  99. public void setPass(String pass)
  100. {
  101. this.pass = pass;
  102. }
  103. public String getPass()
  104. {
  105. return this.pass;
  106. }
  107.  
  108. //sql属性的setter和getter方法
  109. public void setSql(String sql)
  110. {
  111. this.sql = sql;
  112. }
  113. public String getSql()
  114. {
  115. return this.sql;
  116. }
  117.  
  118. //conn属性的setter和getter方法
  119. public void setConn(Connection conn)
  120. {
  121. this.conn = conn;
  122. }
  123. public Connection getConn()
  124. {
  125. return this.conn;
  126. }
  127.  
  128. //stmt属性的setter和getter方法
  129. public void setStmt(Statement stmt)
  130. {
  131. this.stmt = stmt;
  132. }
  133. public Statement getStmt()
  134. {
  135. return this.stmt;
  136. }
  137.  
  138. //rs属性的setter和getter方法
  139. public void setRs(ResultSet rs)
  140. {
  141. this.rs = rs;
  142. }
  143. public ResultSet getRs()
  144. {
  145. return this.rs;
  146. }
  147.  
  148. //rsmd属性的setter和getter方法
  149. public void setRsmd(ResultSetMetaData rsmd)
  150. {
  151. this.rsmd = rsmd;
  152. }
  153. public ResultSetMetaData getRsmd()
  154. {
  155. return this.rsmd;
  156. }
  157. //执行数据库访问的对象
  158. private Connection conn = null;
  159. private Statement stmt = null;
  160. private ResultSet rs = null;
  161. private ResultSetMetaData rsmd = null;
  162. public void doTag()throws JspException,
  163. IOException
  164. {
  165. try
  166. {
  167. //注册驱动
  168. Class.forName(driver);
  169. //获取数据库连接
  170. conn = DriverManager.getConnection(url,user,pass);
  171. //创建Statement对象
  172. stmt = conn.createStatement();
  173. //执行查询
  174. rs = stmt.executeQuery(sql);
  175. rsmd = rs.getMetaData();
  176. //获取列数目
  177. int columnCount = rsmd.getColumnCount();
  178. //获取页面输出流
  179. Writer out = getJspContext().getOut();
  180. //在页面输出表格
  181. out.write("<table border='1' bgColor='#9999cc' width='400'>");
  182. //遍历结果集
  183. while (rs.next())
  184. {
  185. out.write("<tr>");
  186. //逐列输出查询到的数据
  187. for (int i = ; i <= columnCount ; i++ )
  188. {
  189. out.write("<td>");
  190. out.write(rs.getString(i));
  191. out.write("</td>");
  192. }
  193. out.write("</tr>");
  194. }
  195. }
  196. catch(ClassNotFoundException cnfe)
  197. {
  198. cnfe.printStackTrace();
  199. throw new JspException("自定义标签错误" + cnfe.getMessage());
  200. }
  201. catch (SQLException ex)
  202. {
  203. ex.printStackTrace();
  204. throw new JspException("自定义标签错误" + ex.getMessage());
  205. }
  206. finally
  207. {
  208. //关闭结果集
  209. try
  210. {
  211. if (rs != null)
  212. rs.close();
  213. if (stmt != null)
  214. stmt.close();
  215. if (conn != null)
  216. conn.close();
  217. }
  218. catch (SQLException sqle)
  219. {
  220. sqle.printStackTrace();
  221. }
  222. }
  223. }
  224. }
  225.  
  226. example3: 带标签体的标签处理类
  227. 带标签体的标签可以在标签内嵌入其他内容(包括静态HTML、动态JSP内容),通常用于完成一些逻辑运算
  228. package lee;
  229. import javax.servlet.jsp.tagext.*;
  230. import javax.servlet.jsp.*;
  231. import java.io.*;
  232. import java.sql.*;
  233. import java.util.*;
  234.  
  235. public class IteratorTag extends SimpleTagSupport
  236. {
  237. //标签属性,用于指定需要被迭代的集合
  238. private String collection;
  239. //标签属性,指定迭代集合元素,为集合元素指定的名称
  240. private String item;
  241.  
  242. //collection属性的setter和getter方法
  243. public void setCollection(String collection)
  244. {
  245. this.collection = collection;
  246. }
  247. public String getCollection()
  248. {
  249. return this.collection;
  250. }
  251. //item属性的setter和getter方法
  252. public void setItem(String item)
  253. {
  254. this.item = item;
  255. }
  256. public String getItem()
  257. {
  258. return this.item;
  259. }
  260. //标签的处理方法,简单标签处理类只需要重写doTag方法
  261. public void doTag() throws JspException, IOException
  262. {
  263. //从page scope中获取属性名为collection的集合
  264. Collection itemList = (Collection)getJspContext().getAttribute(collection);
  265. //遍历集合
  266. for (Object s : itemList)
  267. {
  268. //将集合的元素设置到page 范围
  269. getJspContext().setAttribute(item, s);
  270. //输出标签体
  271. getJspBody().invoke(null);
  272. }
  273. }
  274. }
  275.  
  276. example4: "页面片段"作为属性的标签处理类
  277. package lee;
  278. import javax.servlet.jsp.tagext.*;
  279. import javax.servlet.jsp.*;
  280. import java.io.*;
  281.  
  282. public class FragmentTag extends SimpleTagSupport
  283. {
  284. private JspFragment fragment;
  285.  
  286. //fragment属性的setter和getter方法
  287. public void setFragment(JspFragment fragment)
  288. {
  289. this.fragment = fragment;
  290. }
  291. public JspFragment getFragment()
  292. {
  293. return this.fragment;
  294. }
  295. @Override
  296. public void doTag() throws JspException, IOException
  297. {
  298. JspWriter out = getJspContext().getOut();
  299. out.println("<div style='padding:10px;border:1px solid black'>");
  300. out.println("<h3>下面是动态传入的JSP片段</h3>");
  301. //调用、输出“页面片段”
  302. fragment.invoke( null );
  303. out.println("</div");
  304. }
  305. }
  306. 上面的程序定义了JspFragment类型的fragment属性,该属性代表了使用该标签时的"页面片段"
  307.  
  308. example5: 动态属性的标签处理类
  309. 在某些特殊情况下,我们需要传入自定义标签的属性个数是不确定的、属性名也是不确定的,这就需要使用到动态属性的标签
  310. package lee;
  311. import javax.servlet.jsp.tagext.*;
  312. import javax.servlet.jsp.*;
  313. import java.io.*;
  314. import java.util.*;
  315.  
  316. public class DynaAttributesTag extends SimpleTagSupport implements DynamicAttributes
  317. {
  318. //保存每个属性名的集合
  319. private ArrayList<String> keys = new ArrayList<String>();
  320. //保存每个属性值的集合
  321. private ArrayList<Object> values = new ArrayList<Object>();
  322.  
  323. @Override
  324. public void doTag() throws JspException, IOException
  325. {
  326. JspWriter out = getJspContext().getOut();
  327. //此处只是简单地输出每个属性
  328. out.println("<ol>");
  329. for( int i = ; i < keys.size(); i++ )
  330. {
  331. String key = keys.get( i );
  332. Object value = values.get( i );
  333. out.println( "<li>" + key + " = " + value + "</li>" );
  334. }
  335. out.println("</ol>");
  336. }
  337.  
  338. /*
  339. 实现DynamicAttributes接口必须实现setDynamicAttribute,该方法用于为该标签处理类动态添加属性名、属性值
  340. */
  341. @Override
  342. public void setDynamicAttribute( String uri, String localName, Object value) throws JspException
  343. {
  344. //添加属性名
  345. keys.add( localName );
  346. //添加属性值
  347. values.add( value );
  348. }
  349. }
  350.  
  351. ) 建立一个*.tld文件,每个*.tld文件对应一个标签库,每个标签库可包含多个标签
  352. TLD(Tag Library Definition 标签库定义)的根元素是taglib,它可以包含多个tag子元素,每个tag元素都定义一个标签
  353. taglib结构如下
  354. ) tlib-version: 指定该标签库实现的内部版本号
  355. ) short-name: 该标签库的默认短名
  356. ) uri: 指定该标签库的唯一标识URIJSP页面中使用标签库就是根据该URI属性来定位标签库的
  357. ) tag: 每个tag元素定义一个标签
  358. 4.1) name: 该标签的名字
  359. 4.2) tag-class: 该标签的处理类
  360. 4.3) body-content: 指定标签体内容
  361. 4.3.) tagdependent: 标签处理类自己负责处理标签体
  362. 4.3.) empty: 该标签只能作为空标签使用
  363. 4.3.) scriptless: 该标签可以是静态HTML元素、表达式语言,但不允许JSP脚本
  364. 4.3.) JSP: 该标签可以使用JSP脚本
  365. 4.3.) dynamic-attributes: 该标签是否支持动态属性
  366. JSP2规范的自定义标签还允许直接将一段"页面代码"作为属性,这种方式给自定义标签提供了更大的灵活性,它和普通标签的区别并不大,对于以"页面代码"作为属性的自定义标签来
    说,需要注意的是:
  367. ) 标签处理类中定义类型为JspFragment的属性,该属性代表了"页面片段"
  368. ) 使用标签库时,通过<jsp:attribute../>动作指令为标签库属性指定值
  369. 除此之外,还可以动态属性的标签
  370. <?xml version="1.0" encoding="GBK"?>
  371. <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
  372. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  373. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"
  374. version="2.0">
  375. <tlib-version>1.0</tlib-version>
  376. <short-name>mytaglib</short-name>
  377. <!-- 定义该标签库的URI -->
  378. <uri>http://littlehann.cnblogs.com/mytaglib</uri>
  379.  
  380. <!-- 定义第一个标签 -->
  381. <tag>
  382. <!-- 定义标签名 -->
  383. <name>helloWorld</name>
  384. <!-- 定义标签处理类 -->
  385. <tag-class>lee.HelloWorldTag</tag-class>
  386. <!-- 定义标签体为空 -->
  387. <body-content>empty</body-content>
  388. </tag>
  389.  
  390. /*
  391. 定义第二个标签,对于有属性的标签,需要为<tag../>元素增加<attribute../>子元素,每个attribute子元素定义一个标签元素。<attribute../>子元素通常还需要指定
    如下子元素
  392. 1) name: 属性名,子元素的值是字符串内容
  393. 2) required: 该属性是否为必须属性,true or false
  394. 3) fragment: 该属性是否支持JSP脚本、表达式等动态内容,true or false
  395. */
  396. <tag>
  397. <!-- 定义标签名 -->
  398. <name>query</name>
  399. <!-- 定义标签处理类 -->
  400. <tag-class>lee.QueryTag</tag-class>
  401. <!-- 定义标签体为空 -->
  402. <body-content>empty</body-content>
  403. <!-- 配置标签属性:driver -->
  404. <attribute>
  405. <name>driver</name>
  406. <required>true</required>
  407. <fragment>true</fragment>
  408. </attribute>
  409. <!-- 配置标签属性:url -->
  410. <attribute>
  411. <name>url</name>
  412. <required>true</required>
  413. <fragment>true</fragment>
  414. </attribute>
  415. <!-- 配置标签属性:user -->
  416. <attribute>
  417. <name>user</name>
  418. <required>true</required>
  419. <fragment>true</fragment>
  420. </attribute>
  421. <!-- 配置标签属性:pass -->
  422. <attribute>
  423. <name>pass</name>
  424. <required>true</required>
  425. <fragment>true</fragment>
  426. </attribute>
  427. <!-- 配置标签属性:sql -->
  428. <attribute>
  429. <name>sql</name>
  430. <required>true</required>
  431. <fragment>true</fragment>
  432. </attribute>
  433. </tag>
  434.  
  435. <!-- 定义第三个带标签体的标签 -->
  436. <tag>
  437. <!-- 定义标签名 -->
  438. <name>iterator</name>
  439. <!-- 定义标签处理类 -->
  440. <tag-class>lee.IteratorTag</tag-class>
  441. <!-- 定义标签体不允许出现JSP脚本 -->
  442. <body-content>scriptless</body-content>
  443. <!-- 配置标签属性:collection -->
  444. <attribute>
  445. <name>collection</name>
  446. <required>true</required>
  447. <fragment>true</fragment>
  448. </attribute>
  449. <!-- 配置标签属性:item -->
  450. <attribute>
  451. <name>item</name>
  452. <required>true</required>
  453. <fragment>true</fragment>
  454. </attribute>
  455. </tag>
  456. <tag>
  457. <!-- 定义以"页面片段"作为属性的标签名 -->
  458. <name>fragment</name>
  459. <!-- 定义标签处理类 -->
  460. <tag-class>lee.FragmentTag</tag-class>
  461. <!-- 指定该标签不支持标签体 -->
  462. <body-content>empty</body-content>
  463. <!-- 定义标签属性:fragment -->
  464. <attribute>
  465. <name>fragment</name>
  466. <required>true</required>
  467. <fragment>true</fragment>
  468. </attribute>
  469. </tag>
  470. <!-- 定义接受动态属性的标签 -->
  471. <tag>
  472. <name>dynaAttr</name>
  473. <tag-class>lee.DynaAttributesTag</tag-class>
  474. <body-content>empty</body-content>
  475. <!-- 指定支持动态属性 -->
  476. <dynamic-attributes>true</dynamic-attributes>
  477. </tag>
  478. </taglib>
  479. 定义了上面的标签库定义文件之后,将标签库文件放在WEB应用的WEB-INF路径下,WEB容器会自动加载该文件,则该文件定义的标签库也将生效
  480.  
  481. ) JSP文件中使用自定义标签
  482. JSP页面中使用标签库步骤
  483. ) 导入标签库: 使用taglib编译指令导入标签库,由URI唯一标识指定标签库,并将标签库和指定前缀关联起来(即所有使用该前缀的标签将由此标签库处理)
  484. <%@ taglib uri="tagliburi" prefix="tagPrefix" %>
  485. ) 使用标签: JSP页面中使用自定义标签
  486. <tagPrefix:tagName tagAttribute="tagValue" ..>
  487. <tagBody/>
  488. </tagPrefix:tagName>
  489. example1: helloWorld标签使用
  490. <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
  491. <mytag:helloWorld></mytag:helloWorld>
  492.  
  493. example2: QueryTag标签使用
  494. <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
  495. <mytag:query
  496. driver="com.mysql.jdbc.Driver"
  497. url="jdbc:mysql://localhost:3306/javaee"
  498. user="root"
  499. pass=""
  500. sql="select * from news_inf"/>
  501. 可以看出自定义标签库的作用,以简单的标签,隐藏复杂的逻辑
  502.  
  503. example3: IteratorTag标签使用
  504. <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
  505. <%
  506. //创建一个List对象
  507. List<String> a = new ArrayList<String>();
  508. a.add("疯狂Java");
  509. a.add("www.crazyit.org");
  510. a.add("java");
  511. //将List对象放入page范围内
  512. pageContext.setAttribute("a" , a);
  513. %>
  514. <table border="" bgcolor="#aaaadd" width="">
  515. <!-- 使用迭代器标签,对a集合进行迭代 -->
  516. <mytag:iterator collection="a" item="item">
  517. <tr>
  518. <td>${pageScope.item}</td>
  519. <tr>
  520. </mytag:iterator>
  521. </table>
  522. 可以看到,使用iterator标签遍历集合元素比使用JSP脚本遍历集合元素要优雅,这也是自定义标签的优势
  523.  
  524. example4: fragment标签使用
  525. <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
  526. <mytag:fragment>
  527. <!-- 使用jsp:attribute标签传入fragment参数 -->
  528. <jsp:attribute name="fragment">
  529. <!-- 下面是动态的JSP页面片段 -->
  530. <mytag:helloWorld/>
  531. </jsp:attribute>
  532. </mytag:fragment>
  533. <mytag:fragment>
  534. <jsp:attribute name="fragment">
  535. <!-- 下面是动态的JSP页面片段 -->
  536. ${pageContext.request.remoteAddr}
  537. </jsp:attribute>
  538. </mytag:fragment>
  539.  
  540. example5: dynaAttr标签使用
  541. <%@ taglib uri="http://littlehann.cnblogs.com/mytaglib" prefix="mytag"%>
  542. <mytag:dynaAttr name="crazyit" url="crazyit.org"/>
  543. <mytag:dynaAttr 书名="疯狂Java讲义" 价格="99.0" 出版时间="2008年" 描述="Java图书"/>
  544. 可以看到,不管传入多少属性,这个标签都可以处理
  545.  
  546. JSTLSun提供的一套标签库,DisplayTagApache组织下的一套开源标签库,主要用于生成页面并显示效果

2. JSP注释

  1. <%-- 注释内容 --%>
  2. JSP注释用于标注在程序开发过程中的开发提示,"不会"输出到客户端,即客户端连注释符号都看不到

3. JSP声明

  1. JSP声明用于声明变量和方法,值得注意的是,JSP声明将会转换成对应的Servlet(.java文件)的成员变量或成员方法(牢记这点,后因为我们还会看到在<%..%>中声明的是局部成员),
    因此JSP声明依然符合java语法。
  2. <%! 声明部分 %>
  3.  
  4. 关于JSP的变量声明
  5. 梳理一下,在JSP中声明变量总共有2中情况:
  6. ) 局部变量
  7. <% JSP(本质是java代码)中声明变量 %>,又因为JSP代码是会被Tomcat翻译成Servlet的面向对象的java代码,所以在<% %>中声明的变量全都是局部变量(即在代码块中声明的变量),
    它们不能使用privatepublicstatic等修饰
  8. ) 类变量
  9. <%! %>
  10. 用这种方式声明的变量是在类的范围域中声明的,属于类变量,它们可以使用privatepublicstatic等修饰
    使用的使用一定要注意

  11. example:
  12. <%!
  13. //声明一个整形变量
  14. public int count;
  15. //声明一个方法
  16. public String info()
  17. {
  18. return "hello";
  19. }
  20. %>

4. JSP表达式

  1. JSP提供了一种输出表达式值的简单方法
  2. <%=表达式%>
  3.  
  4. example:
  5. <%!
  6. public int count;
  7. %>
  8. <%=count++%>

5. JSP脚本

  1. 所有可执行性java代码都可以通过JSP脚本嵌入HTML页面

  2. example:
  3. <%
  4. out.println(new java.util.Date());
  5. %>

6. JSP的动作指令

  1. 动作指令与编译指令不同:
  2. ) 编译指令是通知Servlet引擎的处理消息,是在将JSP编译成Servlet时起作用
  3. ) 动作指令只是运行时的动作,通常可替换成JSP脚本,它只是JSP脚本的标准化写法
  4. JSP的动作指令主要有如下7个:
  5.  
  6. ) jsp:forward:
  7. 执行页面转向,将请求的处理转发到下一个页面,可以转发到:
  8. ) 静态HTML页面
  9. ) 动态的JSP页面
  10. ) 容器中的Servlet
  11. 语法1:
  12. <jsp:forward page="{relativeURL|<%=expression%>}"/>
  13. 语法2:
  14. <jsp:forward page="{relativeURL|<%=expression%>}">
  15. {<jsp:param.../>}
  16. </jsp:forward>
  17. 第二种语法用于在转发时增加额外的请求参数。增加的请求参数的值可以通过HttpServletRequest类的getParameter()方法获取
  18. request.getParameter("");
  19. 从本质上来说,jsp:forward这个动作指令只是一个内部转发,即<jsp:forward../>并没有重新向新页面发送了请求,它只是完全采用了新页面来对用户生成响应(内部转发),请求依然是一次
    请求,所以请求参数、请求属性都不会丢失
  20.  
  21. ) jsp:include:
  22. 动态引入一个JSP页面,它不会导入被include页面的编译指令,仅仅将被导入页面的body内容插入本页面中
  23. <jsp:include page="{relativeURL|<%=expression%>}" flush="true"/>
  24. 或者
  25. <jsp:include page="{relativeURL|<%=expression%>}" flush="true">
  26. <jsp:param name="parameterName" value="parameerValue"/>
  27. </jsp:include>
  28. 这里要注意和编译指令的inlcude进行区分
  29. ) 静态引入(编译指令)
  30. <%@include file="file.jsp"%>
  31. 可以将外部文件嵌入到当前JSP文件中,同时解析这个页面中的JSP语句(如果有的话),也就是说,它既可以包含静态的文本,也可以包含动态的JSP页面。包含页面在编译时将完全包含了被包含
    页面的代码。需要指出的是,静态包含还会将被包含页面的编译指令也包含进来,如果两个页面的编译指令冲突,那么页面就会出错
  32. ) 动态引入(动作指令)
  33. <jsp:include>
  34. 归纳起来,动态导入和静态导入的区别有
  35. . 静态导入是将被导入页面的代码完全融入,两个页面融合成一个整体Servlet
  36. . 动态导入则在Servlet中使用include方法来引入被导入页面的内容
  37. . 静态导入时被导入页面的编译指令会起作用。
  38. . 动态导入时被导入页面的编译指令则失去作用,只是插入被导入页面的body内容
  39. . 动态导入可以增加额外的参数
  40. 实际上,forward动作指令和include动作指令(动态引入)十分相似,它们都采用方法来引入目标页面
  41. forward指令使用_jspx_page_context.forward()方法来引入目标页面
  42. include指令使用org.apache.jasper.runtime.JspRuntimeLibrary.include()方法来引入目标页面
  43. 区别在于,执行forward时,被forward的页面将完全代替原有的页面,而执行include时,被include的页面只是插入原有页面
  44. forward拿目标页面代替原有页面,而include则拿目标页面插入原有页面
  45.  
  46. ) JavaBean相关
  47. 3.1) jsp:useBean: JSP页面中初始化一个JavaBean的实例
  48. <jsp:useBean id="name" class="Classname" scope="page|request|session|application"/>
  49. 3.1.) id: JavaBean的实例名
  50. 3.1.) class: 确定JavaBean的实现类
  51. 3.1.) scope: 指定JavaBean实例的作用范围
  52. 3.1.3.1) page: JavaBean实例仅在该页面有效
  53. 3.1.3.2) request: 在本次请求有效
  54. 3.1.3.3) session: 在本次session内有效
  55. 3.1.3.4) application: 在本应用中一直有效
  56. 3.1.)
  57. 3.2) jsp:setProperty: 设置JavaBean实例的属性值
  58. <jsp:setProperty name="BeanName" property="propertyName" value="value" />
  59. 3.2.) name: JavaBean的实例名
  60. 3.2.) property: 确定需要设置的属性名
  61. 3.2.) value: 确定需要设置的属性值
  62. 3.3) jsp:getProperty: 输出JavaBean实例的属性值
  63. <jsp:getProperty name="BeanName" property="propertyName" />
  64. 3.3.) name: 确定需要输出的JavaBean实例名
  65. 3.3.) property: 确定需要输出的属性名
  66. 这三个指令都是与JavaBean相关的指令,如果多个JSP页面中需要重复使用某段代码,我们可以把这段代码定义成java类的方法,然后让多个JSP页面调用该方法即可,这样可以达到较好的代码
    复用
  67. 在.jsp页面中我们可以这样编码
  68. <!-- 创建lee.Person的实例,该实例的实例名为p1 -->
  69. <jsp:useBean id="p1" class="lee.Person" scope="page"/>
  70. <!-- 设置p1name属性值 -->
  71. <jsp:setProperty name="p1" property="name" value="wawa"/>
  72. <!-- 设置p1age属性值 -->
  73. <jsp:setProperty name="p1" property="age" value=""/>
  74. <!-- 输出p1name属性值 -->
  75. <jsp:getProperty name="p1" property="name"/><br/>
  76. <!-- 输出p1age属性值 -->
  77. <jsp:getProperty name="p1" property="age"/>
  78. 从代码中可以看到,我们使用了useBeansetPropertygetProperty来操作JavaBean的方法,同时我们需要明白的是,对于property="name",在JavaBean中提供了setName()、
    getName()方法来操作,property="age"也是同理
  79. 代码中对应的JavaBeanPerson类源代码如下
  80. package lee;
  81. public class Person
  82. {
  83. private String name;
  84. private int age;
  85.  
  86. //无参数的构造器
  87. public Person()
  88. {
  89. }
  90. //初始化全部属性的构造器
  91. public Person(String name , int age)
  92. {
  93. this.name = name;
  94. this.age = age;
  95. }
  96.  
  97. //name属性的setter和getter方法
  98. public void setName(String name)
  99. {
  100. this.name = name;
  101. }
  102. public String getName()
  103. {
  104. return this.name;
  105. }
  106.  
  107. //age属性的setter和getter方法
  108. public void setAge(int age)
  109. {
  110. this.age = age;
  111. }
  112. public int getAge()
  113. {
  114. return this.age;
  115. }
  116. }
  117.  
  118. ) plugin指令
  119. plugin指令主要用于下载服务器端的JavaBean、或Applet到客户端执行。由于程序在客户端执行,因此客户端必须安装虚拟机
  120.  
  121. ) param指令
  122. param指令用于设置参数值,这个指令本身不能单独使用,因为单独的param没有实际意义。param指令可以与以下三个指令结合使用
  123. 5.1) jsp:include
  124. 当与include指令结合使用时,param指令用于将参数值传入被导入的页面
  125. 5.2) jsp:forward
  126. 当与forward指令结合使用时,param指令用于将参数值传入被转向的页面
  127. 5.3) jsp:plugin
  128. 当与plugin指令结合使用时,用于将参数传入页面中的JavaBean实例或Applet实例
  129. <jsp:param name="paramName" value="paramValue"/>
  130. */

7. JSP脚本中的内置对象

  1. JSP脚本中包含内置对象,这些内置对象都是Servleet API接口的实例,JSP规范对它们进行了默认初始化(由JSP页面对应的Servlet_jspService()方法来创建这些实例)。即它们已经是对
    象了,可以直接在JSP脚本中使用了
  2. 内置对象依次如下:
  3. ) application:
  4. javax.servlet.ServletContext的实例,该实例代表JSP所属的WEB应用本身,因此可以使用application来操作WEB相关的数据,application对象通常有如下两个作用:
  5. 1.1) 在整个WEB应用的多个JSPServlet之间共享数据
  6. application通过setAttribute(String attrName, Object value)方法将一个值设置成applicationattrName属性,该属性的值对整个WEB应用有效,因此该WEB应用的每
    JSP页面或Servlet都可以访问该属性,访问属性的方法为getAttribute(String attrName)
  7. ) put-application.jsp
  8. <% application.setAttribute("counter",String.valueOf(++i)); %>
  9. ) get-application.jsp
  10. <%=application.getAttribute("counter")%>
  11. ) GetApplication.java
  12. ServletContext sc = getServletConfig().getServletContext();
  13. out.println(sc.getAttribute("counter"));
  14. 因为application代表的是整个WEB应用,因此可以在JSPServlet之间共享数据,由于在Servlet中并没有application内置对象,所以需要获取该web应用的ServletContext
    实例,每个web应用只有一个ServletContext实例,而在JSP中可以直接通过application内置对象访问该实例
  15. 1.2) 访问WEB应用的配置参数
  16. 除了共享数据,application还可用于从web.xml中获得WEB应用的配置参数
  17. //从配置参数中获取驱动
  18. String driver = application.getInitParameter("driver");
  19. 从以上的代码可以看到,可以使用applicationgetInitParameter(String paramName)来获取WEB应用的配置参数,这些参数应该在web.xml文件中使用context-param元素
    配置,每个<context-param../>元素配置一个参数
  20. <context-param>
  21. <param-name>driver</param-name>
  22. <param-value>com.mysql.jdbc.Driver</param-value>
  23. </context-param>
  24.  
  25. ) config对象
  26. javax.servlet.ServletConfig类的实例,config对象代表当前JSP配置信息
  27. <%=config.getServletName()%>
  28. 因为所有的JSP页面都有相同的名字: jsp,所以这段JSP代码永远输出jsp
  29. 实际上,我们也可以在web.xml文件中配置JSP,这样就可以为JSP页面指定配置信息,并为JSP页面指定一个虚拟路径
  30. ) configTest2.jsp
  31. <!-- 输出该JSP名为name的配置参数 -->
  32. name配置参数的值:<%=config.getInitParameter("name")%><br/>
  33. <!-- 输出该JSP名为age的配置参数 -->
  34. age配置参数的值:<%=config.getInitParameter("age")%>
  35. ) web.xml
  36. <servlet>
  37. <!-- 指定Servlet名字 -->
  38. <servlet-name>config</servlet-name>
  39. <!-- 指定将哪个JSP页面配置成Servlet -->
  40. <jsp-file>/configTest2.jsp</jsp-file>
  41. <!-- 配置名为name的参数,值为yeeku -->
  42. <init-param>
  43. <param-name>name</param-name>
  44. <param-value>yeeku</param-value>
  45. </init-param>
  46. <!-- 配置名为age的参数,值为30 -->
  47. <init-param>
  48. <param-name>age</param-name>
  49. <param-value></param-value>
  50. </init-param>
  51. </servlet>
  52. <servlet-mapping>
  53. <!-- 指定将config Servlet配置到/config URL-->
  54. <servlet-name>config</servlet-name>
  55. <url-pattern>/config</url-pattern>
  56. </servlet-mapping>
  57.  
  58. ) exception对象
  59. exception对象是Throwable的实例,代表JSP脚本中产生的错误和异常,是JSP异常机制的一部分。在JSP脚本中无须处理异常,即使该异常是checked异常,JSP脚本包含的异常都可以交
    给错误处理页面处理,exception对象也仅在异常处理页面中才有效。
  60. 打开普通的JSP页面所生成的Servlet类,可以看到如下代码段
  61. public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
  62. throws java.io.IOException, javax.servlet.ServletException
  63. {
  64. ..
  65. try
  66. {
  67. response.setContentType("text/html; charset=GBK");
  68. ..
  69. out.write(' ');
  70. }
  71. catch (java.lang.Throwable t)
  72. {
  73. ..
  74. if (_jspx_page_context != null)
  75. _jspx_page_context.handlePageException(t);
  76. else
  77. throw new ServletException(t);
  78. }
  79. finally
  80. {
  81. _jspxFactory.releasePageContext(_jspx_page_context);
  82. }
  83. }
  84. 从以上代码可以看出,JSP脚本和静态HTML部分都已经转换成_jspService()方法里的执行型代码,这就是JSP脚本无须处理异常的原因,因为这些脚本都已经被包含在try块中了。一旦try
    块中捕捉到JSP脚本的异常,并且_jspx_page_context不为null,就会由该对象来处理异常。_jspx_page_context对异常的处理也非常简单: 如果该页面的page指令指定了errorPage属性
    ,则将请求forwarderrorPage属性指定的页面,否则使用系统页面来输出异常信息
  85.  
  86. ) out对象
  87. out对象代表一个页面输出流,通常用于在页面删输出变量值、及常量。所有使用out的地方,都可以使用输出表达式来代替,而且输出表达式更加简洁。从底层原理来看,<%=..%>的本质就
    out.write(..);
  88.  
  89. ) pageContext对象
  90. pageContext对象代表页面上下文,该对象主要用于访问JSP之间的共享数据。使用pageContext可以访问pagerequestsessionapplication范围的变量。
  91. pageContextjavax.servlet.jsp.PageContext类的实例,它提供了
  92. getAttribute(String name, int scope)来取得指定范围内的name属性,其中scope可以是如下值:
  93. ) PageContext.PAGE_SCOPE(对应于page范围,默认值)
  94. ) PageContext.REQUEST_SCOPE(对应于requsst范围)
  95. ) PageContext.SESSION_SCOPE(对应于session范围)
  96. ) PageContext.APPLICATION_SCOPE(对应于application范围)
  97. getAttribute相对的,PageContext内置对象自然也有一个setAttribute()方法,用于将指定变量放入pagerequestsessionapplication范围内
  98. <%
  99. //使用pageContext设置属性,该属性默认在page范围内
  100. pageContext.setAttribute("page","hello");
  101. //下面获取各属性所在的范围:
  102. out.println("page变量所在范围:" + pageContext.getAttributesScope("page") + "<br/>");
  103. %>
  104.  
  105. 除此之外,pageContext还可用于获取其他内置对象,pageContext对象还包含如下方法
  106. ) ServletRequest getRequest(): 获取request对象
  107. ) ServletResponse getResponse(): 获取response对象
  108. ) ServletConfig getServletConfig(): 获取config对象
  109. ) ServletContext getServletContext(): 获取application对象
  110. ) HttpSession getSession(): 获取session对象
  111. 因此,pageContext对象是一个很重要的对象,一旦在JSPServlet编程中获取了pageContext对象,就可以通过它提供的相应方法来获取其他内置对象
  112.  
  113. ) request对象
  114. request对象是JSP中重要的对象,每个request对象封装着一次用户请求,并且所有的请求参数都被封装在request对象中,因此request对象是获取"请求参数"的重要途径。除此之外,
    request可代表本次请求的范围,所以还可用于操作request范围的属性
  115. request对象相关的功能有:
  116. ) 获取请求头/请求参数
  117. requestHttpServletRequest接口的实例,它提供了如下几个方法来获得"请求参数"(GETPOSTCOOKIE)
  118. 1.1) String getParameter(String paramName): 获取paramName参数的值
  119. 1.2) Map getParameterMap(): 获取所有请求参数名和参数值所组成的Map对象
  120. 1.3) Enumeration getParameterNames(): 获取所有请求参数名和参数值所组成的Enumeration对象
  121. 1.4) String[] getParameterValues(String name): 获取参数name的值,如果有同名的多个,则返回数组
  122. HttpServletRequest提供了如下方法来访问HTTP请求头
  123. 1.1) String getHeader(String name): 获取指定HTTP头的参数值
  124. 1.2) java.util.Enumeration<String> getHeaderNames(): 获取所有请求头的名称
  125. 1.3) java.util.Enumeration<String> getHeaders(String name): 获取指定请求头的所有值
  126. 1.4) int getIntHeader(String name): 获取指定请求头的值,并转化为整数值返回
  127.  
  128. ) 操作request范围的属性
  129. HttpServletRequest还包含如下两个方法,用于设置和获取request范围的属性
  130. 2.1) setAttribute(String attName, Object attValue): attValue设置成request范围的属性(用于JSP页面间共享变量)
  131. 2.2) Object getAttribute(String attName): 获取request范围的属性
  132.  
  133. ) 执行forward、或include
  134. request还有一个功能是执行forwardinclude,也就是代替JSP所提供的forwardinclude动作指令。
  135. HttpServletRequest类提供了一个:
  136. RequesDispatcher getRequestDispatcher(String path):
  137. ) path为希望forwardinclude的目标路径
  138. 返回了一个RequesDispatcher对象,它提供如下两个方法:
  139. ) forward(ServletRequest request, ServletResponse response): 执行forward
  140. getRequestDispatcher("/a.jsp").forward(request, response);
  141. ) include(ServletRequest request, ServletResponse response): 执行include
  142. getRequestDispatcher("/a.jsp").include(request, response);
  143.  
  144. ) response对象
  145. response代表服务器对客户端的响应。大部分时候,使用out(页面输出流)生成响应更简单。但outJspWriter的实例,JspWriterWriter的子类,而Writer是字符流,无法输出非字
    符数据。如果需要在JSP中生成一副位图、PDF文档,则必须使用response作为响应输出
  146. 7.1) response响应生成非字符响应
  147. responseHttpServletResponse接口的实例,该接口提供了一个getOutputStream()方法,该方法返回响应输出"字节流"
  148. <%-- 通过contentType属性指定响应数据是图片 --%>
  149. <%@ page contentType="image/jpeg" language="java"%>
  150. <%@ page import="java.awt.image.*,javax.imageio.*,java.io.*,java.awt.*"%>
  151. <%
  152. //创建BufferedImage对象
  153. BufferedImage image = new BufferedImage(, , BufferedImage.TYPE_INT_RGB);
  154. //以Image对象获取Graphics对象
  155. Graphics g = image.getGraphics();
  156. //使用Graphics画图,所画的图像将会出现在image对象中
  157. g.fillRect(,,,);
  158. //设置颜色:红
  159. g.setColor(new Color(,,));
  160. //画出一段弧
  161. g.fillArc(, , ,, , );
  162. //设置颜色:绿
  163. g.setColor(new Color( , , ));
  164. //画出一段弧
  165. g.fillArc(, , ,, , );
  166. //设置颜色:蓝
  167. g.setColor(new Color( , , ));
  168. //画出一段弧
  169. g.fillArc(, , ,, , );
  170. //设置颜色:黑
  171. g.setColor(new Color(,,));
  172. g.setFont(new Font("Arial Black", Font.PLAIN, ));
  173. //画出三个字符串
  174. g.drawString("red:climb" , , );
  175. g.drawString("green:swim" , , );
  176. g.drawString("blue:jump" , , );
  177. g.dispose();
  178. //将图像输出到页面的响应
  179. ImageIO.write(image , "jpg" , response.getOutputStream());
  180. %>
  181. 从代码中可以看到几个关键点:
  182. ) 设置了服务器响应数据是image/jpeg,这表明服务器响应是一张JPG图片
  183. ) 最后的响应输出流是一个图片的字节流
  184. 也可以在其他HTML页面中使用img标签来显示这张图片
  185. <img src="img.jsp">
  186.  
  187. 7.2) 重定向
  188. 重定向是response的另外一个用处,要注意的是,和forward这种内部转接"不同"的是,response的重定向会丢失所有的原始请求参数和request范围的属性,因为重定向将生成第二
    次请求,自然与前一次请求不在同一个request范围内。
  189. HttpServletResponse提供了一个sendRedirect(String path)方法,该方法用于"重定向"path资源,即"重新"path资源发送请求
  190.  
  191. 7.3) 增加Cookie
  192. 增加Cookie也是使用response内置对象完成的,增加Cookie的步骤如下
  193. ) 创建Cookie实例,构造函数Cookie(String name, String value)
  194. ) 设置Cookie的生命周期,即该Cookie在多长时间内有效
  195. ) 向客户端写Cookievoid addCookie(Cookie cookie): 增加Cookie
  196. <%
  197. //获取请求参数
  198. String name = request.getParameter("name");
  199. //以获取到的请求参数为值,创建一个Cookie对象
  200. Cookie c = new Cookie("username" , name);
  201. //设置Cookie对象的生存期限
  202. c.setMaxAge( * );
  203. //向客户端增加Cookie对象
  204. response.addCookie(c);
  205. %>
  206.  
  207. 获取客户端发送的Cookie的方法
  208. <%
  209. //获取本站在客户端上保留的所有Cookie
  210. Cookie[] cookies = request.getCookies();
  211. //遍历客户端上的每个Cookie
  212. for (Cookie c : cookies)
  213. {
  214. //如果Cookie的名为username,表明该Cookie是我们需要访问的Cookie
  215. if(c.getName().equals("username"))
  216. {
  217. out.println(c.getValue());
  218. }
  219. }
  220. %>
  221. 要注意的是:
  222. ) 使用Cookie对象必须设置生存周期,否则Cookie将会随浏览器关闭而自动消失(session cookie)
  223. ) 如果要存入中文Cookie,则需要使用java.net.URLEncoder进行编码,在获取时用java.net.URLDncoder进行解码
  224.  
  225. ) session对象
  226. session对象代表一次用户会话,session范围内的属性可以在多个页面的跳转之间共享。session对象是HttpSession的实例,它有如下两个常用的方法:
  227. 8.1) setAttribute(String attName, Object attValue): 设置session范围内attName属性的值为attValue
  228. 8.2) getAttribute(String attName): 返回session范围内attName属性的值
  229. 使用session对象要注意的是:
  230. 考虑session本身的目的,通常只应该把与用户会话状态相关的信息放入session范围内。不要仅仅为两个页面之间交换信息,就将信息放入session范围内。如果仅仅是为了页面间交换信
    息,可以将信息放入request范围内,然后forward请求即可。
  231. 除此之外,session机制通常用于保存客户端的状态信息,这些状态信息需要保存到web服务器的硬盘上,所以要求session里的属性值必须是可序列化的,否则将引起"不可序列化异常"
    session的属性值可以是任何可序列化的java对象

4. Servlet基础语法

我们知道,JSP的本质就是Servlet,开发者把编写好的JSP页面部署在WEB容器中之后,WEB容器会将JSP编译成对应的Servlet。

Servlet和JSP的区别在于:

  1. ) Servlet中没有内置对象,原来在JSP中的内置对象都必须由程序显示创建。JSPServlet的一种简化,使用JSP只需要完成程序员需要输出到客户端的内容,至于JSP脚本如何嵌入一个类中,
    JSP容器完成
  2. ) 对于静态HTML标签,Servlet都必须使用页面输出流逐行输出。而Servlet则是一个完整的java类,这个类的service()方法用于生成对客户端的响应

0x1: Servlet的配置

配置需要的准备条件如下:

  1. . 编辑好的Servlet源代码文件并不能响应用户请求,还必须将其编译成class文件。将编译好的.class文件放在WEB-INF/classes路径下,如果Servlet有包,则还应该将class文件放在对
    应的包路径下
  2. . 为了让Servlet能响应用户请求,还必须将Servlet配置在web应用中,配置Servlet有两种方式
  3. ) Servlet类中使用@WebServlet Annotation进行配置
  4. 使用@WebServlet时可制定如下常用属性
  5. 1.1) asyncSupported: 声明Servlet是否支持异步操作模式,等价于<async-supported>标签
  6. 1.2) displayName: Servlet的显示名,通常配合工具使用,等价于<display-name>标签
  7. 1.3) initParams: 指定一组Servlet初始化参数,等价于<init-param>标签
  8. 1.4) loadOnStartup: 指定Servlet的加载顺序,等价于<load-on-startup>标签
  9. 1.5) name: 指定Servletname属性,等价于<servlet-name>,如果没有显式指定,则该Servlet的取值即为类的全限定名
  10. 1.6) urlPatterns: 指定一组ServletURL匹配模式(虚拟路径)。等价于<url-pattern>标签
  11. 1.7) value: 该属性等价于urlPatterns属性。两个属性不能同时使用
  12. example:
  13. @WebServlet(name="firstServlet", urlPatterns={"/firstServlet"})
  14. 需要注意的是,如果打算采用Annotation来配置Servlet,需要注意如下两点:
  15. ) 不要在web.xml文件的根元素<web-app../>中指定metadata-complete="true",因为当该属性值为true时,该web应用不会加载Annotation配置的WEB组件(如Servlet
    FilterListener等)
  16. ) 不要在web.xml文件中配置该Servlet
  17. ) 通过在web.xml文件中进行配置
  18. 2.1) 配置Servlet的名字: 对应web.xml文件中的<servlet/>元素
  19. 2.2) 配置ServletURL: 对应web.xml文件中的<servlet-mapping/>元素。这一步是可选的。但如果没有为Servlet配置URL(虚拟路径),则该Servlet不能响应用户请求
  20. example:
  21. <servlet>
  22. <!-- 指定Servlet的名字,相当于指定@WebServletname属性 -->
  23. <servlet-name>firstServlet</servlet-name>
  24. <!-- 指定Servlet的实现类 -->
  25. <servlet-class>lee.FirstServlet</servlet-class>
  26. </servlet>
  27. <!-- 配置ServletURL -->
  28. <servlet-mapping>
  29. <!-- 指定Servlet的名字 -->
  30. <servlet-name>firstServlet</servlet-name>
  31. <!-- 指定Servlet映射的URL地址,相当于指定@WebServleturlPatterns属性-->
  32. <url-pattern>/aa</url-pattern>
  33. </servlet-mapping>
  34. 需要明白的,Annotationweb.xml配置,只要其中一种即可完成Servlet的配置

0x2: JSP/Servlet的生命周期

JSP的本质就是Servlet,当Servlet在容器中运行时,其实例的创建及销毁等都不是由程序员决定的,而是由WEB容器进行控制的。
创建Servlet实例有两个时机

  1. . 客户端第一次请求某个Servlet时,系统创建该Servlet的实例: 大部分的Servlet都是这种情况
  2. . WEB应用启动时立即创建Servlet实例,即load-on-startup Servlet

每个Servlet的运行都遵循如下生命周期

  1. . 创建Servlet实例
  2. . WEB容器调用Servletinit方法,对Servlet进行初始化
  3. . Servlet初始化之后,将一直存在于容器中,用于响应客户端请求:
  4. ) 如果客户端发送GET请求,容器调用ServletdoGet方法处理并响应请求
  5. ) 如果客户端发送POST请求,容器调用ServletdoPost方法处理并响应请求
  6. ) 或者统一用service()方法处理来响应用户请求
  7. . WEB容器决定销毁Servlet时,先调用Servletdestroy方法,通常在关闭web应用之前销毁Servlet

0x3: Filter介绍

Filter从本质上来说和Servlet很相似,它主要用于对用于请求(HttpServletRequest)进行预处理、以及对用户响应(HttpServletResponse)进行后处理,和linux上的iptables类似,是一种典型的"处理链"机制。
Filter完整运行的流程是:

  1. 1) Filter对用于请求(HttpServletRequest)进行预处理
  2. 它使用户可以使用串行的方式在request到达servlet之前预处理,即改变一个Request
  3.  
  4. 2) 接着将请求交给Servlet进行处理并生成响应
  5.  
  6. 3) 最后Filter再对服务器响应(HttpServletResponse)进行后处理
  7. 它使用户可以使用串行的方式在request离开servlet时处理response,即修改一个response

Filter可以实现的功能包括

  1. . servlet被调用之前截获
  2. . servlet被调用之前检查servlet request
  3. . 根据需要修改request头和request数据
  4. . 根据需要修改response头和response数据
  5. . servlet被调用之后截获

使用Filter编程的完整流程是:

  1. . 创建Filter
  2. 创建Filter必须实现javax.servlet.Filter接口,在该接口中定义了如下3个方法
  3. ) void init(FilterConfig config): Filter的初始化
  4. ) void destroy(): 用于Filter销毁前,完成资源的回收等工作
  5. ) void doFilter(ServletRequest request, ServletResponse response, FilterChain chain): 实现过滤功能,该方法负责对每个请求、及响应增加额外的处理
  6. example:
  7. package lee;
  8. import javax.servlet.*;
  9. import javax.servlet.http.*;
  10. import javax.servlet.annotation.*;
  11. import java.io.*;
  12.  
  13. @WebFilter(filterName="log", urlPatterns={"/*"})
  14. public class LogFilter implements Filter
  15. {
  16. //FilterConfig可用于访问Filter的配置信息
  17. private FilterConfig config;
  18. //实现初始化方法
  19. public void init(FilterConfig config)
  20. {
  21. this.config = config;
  22. }
  23. //实现销毁方法
  24. public void destroy()
  25. {
  26. this.config = null;
  27. }
  28. //执行过滤的核心方法
  29. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException
  30. {
  31. //---------下面代码用于对用户请求执行预处理---------
  32. //获取ServletContext对象,用于记录日志
  33. ServletContext context = this.config.getServletContext();
  34. long before = System.currentTimeMillis();
  35. System.out.println("开始过滤...");
  36. //将请求转换成HttpServletRequest请求
  37. HttpServletRequest hrequest = (HttpServletRequest)request;
  38. //输出提示信息
  39. System.out.println("Filter已经截获到用户的请求的地址: " + hrequest.getServletPath());
  40. //Filter只是链式处理,请求依然放行到目的地址
  41. chain.doFilter(request, response);
  42. //---------下面代码用于对服务器响应执行后处理---------
  43. long after = System.currentTimeMillis();
  44. //输出提示信息
  45. System.out.println("过滤结束");
  46. //输出提示信息
  47. System.out.println("请求被定位到" + hrequest.getRequestURI() + " 所花的时间为: " + (after - before));
  48. }
  49. }
  50. 从代码中可以看到,doFilter()方法中"请求预处理""响应后处理"的分界线是chain.doFilter()
  51.  
  52. . 配置Filter
  53. 配置Filter和配置Servlet非常类似,需要配置如下两部分:
  54. ) 配置Filter
  55. ) 配置Filter拦截URL模式: Servlet通常只配置一个URL,而Filter可以同时拦截多个请求的URL。因此在配置FilterURL模式时通常会使用"模式字符串"(正则字符串),使得
    Filter可以拦截多个请求
  56. 2.1) Filter类中通过Annotation进行配置
  57. 2.1.) asyncSupported: 声明Filter是否支持异步操作模式
  58. 2.1.) dispatcherTypes: 指定该Filter仅对哪种dispatcher模式的请求进行过滤
  59. 2.1.2.1) ASYNC
  60. 2.1.2.2) ERROR
  61. 2.1.2.3) FORWARD
  62. 2.1.2.4) INLCUDE
  63. 2.1.2.5) REQUEST
  64. 5种组合可以以OR的形式进行组合,dispatcherTypes的默认值是"同时"过滤5种模式的请求
  65. 2.1.) displayName: Filter的显示名
  66. 2.1.) filterName: 指定该Filter的名称
  67. 2.1.) initParams: 指定一组Filter配置参数
  68. 2.1.) servletName: 指定多个Servlet的名称,用于指定该Filter仅对这几个Servlet执行过滤
  69. 2.1.) urlPatterns: 指定一组FilterURL匹配模式(虚拟路径)
  70. 2.1.) value: 该属性等价于urlPatterns属性。两个属性不能同时使用
  71. 2.2) web.xml文件中通过配置文件进行配置
  72. <filter>
  73. <!-- Filter的名字,相当于指定@WebFilterfilterName属性 -->
  74. <filter-name>log</filter-name>
  75. <!-- Filter的实现类 -->
  76. <filter-class>lee.LogFilter</filter-class>
  77. </filter>
  78. <!-- 定义Filter拦截的URL地址 -->
  79. <filter-mapping>
  80. <!-- Filter的名字 -->
  81. <filter-name>log</filter-name>
  82. <!-- Filter负责拦截的URL,相当于指定@WebFilterurlPatterns属性 -->
  83. <url-pattern>/*</url-pattern>
  84. </filter-mapping>
  85.  
  86. 3. 使用Filter
  87. Filter对应的.class文件被加载后,Filter就会根据设定的URL模式进行响应的预处理、后处理

Tomcat Filter的函数调用流程为

  1. . setFilterConfig()方法
  2. 服务器每次只调用一次准备filter的处理
  3.  
  4. . doFilter()方法
  5. 调用多次,用于每次以处理不同的请求。FilterConfig接口有方法可以找到filter名字及初始化参数信息。服务器可以设置FilterConfig为空来指明filter已经终结。
  6. 每一个filterdoFilter()方法中得到当前的requestresponse。在这个方法里,可以进行任何的针对request response的操作.(包括收集数据,包装数据等)
  7.  
  8. . chain.doFilter()方法
  9. filter调用chain.doFilter()方法把控制权交给下一个filter。一个filterdoFilter()方法中结束。如果一个filter想停止request处理而获得对response的完全的控制,那它可以不调用下一个filter,即这是一个链式的操作

Filter和Servlet的异同

  1. 从本质上来说,FilterServlet很相似,Filter里的doFilter()方法里的代码就是从多个Servletservice()方法里抽取的通用代码,通过使用Filter可以实现更好的代码复用
    (类似PHP中的auto_prepend_fileauto_append_file)
  2. 假设系统有包含多个Servlet,这些Servlet都需要进行一些通用处理,比如
  3. ) 权限控制: 在预处理中判断用户是否登录,从而决定是否重定向到初始登录页面
  4. ) 记录日志: 将用户的访问记录记录到日志中
  5. ) URL Rewrite实现网站伪静态
  6. 所谓伪静态,是将*.jsp、*.php、这种动态URL伪装成静态HTML页面,目的是提供搜索引擎的收录率,我们可以通过Filter拦截所有发向*.html请求,然后按某种规则将请求forward到实际的
    *.jsp页面
  7. 3.1) 下载Url Rewrite: http://www.tuckey.org/urlrewrite/
  8. 3.2) urlrewrite-3.2..jar放到WEB-INF\lib目录下
  9. 3.3) 配置WEB-INF\web.xml
  10. <filter>
  11. <filter-name>UrlRewriteFilter</filter-name>
  12. <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
  13. </filter>
  14. <!-- 配置Url RewriteFilter拦截所有请求 -->
  15. <filter-mapping>
  16. <filter-name>UrlRewriteFilter</filter-name>
  17. <url-pattern>/*</url-pattern>
  18. </filter-mapping>
  19. 3.4) 配置WEB-INF\urlrewrite.xml
  20. <urlrewrite>
  21. <rule>
  22. <!-- 所有配置如下正则表达式的请求 -->
  23. <from>/userinf-(\w*).html</from>
  24. <!-- 将被forward到如下JSP页面,其中$1代表上面第一个正则表达式所匹配的字符串 -->
  25. <to type="forward">/userinf.jsp?username=$1</to>
  26. </rule>
  27. </urlrewrite>
  28. 3.5) 访问伪静HTML页面: http://localhost:8080/urlrewrite/userinf-LittleHann.html

0x4: Listener介绍

当WEB应用在WEB容器中运行时,WEB应用内部会不断地发生各种事件:

  1. ) web应用被启动
  2. ) web应用被停止
  3. ) 用户session开始
  4. ) 用户session结束
  5. ) 用户请求到达

通常来说,这些web事件对开发者是透明的
实际上,Servlet API提供了大量监听器和监听WEB应用内部事件,从而允许当WEB内部事件发生时自动回调"事件监听器内的方法"

使用Listener的步骤如下:

  1. . 实现Listener
  2. 监听不同的WEB事件的监听器也不相同。WEB事件监听器接口如下
  3. ) ServletContextListener: 用于监听WEB应用的启动和关闭
  4. 1.1) contextInitialized(ServletContextEvent sce)
  5. 1.2) contextDestroyed(ServletContextEvent sce)
  6. ) ServletContextAttributeListener: 用于监听ServletContext范围(application)内属性的改变
  7. 2.1) attributeAdded(ServletContextAttributeEvent event)
  8. 2.2) attributeRemoved(ServletContextAttributeEvent event)
  9. 2.3) attributeReplaced(ServletContextAttributeEvent event)
  10. ) ServletRequestListener: 用于监听用户请求
  11. 3.1) requestInitialized(ServletRequestEvent sre)
  12. 3.2) requestDestroyed(ServletRequestEvent sre)
  13. 由于实现了ServletRequestListener接口的监听器可以非常方便地监听到每次请求的创建、销毁,因此web应用可通过该接口的监听器来监听访问该应用的每个请求,从而实现系统日志
  14. ) ServletRequestAttributeListener: 用于监听ServletRequest范围(request)内属性的改变
  15. 4.1) attributeAdded(ServletRequestAttributeEvent event)
  16. 4.2) attributeRemoved(ServletRequestAttributeEvent event)
  17. 4.3) attributeReplaced(ServletRequestAttributeEvent event)
  18. ) HttpSessionListener: 用于监听用户session的开始和结束
  19. 5.1) sessionCreated(HttpSessionEvent se)
  20. 5.2) sessionDestroyed(HttpSessionEvent se)
  21. 实现HttpSessionListener接口的监听器可以监听每个用于会话的开始和断开,因此应用可以通过该监听器监听系统的在线用户
  22. ) HttpSessionAttributeListener: 用于监听HttpSession范围(session)内属性的改变
  23. 6.1) attributeAdded(HttpSessionBindingEvent se)
  24. 6.2) attributeRemoved(HttpSessionBindingEvent se)
  25. 6.3) attributeReplaced(HttpSessionBindingEvent se)
  26. . 配置Listener
  27. 配置Listener只要向web应用注册Listener实现类即可,无须配置参数,相对较简单
  28. ) 使用@WebListener修饰Listener实现类
  29. ) web.xml文档中使用<listener../>元素进行配置
  30. <listener>
  31. <!-- 指定Listener的实现类 -->
  32. <listener-class>lee.GetConnListener</listener-class>
  33. </listener>
  34. . 在指定事件发生时执行相应的函数,我们在实现相应的接口时就需要实现相应的函数

Copyright (c) 2014 LittleHann All rights reserved

JSP/Servlet基础语法的更多相关文章

  1. JSP(基础语法)

    一.JSP简介 JSP全称为Java Server Pages,其根本是一个简化的Servlet设计,它实现了在java当中使用HTML标签.JSP是一种动态网页技术标准也就是javaEE的标准.JS ...

  2. jsp servlet基础复习 Part1

    jsp和servlet的一些基础知识整理,用于备忘. 一.jsp与servlet的基本关系 1.jsp-->web容器-->servlet-->加载进容器的虚拟机执行-->输出 ...

  3. JSP SERVLET 基础知识

    jsp(java server page)和servlet是JAVA EE规范的两个基本成员,是JAVA WEB开发的重点也是基础知识.JSP本质上也需要编译成SERVLET运行. JSP比较简单,可 ...

  4. JSP/Servlet基础

    动态网页的技术 html+css javascript(弱语言) jquery(改造) jsp(java的html) servlet(核心) S2SH:structs2 (springmvc) spr ...

  5. jsp servlet基础复习 Part2--GET,Post请求

    最近进行servlet和jsp方面的梳理复习时,发现以前忽略了一个非常重要的知识点:get和post的请求(如果你觉得两者仅仅是提交数据量的大小以及方式不同就大错特错了)的正真区别,下面进行简答的整理 ...

  6. JavaWeb:JSP技术基础

    JavaWeb:JSP技术 快速开始 介绍 JSP全称Java Server Pages,是一种动态网页开发技术.它使用JSP标签在HTML网页中插入Java代码.标签通常以<%开头以%> ...

  7. 01.JSP基础语法

        本章主要讲解Java Web与JSP的入门内容,适合有JSP或Java Web基础的读者学习. 1.Web应用与web.xml文件 (1)Java Web应用程序的结构     Java We ...

  8. JavaWeb基础-Jsp基础语法

    jsp基础语法 JSP的组成 静态内容.指令.表达式.小脚本.声明.注释 JSP的生命周期 用户发出index.jsp ,服务端判断是否是第一次请求,若是第一次请求,则tomcat中的JSP引擎中的文 ...

  9. Jsp基础语法(由简入杂)

    JSP基础语法 一,JSP简介 Jsp是一个简化的Servlet设计,是在服务器端执行,他实现了再Java中使用HTML标签. Jsp是一种动态网页技术标准也是JAVAEE的标准 二,常见动态网站开发 ...

随机推荐

  1. 转:程序员必须知道的几个Git代码托管平台

    http://www.open-open.com/lib/view/open1420704561390.html

  2. .project sturcture和Project Structure 无论是按快捷键或者是从files中打开都不显示

    project sturcture和Project Structure 无论是按快捷键或者是从files中打开都不显示 event log中报:IllegalArgumentException:Mul ...

  3. performSelector:withObject:afterDelay: 精要概览(持续更新)

    - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay; - ...

  4. 项目移植将eclipse里面的项目移植到intellij idea里面

    怎么关联多个库 .  A B C D,A依赖BC,D依赖A,怎么搞? 注意: as和idea里面,project是工作空间的意思,这里面model才是项目. 打开主项目D 打开已经存在的model 导 ...

  5. OpenCV人脸检测demo--facedetect

    &1 问题来源 在运行官网的facedetect这个demo的时候,总是不会出来result的图形,电脑右下角提示的错误是“显示器驱动程序已停止响应,而且已恢复 windows 8(R)”. ...

  6. 在opencv3中实现机器学习之:利用逻辑斯谛回归(logistic regression)分类

    logistic regression,注意这个单词logistic ,并不是逻辑(logic)的意思,音译过来应该是逻辑斯谛回归,或者直接叫logistic回归,并不是什么逻辑回归.大部分人都叫成逻 ...

  7. Github克隆别人的库

    一. 首先在网站上进入别人的库(通过别人提供的链接或者自己在页面上查询),然后在右下方选择SSH,将链接复制下来. 二. 在你的电脑上新建一个与人家库名相同的文件夹,然后在文件夹上右击,在弹出菜单上选 ...

  8. Bootstrap 排版

    Bootstrap 使用 Helvetica Neue. Helvetica. Arial 和 sans-serif 作为其默认的字体栈. 使用 Bootstrap 的排版特性,您可以创建标题.段落. ...

  9. HTML5 文件异步上传 — h5uploader.js

    原文地址:http://imziv.com/blog/article/read.htm?id=62 之前写过一篇H5异步文件上传的文章, 但是很多朋友看着我的这个教程还是出现很多问题,文章写的不是很好 ...

  10. <实训|第三天>Linux登录界面的修改以及Richard Stallman、自由软件运动

    在写博客之前我想说两点: 承认一个错误,昨天写的实训第二天,我把redhat6.7写成了Linux6.7,感谢热心人士的指出! 昨天写的文章名字太长了,今天改善,内容感觉表述不全,希望各位谅解! 官方 ...