Head First Servlets & JSP学习笔记

前言和体系结构

Web服务器做些什么

  • Web服务器接收客户请求,然后向客户返回一些结果。
  • 如果没有请求的资源,则返回404 Not Found错误。

Web客户端做些什么

  • Web客户端允许用户请求服务器上的某个资源,并且向用户显示请求的结果。

客户和服务器都知道HTML和HTTP

  • HTML告诉浏览器怎样向用户显示内容。
  • HTTP是Web上客户和服务器之间进行通信所用的协议。
  • 服务器使用HTTP向客户端发送HTML。

HTML速成指南

标记 描述
注释
锚点——通常用来放一个超链接
对齐
定义文本体的边界

行分隔
将内容居中
定义一个表单

一级标题
定义文档首部的边界
定义HTML文档的边界
在表单中定义一个输入组件

一个新段落
</code></td> <td>HTML文档的标题</td> </tr> </tbody> </table> <h2 id="什么是http协议">什么是HTTP协议?</h2> <ul> <li>HTTP是TCP/IP的上层协议。TCP负责确保从一个网络节点向另一个网络节点发送的文件能作为一个完整的文件到达目的地,尽管在具体传送过程中这个文件可能会分解为小块传输。IP是一个底层协议,负责把数据块(数据包)沿路移动/路由到目的地。HTTP则是另一个网络协议,有一些Web特定的特征,不过它要依赖于TCP/IP从一处向另一处完整地传送请求和响应。HTTP会话的结构是一个简单的请求/响应序列:浏览器发出请求,服务器做出响应。</li> <li>请求流的关键要素:HTTP方法、URL、表单参数。</li> <li>响应流的关键要素:状态码、内容类型、内容。</li> </ul> <h2 id="html是http响应的一部分">HTML是HTTP响应的一部分</h2> <ul> <li>HTTP响应可以包含HTML</li> <li>HTTP还会在响应中包含的内容前面增加首部信息。</li> </ul> <h2 id="请求">请求</h2> <ul> <li>请求最常用的类型为GET和POST。</li> <li>GET是最简单的HTTP方法,它的主要任务就是要求服务器获得一个资源并把资源发回来。</li> <li>POST可以请求某个东西,与此同时向服务器发送一些表单数据。</li> </ul> <h3 id="最好使用post发送数据">最好使用POST发送数据</h3> <ul> <li>GET中的总字符数是有限的(取决于服务器)。</li> <li>用GET发送的数据会追加到URL的后面,在浏览器地址栏中显示出来,所以你发送的数据会完全暴露。</li> <li>如果使用POST而不是GET,用户就不能对一个表单提交建立书签。</li> </ul> <h2 id="http-get请求剖析">HTTP GET请求剖析</h2> <pre class="prettyprint"><code class="language-http hljs "><span class="hljs-attribute">GET /socket.io/1/xhr-polling/cjJ4rr2VUk0aTC0JKKvG?t=1493719041095 HTTP/1.1\r\n Host</span>: <span class="hljs-string">s1-im-notify.csdn.net\r\n</span> <span class="hljs-attribute">Connection</span>: <span class="hljs-string">keep-alive\r\n</span> <span class="hljs-attribute">User-Agent</span>: <span class="hljs-string">Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/5.0.2.2000 Chrome/47.0.2526.73 Safari/537.36\r\n</span> <span class="hljs-attribute">Origin</span>: <span class="hljs-string">http://write.blog.csdn.net\r\n</span> <span class="hljs-attribute">Accept</span>: <span class="hljs-string">*/*\r\n</span> <span class="hljs-attribute">DNT</span>: <span class="hljs-string">1\r\n</span> <span class="hljs-attribute">Referer</span>: <span class="hljs-string">http://write.blog.csdn.net/postlist\r\n</span> <span class="hljs-attribute">Accept-Encoding</span>: <span class="hljs-string">gzip, deflate\r\n</span> <span class="hljs-attribute">Accept-Language</span>: <span class="hljs-string">zh-CN\r\n</span></code></pre> <ul> <li><code>GET /socket.io/1/xhr-polling/cjJ4rr2VUk0aTC0JKKvG?t=1493719041095 HTTP/1.1\r\n</code>为请求行 <br> <ul> <li>GET:HTTP方法</li> <li><code>/socket.io/1/xhr-polling/cjJ4rr2VUk0aTC0JKKvG</code>:Web服务器上资源的路径。</li> <li><code>?t=1493719041095</code>:在GET请求中,参数(如果有)会追加到请求URL第一部分的后面,以”?”开头。各参数之间用”&”分隔。</li> <li><code>HTTP/1.1</code>:Web浏览器所请求的协议的版本。</li> </ul></li> <li><p>其余部分为请求首部:</p> <pre class="prettyprint"><code class=" hljs http"><span class="hljs-attribute">Host</span>: <span class="hljs-string">s1-im-notify.csdn.net\r\n</span> <span class="hljs-attribute">Connection</span>: <span class="hljs-string">keep-alive\r\n</span> <span class="hljs-attribute">User-Agent</span>: <span class="hljs-string">Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/5.0.2.2000 Chrome/47.0.2526.73 Safari/537.36\r\n</span> <span class="hljs-attribute">Origin</span>: <span class="hljs-string">http://write.blog.csdn.net\r\n</span> <span class="hljs-attribute">Accept</span>: <span class="hljs-string">*/*\r\n</span> <span class="hljs-attribute">DNT</span>: <span class="hljs-string">1\r\n</span> <span class="hljs-attribute">Referer</span>: <span class="hljs-string">http://write.blog.csdn.net/postlist\r\n</span> <span class="hljs-attribute">Accept-Encoding</span>: <span class="hljs-string">gzip, deflate\r\n</span> <span class="hljs-attribute">Accept-Language</span>: <span class="hljs-string">zh-CN\r\n</span></code></pre> <p>Accept表示可以接受的MIME类型。</p></li> </ul> <h2 id="http-post请求剖析">HTTP POST请求剖析</h2> <pre class="prettyprint"><code class="language-http hljs "><span class="hljs-attribute">POST /pollmessage HTTP/1.1\r\n Host</span>: <span class="hljs-string">p.f.360.cn\r\n</span> <span class="hljs-attribute">Accept</span>: <span class="hljs-string">*/*\r\n</span> <span class="hljs-attribute">Connection</span>: <span class="hljs-string">Keep-Alive\r\n</span> <span class="hljs-attribute">Cache-Control</span>: <span class="hljs-string">no-cache\r\n</span> <span class="hljs-attribute">Content-Length</span>: <span class="hljs-string">358\r\n</span> <span class="hljs-attribute">Content-Type</span>: <span class="hljs-string">application/x-www-form-urlencoded\r\n</span> \<span class="hljs-attribute">r\n [Full request URI</span>: <span class="hljs-string">http://p.f.360.cn/pollmessage]</span> [<span class="hljs-attribute">HTTP request 1/1] [Response in frame</span>: <span class="hljs-string">150751]</span></code></pre> <ul> <li><code>POST /pollmessage HTTP/1.1\r\n</code>:请求行 <br> <ul> <li><code>POST</code>:HTTP方法</li> <li><code>/pollmessage</code>:资源在Web服务器上的路径</li> <li><code>HTTP/1.1</code>:Web浏览器请求的协议的版本</li> </ul></li> <li><p>请求首部:</p> <pre class="prettyprint"><code class="language-http hljs "><span class="hljs-attribute">Host</span>: <span class="hljs-string">p.f.360.cn\r\n</span> <span class="hljs-attribute">Accept</span>: <span class="hljs-string">*/*\r\n</span> <span class="hljs-attribute">Connection</span>: <span class="hljs-string">Keep-Alive\r\n</span> <span class="hljs-attribute">Cache-Control</span>: <span class="hljs-string">no-cache\r\n</span> <span class="hljs-attribute">Content-Length</span>: <span class="hljs-string">358\r\n</span> <span class="hljs-attribute">Content-Type</span>: <span class="hljs-string">application/x-www-form-urlencoded\r\n</span></code></pre></li> <li><p>消息体(负载):</p> <pre class="prettyprint"><code class="language-http hljs ">[<span class="hljs-attribute">Full request URI</span>: <span class="hljs-string">http://p.f.360.cn/pollmessage]</span> [<span class="hljs-attribute">HTTP request 1/1] [Response in frame</span>: <span class="hljs-string">150751]</span></code></pre></li> </ul> <h2 id="http-响应剖析">HTTP 响应剖析</h2> <ul> <li>HTTP响应包括一个首部和一个体。</li> <li>首部信息告诉浏览器使用了什么协议,请求是否成功,以及体中包括何种类型的内容。</li> <li><p>体包含了让浏览器显示的具体内容。</p> <pre class="prettyprint"><code class="language-http hljs "><span class="hljs-status">HTTP/1.1 <span class="hljs-number">200</span> OK\r\n</span> <span class="hljs-attribute">Server</span>: <span class="hljs-string">nginx\r\n</span> <span class="hljs-attribute">Date</span>: <span class="hljs-string">Tue, 02 May 2017 13:01:11 GMT\r\n</span> <span class="hljs-attribute">Content-Type</span>: <span class="hljs-string">application/octet-stream\r\n</span> <span class="hljs-attribute">Content-Length</span>: <span class="hljs-string">160\r\n</span> <span class="hljs-attribute">Connection</span>: <span class="hljs-string">close\r\n</span> <span class="hljs-attribute">Cache-Control</span>: <span class="hljs-string">no-cache\r\n</span> <span class="hljs-attribute">pragma</span>: <span class="hljs-string">no-cache\r\n</span> \<span class="hljs-attribute">r\n [HTTP response 1/1] [Time since request</span>: <span class="hljs-string">0.117763000 seconds]</span> [<span class="hljs-attribute">Request in frame</span>: <span class="hljs-string">150745]</span></code></pre> <ul> <li><code>HTTP/1.1</code>:Web服务器使用的协议的版本</li> <li><code>200</code>:响应的HTTP状态码</li> <li><code>OK</code>:状态码的响应文本</li> <li><code>Content-Type: application/octet-stream</code>:MIME类型。MIME类型告诉浏览器要接收的数据是什么类型,这样浏览器才能知道如何显示这些数据。响应中必须有的一个首部。</li> <li><p>HTTP响应首部:</p> <pre class="prettyprint"><code class="language-http hljs "><span class="hljs-status">HTTP/1.1 <span class="hljs-number">200</span> OK\r\n</span> <span class="hljs-attribute">Server</span>: <span class="hljs-string">nginx\r\n</span> <span class="hljs-attribute">Date</span>: <span class="hljs-string">Tue, 02 May 2017 13:01:11 GMT\r\n</span> <span class="hljs-attribute">Content-Type</span>: <span class="hljs-string">application/octet-stream\r\n</span> <span class="hljs-attribute">Content-Length</span>: <span class="hljs-string">160\r\n</span> <span class="hljs-attribute">Connection</span>: <span class="hljs-string">close\r\n</span> <span class="hljs-attribute">Cache-Control</span>: <span class="hljs-string">no-cache\r\n</span> <span class="hljs-attribute">pragma</span>: <span class="hljs-string">no-cache\r\n</span></code></pre></li> <li><p>体:</p> <pre class="prettyprint"><code class="language-http; hljs json">[HTTP response <span class="hljs-number">1</span>/<span class="hljs-number">1</span>] [Time since request: <span class="hljs-number">0.117763000</span> seconds] [Request in frame: <span class="hljs-number">150745</span>]</code></pre></li> </ul></li> </ul> <h2 id="url">URL</h2> <pre class="prettyprint"><code class="language-http hljs "><span class="hljs-attribute">http://code.thunisoft.com:80/media/asr-server/blob/master/asrServer/readme/interface/接口文档.md</span></code></pre> <ul> <li><code>http://</code>:协议,告诉服务器使用什么通信协议。</li> <li><code>code.thunisoft.com</code>:服务器:所请求物理服务器的唯一名。这个名字映射到一个唯一的IP地址。IP地址是一个数字,形式为”xxx.yyy.zzz.aaa”。在这里也可以指定一个IP地址而不是服务器名,不过服务器名更容易记。</li> <li><code>80</code>:端口,URL的这一部分是可选的。一个服务器可以支持多个端口。一个服务器应用由端口标识。如果在URL中没有指定的端口,默认端口则是端口80,而且很幸运,这正是Web服务器的默认端口。</li> <li><code>media/asr-server/blob/master/asrServer/readme/interface/接口文档.md</code>:路径:所请求资源在服务器上的路径。</li> <li><code>接口文档.md</code>:所请求内容的名字。这一部分是可选的,如果没有这一部分,大多数Web服务器都会默认地查找index.html。</li> </ul> <h2 id="端口">端口</h2> <ul> <li>TCP端口只是一个数字而已。</li> <li>端口是一个16位数字,标识服务器硬件上一个特定的软件程序。</li> <li>端口并不表示一个可以插入物理设备的位置。它们只是表示服务器应用的“逻辑”数而已。</li> <li>从0~1023的TCP端口号已经保留,由一些众所周知的服务使用。你自己的定制服务器程序不要使用这些端口。</li> <li><p>常用服务器应用TCP端口号:</p> <table> <thead> <tr> <th>应用</th> <th>端口</th> </tr> </thead> <tbody> <tr> <td>FTP</td> <td>21</td> </tr> <tr> <td>Telnet</td> <td>23</td> </tr> <tr> <td>SMTP</td> <td>25</td> </tr> <tr> <td>Time</td> <td>37</td> </tr> <tr> <td>HTTP</td> <td>80</td> </tr> <tr> <td>POP3</td> <td>110</td> </tr> <tr> <td>HTTPS</td> <td>443</td> </tr> </tbody> </table> </li> </ul> <h2 id="静态页面与动态页面">静态页面与动态页面</h2> <ul> <li>Web服务器只能提供静态页面,静态页面只是原封不动地待在目录中。服务器找到静态页面,并把它原样传回给客户。每个客户看到的东西都一样。</li> <li>动态页面,或者叫即时页面,是由辅助应用产生的,产生后交给服务器,再由服务器交给客户。即时页面在请求到来之前并不存在,创建这样一个HTML页面就像是搭建一个“空中楼阁”。请求到来后,辅助应用“具体写出”HTML,Web服务器再把这个HTML交回给客户。</li> <li>辅助应用可以使CGI和Servlet。</li> </ul> <h2 id="我的第一个servlet">我的第一个Servlet</h2> <ul> <li><p>创建一个目录树:</p> <pre class="prettyprint"><code class="language-java hljs ">/project1 /src /classes /etc</code></pre></li> <li><p>编写一个Ch1Servlet.java的servlet,把它放在src目录中:</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">import</span> javax.servlet.*; <span class="hljs-keyword">import</span> javax.servlet.http.*; <span class="hljs-keyword">import</span> java.io.*; <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Ch1Servlet</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doGet</span>(HttpServletRequest req, HttpServletResponse resp) <span class="hljs-keyword">throws</span> IOException { PrintWriter out = resp.getWriter(); java.util.Date today = <span class="hljs-keyword">new</span> java.util.Date(); out.println(<span class="hljs-string">"<html>"</span> + <span class="hljs-string">"<body>"</span> + <span class="hljs-string">"<h1 align=center>HF\'s Chapter1 Servlet</h1>"</span> + <span class="hljs-string">"<br>"</span> + today + <span class="hljs-string">"</body>"</span> + <span class="hljs-string">"</html>"</span>); } }</code></pre></li> <li><p>创建一个部署文件(deployment descriptor,DD),名为web.xml,把它放在etc目录中。(可以从tomcat的例子中拷贝一份出来修改)</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-pi"><?xml version="1.0" encoding="ISO-8859-1"?></span> <span class="hljs-tag"><<span class="hljs-title">web-app</span> <span class="hljs-attribute">xmlns</span>=<span class="hljs-value">"http://xmlns.jcp.org/xml/ns/javaee"</span> <span class="hljs-attribute">xmlns:xsi</span>=<span class="hljs-value">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="hljs-attribute">xsi:schemaLocation</span>=<span class="hljs-value">"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"</span> <span class="hljs-attribute">version</span>=<span class="hljs-value">"3.1"</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>Chapter1 Servlet<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-class</span>></span>Ch1Servlet<span class="hljs-tag"></<span class="hljs-title">servlet-class</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-mapping</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>Chapter1 Servlet<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/Serv1<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet-mapping</span>></span> <span class="hljs-tag"></<span class="hljs-title">web-app</span>></span></code></pre></li> <li><p>在以后的Tomcat目录下建立这个目录树:</p> <pre class="prettyprint"><code class="language-java hljs ">/tomcat /webapps /ch1 /WEB-INF /classes</code></pre></li> <li><p>从project1目录编译servlet:</p> <pre class="prettyprint"><code class="language-shell hljs tex">javac -classpath "G:<span class="hljs-command">\Tomcat</span> 8.5<span class="hljs-command">\lib</span><span class="hljs-command">\servlet</span>-api.jar" -d classes src/Ch1Servlet.java</code></pre></li> <li><p>把Ch1Servlet.class文件复制到WEB-INF/classes,再把web.xml文件复制到WEB-INF。</p></li> <li>启动Tomcat</li> <li><p>打开浏览器,键入:</p> <pre class="prettyprint"><code class="language-http hljs "><span class="hljs-attribute">http://localhost:8080/ch1/Serv1</span></code></pre></li> <li><p>每次更新servlet类或部署文件都需要关闭Tomcat。</p></li> </ul> <h2 id="jsp">JSP</h2> <ul> <li>实际上,在servlet的out.println()里格式化HTML确实不太好。于是引入JSP。</li> <li>JSP页面就像是一个HTML页面,只不过可以把Java和与Java有关的东西放在这个页面中。</li> </ul> <h1 id="高层体系结构">高层体系结构</h1> <h2 id="什么是容器">什么是容器?</h2> <ul> <li>Servlet没有main()方法。它们受控于另一个Java应用,这个Java应用称为容器。Tomcat就是这样一个容器。如果Web服务器应用得到一个指向某sevlet的请求,此时服务器不是把这个请求给servlet本身,而是交给部署该servlet的容器。要由容器向servlet提供HTTP请求和相应,而且要由容器调用servlet的方法,如doPost()或doGet()。</li> </ul> <h2 id="容器能提供什么">容器能提供什么?</h2> <ul> <li>通信支持:利用容器提供的方法,你能轻松地让servlet与Web服务器对话。</li> <li>生命周期管理:容器控制着servlet的生与死。</li> <li>多线程支持:容器会自动地为它接收的每个servlet请求创建一个新的Java线程。</li> <li>声明方式实现安全:利用容器,可以使用XML部署描述文件来配置(和修改)安全性,而不必将其硬编码写到servlet类代码中。</li> <li>JSP支持。</li> </ul> <h2 id="容器如何处理请求">容器如何处理请求</h2> <ol> <li>用户点击一个链接,其URL指向一个servlet</li> <li>容器“看出来”这个请求要的是一个servlet,所以容器创建两个对象:HttpServletResponse,HttpServletRequest。</li> <li>容器根据请求中的URL找到正确的servlet,为这个请求创建或分配一个线程,并把请求和响应对象传递给这个servlet线程。</li> <li>容器调用servlet的service()方法。根据请求的不同类型,service()方法会调用doGet()或doPost()方法。</li> <li>doGet()或doPost()方法生成动态页面,并把这个页面“填入”响应对象。</li> <li>线程结束,容器把响应对象转换为一个HTTP响应,把它发回给客户,然后删除请求和响应对象。</li> </ol> <h2 id="代码里有什么">代码里有什么?</h2> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">import</span> javax.servlet.*; <span class="hljs-keyword">import</span> javax.servlet.http.*; <span class="hljs-keyword">import</span> java.io.*; <span class="hljs-comment">// 99.9999%的servlet都是HttpServlet</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Ch1Servlet</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> {</span> <span class="hljs-comment">// 在实际中,99.9%的servlet都会覆盖doGet()或doPost()方法</span> <span class="hljs-comment">// servlet从这里拿到容器创建的请求和响应对象的引用</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doGet</span>(HttpServletRequest req, HttpServletResponse resp) <span class="hljs-keyword">throws</span> IOException { <span class="hljs-comment">// 在servlet从容器得到的响应对象中,可以拿到一个PrintWriter。</span> <span class="hljs-comment">// 使用这个PrintWriter能够将HTML文本输出到响应对象</span> PrintWriter out = resp.getWriter(); java.util.Date today = <span class="hljs-keyword">new</span> java.util.Date(); out.println(<span class="hljs-string">"<html>"</span> + <span class="hljs-string">"<body>"</span> + <span class="hljs-string">"<h1 align=center>HF\'s Chapter1 Servlet</h1>"</span> + <span class="hljs-string">"<br>"</span> + today + <span class="hljs-string">"</body>"</span> + <span class="hljs-string">"</html>"</span>); } }</code></pre> <h2 id="一个servlet可以有3个名字">一个servlet可以有3个名字</h2> <ol> <li>URL名:客户看到HTML中对应一个servlet的URL。</li> <li>部署名:部署人员知道的秘密的内部名</li> <li>实际的文件名</li> </ol> <p>建立servlet名的映射,这有助于改善应用的灵活性和安全性。</p> <h2 id="使用部署描述文件将url映射到servlet">使用部署描述文件将URL映射到servlet</h2> <ul> <li><code><servlet></code>: 内部名映射到完全限定类名</li> <li><code><servlet-mapping></code>: 内部名映射到公共URL名</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-pi"><?xml version="1.0" encoding="ISO-8859-1"?></span> <span class="hljs-tag"><<span class="hljs-title">web-app</span> <span class="hljs-attribute">xmlns</span>=<span class="hljs-value">"http://xmlns.jcp.org/xml/ns/javaee"</span> <span class="hljs-attribute">xmlns:xsi</span>=<span class="hljs-value">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="hljs-attribute">xsi:schemaLocation</span>=<span class="hljs-value">"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"</span> <span class="hljs-attribute">version</span>=<span class="hljs-value">"3.1"</span>></span> <span class="hljs-comment"><!-- <servlet>元素告诉容器哪些类文件属于一个特定Web应用 --></span> <span class="hljs-tag"><<span class="hljs-title">servlet</span>></span> <span class="hljs-comment"><!-- <servlet-name>元素用于把一个<servlet>元素绑定到一个 特定的<servlet-mapping>元素。最终用户绝对看不到这个名, 这个名只在这个部署描述文件的其他部分中使用。 --></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>Chapter1 Servlet<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-comment"><!-- 在<servlet-class>里放置类的完全限定名(但是不要加".class"扩展名) --></span> <span class="hljs-tag"><<span class="hljs-title">servlet-class</span>></span>Ch1Servlet<span class="hljs-tag"></<span class="hljs-title">servlet-class</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet</span>></span> <span class="hljs-comment"><!-- <servlet-mapping>映射URL和servlet --></span> <span class="hljs-tag"><<span class="hljs-title">servlet-mapping</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>Chapter1 Servlet<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-comment"><!-- <url-pattern>里是客户看到(并使用)的servlet名。 这是一个虚构的名字,并不是具体servlet的名字 --></span> <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/Serv1<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet-mapping</span>></span> <span class="hljs-tag"></<span class="hljs-title">web-app</span>></span></code></pre> <ul> <li>还可以使用部署描述文件对Web应用的其他方面进行定制,包括安全角色,错误页面,标记库,初始配置信息等。</li> <li>部署描述文件(DD)提供了一种“声明”机制来定制Web应用,而无需修改源代码。</li> </ul> <h3 id="dd优点">DD优点</h3> <ul> <li>尽量少改动已经测试过的源代码。</li> <li>即使你手上并没有源代码,也可以对应用的功能进行调整。</li> <li>不用重新编译和测试任何代码,也可以让你的应用适应不同的资源。</li> <li>可以更容易地维护动态安全信息,如访问控制列表和安全角色。</li> <li>非程序员也可以修改和部署你的Web应用。</li> </ul> <h2 id="mvc">MVC</h2> <ul> <li>模型-视图-控制器(MVC)就是把业务逻辑从servlet中抽出来,把它放在一个“模型”中,所谓模型就是一个可重用的普通Java类。模型是业务数据(如购物车的状态)和处理该数据的方法(规则)的组合。</li> </ul> <h3 id="servlet-jsp世界汇总的mvc">Servlet & JSP世界汇总的MVC</h3> <ul> <li>控制器(Servlet):从请求获得用户输入,并明确这些输入对模型有什么影响。告诉模型自行更新,并且让视图(JSP)能得到新的模型状态。</li> <li>模型(Java类):包含具体的业务逻辑和状态。换句话说模型知道用什么规则来得到和更新状态。系统中只有这部分与数据库通信。</li> <li>视图(JSP):负责表示方面。它从控制器得到模型的状态(不过不是直接得到;控制器会把模型数据放在视图能找到的一个地方)。另外视图还要获得用户输入,并交给控制器。</li> </ul> <h2 id="要点">要点</h2> <ul> <li>容器为Web应用提供了通信支持、声明周期管理、多线程支持、声明方式安全,以及JSP支持。</li> <li>容器创建一个请求对象和一个响应对象,servlet可以用这些对象得到有关请求的信息,并把信息发送给客户。</li> <li>典型的servlet是一个扩展了HttpServlet的类,而且覆盖了一个或多个服务方法(doGet(),doPost()),分别对应于浏览器调用的HTTP方法。</li> <li>部署人员可以吧servlet类映射到一个URL,这样客户可以使用这个URL来请求该servlet。部署名可以与实际的类文件名完全不同。</li> </ul> <h2 id="j2ee">J2EE</h2> <ul> <li>J2EE应用服务器包括一个Web容器和一个EJB容器。Tomcat是一个Web容器,而不是一个完整的J2EE应用服务器。</li> </ul> <h1 id="mvc实战">MVC实战</h1> <h2 id="构建一个真正的小web应用">构建一个真正的(小)Web应用</h2> <h3 id="四大步骤">四大步骤</h3> <ol> <li>分析用户的视图,以及高层体系结构。</li> <li>创建用于开发这个项目的开发环境。</li> <li>创建用于部署这个项目的部署环境。</li> <li>对Web应用的各个组件完成迭代式的开发和测试。</li> </ol> <h2 id="啤酒顾问">啤酒顾问</h2> <h3 id="场景">场景</h3> <ul> <li>我们的Web应用是一个啤酒顾问。用户访问这个应用,先问一个问题,然后会得到一条有用的啤酒建议。</li> </ul> <h3 id="开发流程">开发流程</h3> <h4 id="第一步-分析用户的视图以及高层体系结构">第一步 分析用户的视图,以及高层体系结构</h4> <ul> <li>啤酒顾问有两个页面: <br> <ol> <li>HTML页面,用户选择页面,生成HTTP POST请求,并把用户的颜色选择作为一个参数发送。</li> <li>JSP页面,基于用户的选择给出建议。</li> </ol></li> <li>体系结构 <br> <ol> <li>客户请求得到form.html页面。</li> <li>容器找到并获得form.html页面。</li> <li>容器把这个页面返回给浏览器,用户再在浏览器上回答表单上的问题。</li> <li>浏览器把请求数据发送给容器。</li> <li>容器根据URL查找正确的servlet,并把请求传递给这个servlet。</li> <li>servlet调用BeerExpert寻求帮助。</li> <li>这个“专家”类返回一个回答,servlet把这个回答增加到请求对象。</li> <li>servlet把请求转发给JSP。</li> <li>JSP从请求对象得到回答。</li> <li>JSP为容器生成一个页面。</li> <li>容器把这个页面返回给心满意足的用户。</li> </ol></li> </ul> <h4 id="第二步-创建用于开发这个项目的开发环境">第二步 创建用于开发这个项目的开发环境</h4> <pre class="prettyprint"><code class="language-shell hljs avrasm">/projects /web /beerV1 /etc web<span class="hljs-preprocessor">.xml</span> -- 配置文件 /lib -- 在这里放第三方JAR文件 /src -- 所有Java代码都放在src目录下 /<span class="hljs-keyword">com</span> /cynhard /web -- 在这里放控制组件 BeerSelect<span class="hljs-preprocessor">.java</span> /model -- 在这里放模型组件 BeerExpert<span class="hljs-preprocessor">.java</span> /classes -- 与src对应,放置相应的<span class="hljs-preprocessor">.class</span>文件 /<span class="hljs-keyword">com</span> /cynhard /web BeerSelect<span class="hljs-preprocessor">.class</span> /model BeerExpert<span class="hljs-preprocessor">.class</span> /web -- 静态和动态视图组件放在这里 result<span class="hljs-preprocessor">.jsp</span> form<span class="hljs-preprocessor">.html</span></code></pre> <h4 id="第三步-创建用于部署这个项目的部署环境">第三步 创建用于部署这个项目的部署环境</h4> <pre class="prettyprint"><code class="language-shell hljs brainfuck"><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">特定于Tomcat的部分</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">/Tomcat</span> <span class="hljs-comment">8</span><span class="hljs-string">.</span><span class="hljs-comment">5</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">Tomcat主目录</span> <span class="hljs-comment">/webapps</span> <span class="hljs-comment">/Beer</span><span class="hljs-literal">-</span><span class="hljs-comment">v1</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">Web应用的名字,在Tomcat解析URL是用到。</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">Servlet规范的部分</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">form</span><span class="hljs-string">.</span><span class="hljs-comment">html</span> <span class="hljs-comment">result</span><span class="hljs-string">.</span><span class="hljs-comment">jsp</span> <span class="hljs-comment">/WEB</span><span class="hljs-literal">-</span><span class="hljs-comment">INF</span> <span class="hljs-comment">web</span><span class="hljs-string">.</span><span class="hljs-comment">xml</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">必须放在WEB</span><span class="hljs-literal">-</span><span class="hljs-comment">INF中</span> <span class="hljs-comment">/lib</span> <span class="hljs-comment">/classes</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">特定于应用的部分</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">/com</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span> <span class="hljs-comment">这个包结构与开发环境中使用的结构完全相同</span> <span class="hljs-comment">/cynhard</span> <span class="hljs-comment">/web</span> <span class="hljs-comment">BeerSelect</span><span class="hljs-string">.</span><span class="hljs-comment">class</span> <span class="hljs-comment">/model</span> <span class="hljs-comment">BeerExpert</span><span class="hljs-string">.</span><span class="hljs-comment">class</span></code></pre> <h4 id="第四步-对web应用的各个组件完成迭代式的开发和测试">第四步 对Web应用的各个组件完成迭代式的开发和测试</h4> <ul> <li>这一步又分为5个小步骤: <br> <ul> <li>4.1 构建和测试用户最初请求的HTML表单。</li> <li>4.2 构建控制器servlet的第一个版本,并用HTML表单测试这个控制器。</li> <li>4.3 为专家/模型类构建一个测试类,然后构建并测试专家/模型类本身。</li> <li>4.4 把servlet升级到第2版。这个版本增加了一个功能,可以调用模型类来得到啤酒建议。</li> <li>4.5 构建JSP,把servlet升级到第3版本(再增加一个功能,可以把表示分派到JSP完成),然后再测试整个应用。</li> </ul></li> </ul> <h5 id="41-构建和测试用户最初请求的html表单">4.1 构建和测试用户最初请求的HTML表单</h5> <ul> <li><p>4.1.1 编写开始页面</p> <pre class="prettyprint"><code class="language-html hljs "><span class="hljs-tag"><<span class="hljs-title">html</span>></span> <span class="hljs-tag"><<span class="hljs-title">body</span>></span> <span class="hljs-tag"><<span class="hljs-title">h1</span> <span class="hljs-attribute">align</span>=<span class="hljs-value">"center"</span>></span>Beer Selection Page<span class="hljs-tag"></<span class="hljs-title">h1</span>></span> <span class="hljs-tag"><<span class="hljs-title">form</span> <span class="hljs-attribute">method</span>=<span class="hljs-value">"POST"</span> <span class="hljs-attribute">action</span>=<span class="hljs-value">"SelectBeer.do"</span>></span> Select beer characteristics<span class="hljs-tag"><<span class="hljs-title">p</span>></span> Color: <span class="hljs-comment"><!-- size表示下拉类表中可见选项的数目 --></span> <span class="hljs-tag"><<span class="hljs-title">select</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"color"</span> <span class="hljs-attribute">size</span>=<span class="hljs-value">"1"</span>></span> <span class="hljs-tag"><<span class="hljs-title">option</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"light"</span>></span> light <span class="hljs-tag"></<span class="hljs-title">option</span>></span> <span class="hljs-tag"><<span class="hljs-title">option</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"amber"</span>></span> amber <span class="hljs-tag"></<span class="hljs-title">option</span>></span> <span class="hljs-tag"><<span class="hljs-title">option</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"brown"</span>></span> brown <span class="hljs-tag"></<span class="hljs-title">option</span>></span> <span class="hljs-tag"><<span class="hljs-title">option</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"dark"</span>></span> dark <span class="hljs-tag"></<span class="hljs-title">option</span>></span> <span class="hljs-tag"></<span class="hljs-title">select</span>></span> <span class="hljs-tag"><<span class="hljs-title">br</span>></span><span class="hljs-tag"><<span class="hljs-title">br</span>></span> <span class="hljs-tag"><<span class="hljs-title">center</span>></span> <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"SUBMIT"</span>></span> <span class="hljs-tag"></<span class="hljs-title">center</span>></span> <span class="hljs-tag"></<span class="hljs-title">form</span>></span> <span class="hljs-tag"></<span class="hljs-title">body</span>></span> <span class="hljs-tag"></<span class="hljs-title">html</span>></span></code></pre></li> <li><p>4.1.2 部署和测试开始页面</p> <ol> <li>在开发环境中创建HTML。将上面的HTML页面保存到开发环境中的 /beerV1/web/form.html文件中。</li> <li>把这个文件复制到部署环境:/webapps/Beer-v1/form.html。</li> <li><p>在开发环境中创建DD,保存到开发环境中的 /beerV1/etc/web.xml中。</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-pi"><?xml version="1.0" encoding="ISO-8859-1"?></span> <span class="hljs-tag"><<span class="hljs-title">web-app</span> <span class="hljs-attribute">xmlns</span>=<span class="hljs-value">"http://xmlns.jcp.org/xml/ns/javaee"</span> <span class="hljs-attribute">xmlns:xsi</span>=<span class="hljs-value">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="hljs-attribute">xsi:schemaLocation</span>=<span class="hljs-value">"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"</span> <span class="hljs-attribute">version</span>=<span class="hljs-value">"3.1"</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>Ch3 Beer<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-class</span>></span>com.cynhard.web.BeerSelect<span class="hljs-tag"></<span class="hljs-title">servlet-class</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-mapping</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>Ch3 Beer<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/SelectBeer.do<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet-mapping</span>></span> <span class="hljs-tag"></<span class="hljs-title">web-app</span>></span></code></pre></li> <li><p>把DD文件拷贝到部署环境:/webapps/Beer-v1/WEB-INF/web.xml。</p></li> <li>启动Tomcat。</li> <li>测试页面。在浏览器输入:<code>http://localhost:8080/Beer-v1/form.html</code>。</li> </ol></li> </ul> <h5 id="42-构建控制器servlet的第一个版本并用html表单测试这个控制器">4.2 构建控制器servlet的第一个版本,并用HTML表单测试这个控制器</h5> <ul> <li><p>4.2.1 控制器servlet的第1版</p> <ul> <li>第一版只要确保HTML页面能适当的调用servlet,而且servlet能正确的接收HTML参数就可以了。</li> <li><p>在开发环境的src/com/cynhard/web目录下创建BeerSelect.java,内容如下:</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.cynhard.web; <span class="hljs-comment">// 确保与前面创建的开发结构和部署结构匹配</span> <span class="hljs-keyword">import</span> javax.servlet.*; <span class="hljs-keyword">import</span> javax.servlet.http.*; <span class="hljs-keyword">import</span> java.io.*; <span class="hljs-comment">// HttpServlet扩展了GenericSevlet,GenericServlet则实现了Servlet接口</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BeerSelect</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> {</span> <span class="hljs-comment">// 我们使用doPost来处理HTTP请求,因为HTTP表单指出:method=POST</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doPost</span>(HttpServletRequest request, HttpServletResponse response) <span class="hljs-keyword">throws</span> IOException { response.setContentType(<span class="hljs-string">"text/html"</span>); PrintWriter out = response.getWriter(); out.println(<span class="hljs-string">"Beer Selection Advice<br>"</span>); String c = request.getParameter(<span class="hljs-string">"color"</span>); out.println(<span class="hljs-string">"<br>Got beer color "</span> + c); } }</code></pre></li> </ul></li> <li><p>4.2.2 编译、部署和测试控制器servlet</p> <ul> <li><p>编译servlet</p> <pre class="prettyprint"><code class="language-shell hljs tex">javac -classpath "G:<span class="hljs-command">\Tomcat</span> 8.5<span class="hljs-command">\lib</span><span class="hljs-command">\servlet</span>-api.jar";classes;. -d classes src<span class="hljs-command">\com</span><span class="hljs-command">\cynhard</span><span class="hljs-command">\web</span><span class="hljs-command">\BeerSelect</span>.java</code></pre> <p><code>-d</code> 选项告诉编译器,把.class文件放在适当包结构中的classes目录下。</p></li> <li><p>部署servlet <br> 将开发环境的<code>BeerSelect.class</code>拷贝到部署环境中: <code>webapps/Beer-v1/WEB-INF/classes/com/cynhard/web/BeerSelect.class</code></p></li> <li><p>测试servlet</p> <ul> <li>重启tomcat</li> <li>浏览器中输入:<code>http://localhost:8080/Beer-v1/form.html</code></li> <li>选择一种啤酒颜色,提交。</li> <li>如果servlet正常运行,就会在浏览器中看到结果。</li> </ul></li> </ul></li> </ul> <h5 id="43-为专家模型类构建一个测试类然后构建并测试专家模型类本身">4.3 为专家/模型类构建一个测试类,然后构建并测试专家/模型类本身</h5> <ul> <li>4.3.1 模型规范 <br> <ul> <li>包应当是 com.example.model。</li> <li>其目录结构应当是 /WEB-INF/classes/com/model。</li> </ul></li> <li>4.3.2 为模型构建测试类 <br> <ul> <li>略</li> </ul></li> <li><p>4.3.3 构建和测试模型</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.cynhard.model; <span class="hljs-keyword">import</span> java.util.*; <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BeerExpert</span> {</span> <span class="hljs-keyword">public</span> List <span class="hljs-title">getBrands</span>(String color) { List<String> brands = <span class="hljs-keyword">new</span> ArrayList<String>(); <span class="hljs-keyword">if</span> (color.equals(<span class="hljs-string">"amber"</span>)) { brands.add(<span class="hljs-string">"Jack Amber"</span>); brands.add(<span class="hljs-string">"Red Moose"</span>); } <span class="hljs-keyword">else</span> { brands.add(<span class="hljs-string">"Jail Pale Ale"</span>); brands.add(<span class="hljs-string">"Gout Stout"</span>); } <span class="hljs-keyword">return</span> brands; } }</code></pre> <p>编译 :</p> <pre class="prettyprint"><code class=" hljs tex">javac -d classes -Xlint:unchecked src<span class="hljs-command">\com</span><span class="hljs-command">\cynhard</span><span class="hljs-command">\model</span><span class="hljs-command">\BeerExpert</span>.java</code></pre> <p>将边编译后的BeerExpert.class放到部署目录:</p> <pre class="prettyprint"><code class=" hljs tex"><span class="hljs-command">\webapps</span><span class="hljs-command">\Beer</span>-v1<span class="hljs-command">\WEB</span>-INF<span class="hljs-command">\classes</span><span class="hljs-command">\com</span><span class="hljs-command">\cynhard</span><span class="hljs-command">\model</span></code></pre></li> </ul> <h5 id="44-把servlet升级到第2版调用模型类">4.4 把servlet升级到第2版,调用模型类</h5> <ul> <li><p>第2版servlet代码</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.cynhard.web; <span class="hljs-keyword">import</span> com.cynhard.model.*; <span class="hljs-keyword">import</span> javax.servlet.*; <span class="hljs-keyword">import</span> javax.servlet.http.*; <span class="hljs-keyword">import</span> java.io.*; <span class="hljs-keyword">import</span> java.util.*; <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BeerSelect</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doPost</span>(HttpServletRequest request, HttpServletResponse response) <span class="hljs-keyword">throws</span> IOException { String c = request.getParameter(<span class="hljs-string">"color"</span>); <span class="hljs-comment">// 实例化BeerExpert类,调用getBrands()</span> BeerExpert be = <span class="hljs-keyword">new</span> BeerExpert(); List result = be.getBrands(c); response.setContentType(<span class="hljs-string">"text/html"</span>); PrintWriter out = response.getWriter(); out.println(<span class="hljs-string">"Beer Selection Advice<br>"</span>); <span class="hljs-comment">// 打印建议</span> Iterator it = result.iterator(); <span class="hljs-keyword">while</span> (it.hasNext()) { out.print(<span class="hljs-string">"<br>try: "</span> + it.next()); } } }</code></pre></li> <li><p>编译:</p> <pre class="prettyprint"><code class="language-shell hljs tex">javac -classpath "G:<span class="hljs-command">\Tomcat</span> 8.5<span class="hljs-command">\lib</span><span class="hljs-command">\servlet</span>-api.jar";classes;. -d classes src<span class="hljs-command">\com</span><span class="hljs-command">\cynhard</span><span class="hljs-command">\web</span><span class="hljs-command">\BeerSelect</span>.java</code></pre></li> <li><p>部署和测试</p> <ul> <li><p>将编译的.class文件复制到部署环境:</p> <pre class="prettyprint"><code class="language-shell hljs tex"><span class="hljs-command">\webapps</span><span class="hljs-command">\Beer</span>-v1<span class="hljs-command">\WEB</span>-INF<span class="hljs-command">\classes</span><span class="hljs-command">\com</span><span class="hljs-command">\cynhard</span><span class="hljs-command">\web</span></code></pre></li> <li>重启tomcat。</li> <li>重新打开页面。</li> </ul></li> </ul> <h5 id="45-构建jsp把servlet升级到第3版本">4.5 构建JSP,把servlet升级到第3版本</h5> <ul> <li><p>4.5.1 新建JSP,保存在开发环境下:<code>\beerV1\web\result.jsp</code>。</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-comment"><!-- 这是一个“页面指令” --></span> <span class="vbscript"><%@ page import=<span class="hljs-string">"java.util.*"</span> %></span> <span class="hljs-tag"><<span class="hljs-title">html</span>></span> <span class="hljs-tag"><<span class="hljs-title">body</span>></span> <span class="hljs-tag"><<span class="hljs-title">h1</span> <span class="hljs-attribute">align</span>=<span class="hljs-value">"center"</span>></span>Beer Recommendations JSP<span class="hljs-tag"></<span class="hljs-title">h1</span>></span> <span class="hljs-tag"><<span class="hljs-title">p</span>></span> <span class="hljs-comment"><!-- <% %> 标记里有一些标准Java代码(这称为scriptlet) --></span> <span class="vbscript"><% List styles = (List)<span class="hljs-built_in">request</span>.getAttribute(<span class="hljs-string">"styles"</span>); Iterator it = styles.iterator(); <span class="hljs-keyword">while</span> (it.hasNext()) { out.print(<span class="hljs-string">"<br>try: "</span> + it.<span class="hljs-keyword">next</span>()); } %></span> <span class="hljs-tag"></<span class="hljs-title">body</span>></span> <span class="hljs-tag"></<span class="hljs-title">html</span>></span></code></pre> <p>将其拷贝到部署目录</p> <pre class="prettyprint"><code class="language-shell hljs tex"><span class="hljs-command">\webapps</span><span class="hljs-command">\Beer</span>-v1</code></pre></li> <li><p>4.5.2 改进servelt,调用JSP</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.cynhard.web; <span class="hljs-keyword">import</span> com.cynhard.model.*; <span class="hljs-keyword">import</span> javax.servlet.*; <span class="hljs-keyword">import</span> javax.servlet.http.*; <span class="hljs-keyword">import</span> java.io.*; <span class="hljs-keyword">import</span> java.util.*; <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BeerSelect</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doPost</span>(HttpServletRequest request, HttpServletResponse response) <span class="hljs-keyword">throws</span> IOException, ServletException { String c = request.getParameter(<span class="hljs-string">"color"</span>); <span class="hljs-comment">// 实例化BeerExpert类,调用getBrands()</span> BeerExpert be = <span class="hljs-keyword">new</span> BeerExpert(); List result = be.getBrands(c); <span class="hljs-comment">// 为请求对象增加一个属性,供JSP使用。</span> request.setAttribute(<span class="hljs-string">"styles"</span>, result); <span class="hljs-comment">// 为JSP实例化一个请求分派器。</span> RequestDispatcher view = request.getRequestDispatcher(<span class="hljs-string">"result.jsp"</span>); <span class="hljs-comment">// 使用请求分派器要求容器准备好JSP,并向JSP发送请求和响应。</span> view.forward(request, response); } }</code></pre> <p>编译、部署和测试:和之前的一样,这里略过。</p></li> </ul> <h1 id="请求和响应">请求和响应</h1> <h2 id="servlet的生命周期">servlet的生命周期</h2> <ul> <li><p>时序图</p> <div class="sequence-diagram"> Created with Raphaël 2.1.2 Web容器 Web容器 Servlet类 Servlet类 Servlet对象 Servlet对象 加载类 初始化servlet(构造函数运行) init() service() 处理客户请求(doGet(),doPost()) destory() </div></li> <li><p>声明周期中的三大重要时刻</p> <table> <thead> <tr> <th>方法</th> <th>何时调用</th> <th>作用</th> <th>是否覆盖</th> </tr> </thead> <tbody> <tr> <td>init()</td> <td>servlet实例创建后,并在<br>servlet能为客户请求提供<br>服务之前,容器对servlet<br>调用init()。</td> <td>使你在sevlet处理客户请求<br>之前有机会对其初始化。</td> <td>有可能。</td> </tr> <tr> <td>service()</td> <td>客户请求到来时,容器会<br>开始或分配一个新线程,<br>调用service()。</td> <td>查看请求类型,决定调用<br>doGet()或者doPost()。</td> <td>不需要。</td> </tr> <tr> <td>doGet()和/或doPost()</td> <td>service()根据请求的HTTP<br>方法调用doGet()或doPost()</td> <td>在这里写业务逻辑代码。</td> <td>至少覆盖其一。</td> </tr> </tbody> </table> </li> <li><p>service()方法总是在自己的栈中调用。容器运行多个线程来处理对一个servlet的多个请求。</p></li> </ul> <h2 id="init">init()</h2> <ul> <li>init()总是在第一个service()调用之前完成。 <br> <ul> <li>容器启动时找到servlet类文件。</li> <li>容器启动时或第一个请求到来时时加载servlet类。</li> <li>只有初始化之后才会调用service()。</li> </ul></li> <li>init()使一个普通对象变成servlet。</li> <li>init()之前容器产生ServletConfig对象和ServletContext对象,可以在init()中访问这些对象。</li> </ul> <h3 id="servletconfig对象">ServletConfig对象</h3> <ul> <li>每个servlet都有一个ServletConfig对象</li> <li>用于向servlet传递部署时信息。</li> <li>用于访问ServletContent。</li> <li>参数在部署描述文件中配置。</li> </ul> <h3 id="servletcontext对象">ServletContext对象</h3> <ul> <li>每个Web应用有一个ServletContent对象。</li> <li>用于访问Web应用参数。</li> <li>相当于一种应用公告栏,可以在这里放置消息,应用的其他部分可以访问这些消息。</li> <li>用于得到服务器信息,包括容器名和容器版本,以及所支持的API的版本等。</li> </ul> <h2 id="servicedogetdopost">service(),doGet(),doPost()</h2> <ul> <li>HTTP请求方法确定究竟运行doGet()还是doPost()。</li> </ul> <h3 id="get和post的区别">GET和POST的区别</h3> <ul> <li>POST有一个体。参数显示在体里,长度不受限制。GET参数显示在请求的URL后面,有长度限制。</li> <li>GET请求可以建立书签,POST不能。</li> <li>GET用于得到东西。POST用来修改服务器上的某些东西。</li> <li>幂等:任意多次执行所产生的影响均与一次执行的影响相同。GET是幂等的,POST不是幂等的。</li> </ul> <h3 id="如何确定浏览器发送的是get还是post">如何确定浏览器发送的是GET还是POST</h3> <ul> <li>超链接是GET</li> <li>form中<code>method="POST"</code> 是POST,method=”GET”或者没有method都是GET。</li> </ul> <h3 id="httpservletrequest">HttpServletRequest</h3> <ul> <li><p>获取参数</p> <ul> <li><p>获取单个参数:</p> <pre class="prettyprint"><code class="language-java hljs ">String param1 = request.getParameter(<span class="hljs-string">"param1"</span>); String param2 = request.getParameter(<span class="hljs-string">"param2"</span>);</code></pre></li> <li><p>如果参数是数组:</p> <pre class="prettyprint"><code class="language-java hljs ">String[] param = request.getParameterValues(<span class="hljs-string">"param"</span>)</code></pre></li> </ul></li> <li><p>客户的平台和浏览器信息</p> <pre class="prettyprint"><code class="language-java hljs ">String client = request.getHeader(<span class="hljs-string">"User-Agent"</span>);</code></pre></li> <li><p>与请求相关的cookie</p> <pre class="prettyprint"><code class="language-java hljs ">Cookie[] cookies = request.getCookies();</code></pre></li> <li><p>与客户相关的会话(session)</p> <pre class="prettyprint"><code class="language-java hljs ">HttpSession session = request.getSession();</code></pre></li> <li><p>请求的HTTP方法</p> <pre class="prettyprint"><code class="language-java hljs ">String method = request.getMethod();</code></pre></li> <li><p>请求的输入流</p> <pre class="prettyprint"><code class="language-java hljs ">InputStream input = request.getInputStream();</code></pre></li> </ul> <h3 id="httpservletresponse">HttpServletResponse</h3> <ul> <li>大多数情况下,使用响应只是为了向客户发回数据。会对响应调用两个方法:setContentType()和getWriter()。在此之后,只需要完成I/O将HTML(或其他内容)写至流。不过你也可以使用响应设置其他首部、发送错误,以及增加cookie。</li> <li>response.setContentType()指定MIME类型。内容类型是HTTP响应中必须有的一个HTTP首部。</li> <li><p>可以用PrintWriter对象或OutputStream对象输出数据,PrintWriter是对OutputStream的封装,用来写入文本数据。OutputStream用来写入二进制数据。PrintWriter通过getWriter()方法得到。OutputStream对象由getOutputStream()方法得到:</p> <pre class="prettyprint"><code class="language-java hljs ">PrintWriter writer = response.getWriter(); OutputStream out = response.getOutputStream();</code></pre></li> <li><p>setHeader()设置响应头部,addHeader()增加响应头部。setHeader()会覆盖现有的值。addHeader()会增加另外一个值。</p></li> </ul> <h4 id="重定向">重定向</h4> <ul> <li>通过sendRedirect()重定向。重定向交给浏览器请求重定向的URL。</li> <li><p>重定向是一个字符串,如果不以/开头,则重定向以当前目录为基路径。如果以<code>/</code>开头,则重定向以Web应用为基路径。</p> <ul> <li>不以<code>/</code>开头</li> </ul> <div class="flow-chart"> Created with Raphaël 2.1.2 开始 原始URL: http://www.cynhard.com/myApp/cool/bar.do 重定向:sendRedirect("foo/stuff.html") 结果: http://www.cynhard.com/myApp/cool/foo/stuff.html End </div> <ul> <li>以<code>/</code>开头</li> </ul> <div class="flow-chart"> Created with Raphaël 2.1.2 开始 原始URL: http://www.cynhard.com/myApp/cool/bar.do 重定向:sendRedirect("/foo/stuff.html") 结果: http://www.cynhard.com/foo/stuff.html End </div></li> <li><p>不能在写到响应之后再调用sendRedirect()。</p></li> </ul> <h4 id="请求分派">请求分派</h4> <ul> <li><p>请求分派交给服务器上的其他部分处理。</p> <pre class="prettyprint"><code class="language-java hljs ">RequestDispatcher view = request.getRequestDispatcher(<span class="hljs-string">"result.jsp"</span>); view.forward(request, response);</code></pre></li> </ul> <h2 id="复习servlet声明周期和api">复习:servlet声明周期和API</h2> <ul> <li>容器要加载类、调用servlet的无参构造函数,并调用servlet的init()方法,从而初始化servlet。</li> <li>init()方法在servlet一生中只调用一次,往往在servlet为客户请求提供服务器之前调用。</li> <li>init()方法使servlet可以访问ServletConfig和ServletContent对象,servlet需要从这些对象得到有关servlet配置和web应用的信息。</li> <li>容器通过调用servlet的destory()方法来结束servlet的生命。</li> <li>servlet一生的大多数时间都是为某个客户请求运行service()方法。</li> <li>对servlet的每个请求都在一个单独的线程中运行!任何特定servlet类都只有一个实例。</li> <li>你的servlet类一般都会扩展javax.servlet.http.HttpServlet,并由此继承service()方法中的一个实现,它取一个HttpServletRequest和一个HttpServletResponse作为参数。</li> <li>HttpServlet扩展了javax.servlet.GenericServlet,这是一个抽象类,实现了大多数基本servlet方法。</li> <li>GenericServlet实现了Servlet接口。</li> <li>Servlet相关的类都在以下两个包中:javax.servlet或javax.servlet.http。</li> <li>可以覆盖init()方法,而且必须覆盖一个服务方法(doGet()、doPost()等)。</li> </ul> <h2 id="复习http和httpservletrequest">复习:HTTP和HttpServletRequest</h2> <ul> <li>HttpServlet的doGet()和doPost()方法取一个HttpServletRequest和一个HttpServletResponse作为参数。</li> <li>service()方法根据HTTP请求的HTTP方法(GET、POST等)来确定运行doGet()还是doPost()。</li> <li>POST请求有一个体;GET请求没有,不过GET请求可以把请求参数追加到请求URL的后面(有时成为“查询串”)。</li> <li>GET请求本质上讲(根据HTTP规范)是幂等的。它们应当能多次运行而不会对服务器产生任何副作用。GET请求不应修改服务器上的任何东西。但是你也可以写一个非幂等的doGet()方法(不过这是很糟糕的做法)。</li> <li>POST本质上讲不是幂等的,所以要由你来适当地设计和编写代码,如果客户错误地把一个请求发送了两次,你也能正确地加以处理。</li> <li>如果HTML表单没有明确地指出“method=POST”,请求就会作为一个GET请求发送,而不是POST请求。如果你的servlet中没有doGet(),这个请求就会失败。</li> <li>可以用getParameter(“paramname”)方法从请求得到参数。返回值总是一个String。</li> <li>如果对应一个给定的参数名有多个参数值,要使用getParameterValues(“paramname”)方法来返回一个String数组。</li> <li>从请求对象还可以得到其他东西,包括首部、cookie、会话、查询串和输入流。</li> </ul> <h2 id="复习httpservletresponse">复习:HttpServletResponse</h2> <ul> <li>使用响应向客户发回数据。</li> <li>对响应对象(HttpServletResponse)调用的最常用的方法是setContentType()和getWriter()。</li> <li>要当心——很多开发人员都认为应该是getPrintWriter(),但实际上得到书写器的方法是getWriter()。</li> <li>利用getWriter()方法可以完成字符I/O,想流写入HTML(或其他内容)。</li> <li>还可以使用响应来设置首部、发送错误,以及增加cookie。</li> <li>在实际中,可能会使用JSP发送大多数HTML响应,但仍有可能使用一个响应流向客户发送二进制数据(如JAR文件)。</li> <li>要得到二进制流,需要在响应上调用getOutputStream()。</li> <li>setContentType()方法告诉浏览器如何处理随响应到来的数据。常见的内容类型为”text/html”、”application/pdf”和”image/jpeg”。</li> <li>不用记住内容类型(也称为MIME类型)。</li> <li>可以使用addHeader()或setHeader()设置响应首部。二者区别是这个首部是否已经是相应的一部分。如果是,setHeader()会替换原来的值,而addHeader()会向现有的响应增加另一个值。如果响应中原来没有这个首部,setHeader()和addHeader()的表现完全一样。</li> <li>如果你不想对一个请求做出响应,可以把请求重定向到另一个URL。浏览器会负责把新请求发送到你提供的URL。</li> <li>要重定向一个请求,需要在响应上调用sendRedirect(aStringURL)。</li> <li>不能在响应已经提交之后才调用sendRedirect()!换句话说,如果已经向流中写入了东西,再想重定向则为时已晚。</li> <li>请求重定向与请求分派完全是两码事。请求分派在服务器端发生,而重定向在客户端进行。请求分派吧请求传递给服务器上的另一个组件(通常在同一个Web应用中)。请求重定向只是告诉浏览器去访问另一个URL。</li> </ul> <h1 id="属性和监听者">属性和监听者</h1> <h2 id="servletconfig">ServletConfig</h2> <ul> <li><p>Servlet初始化参数:</p> <ul> <li><p>在DD文件中:</p> <pre class="prettyprint"><code class="language-xml hljs "> <span class="hljs-tag"><<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>Ch3 Beer<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-class</span>></span>com.cynhard.web.BeerSelect<span class="hljs-tag"></<span class="hljs-title">servlet-class</span>></span> <span class="hljs-tag"><<span class="hljs-title">init-param</span>></span> <span class="hljs-tag"><<span class="hljs-title">param-name</span>></span>myEmail<span class="hljs-tag"></<span class="hljs-title">param-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">param-value</span>></span>cynhard85@126.com<span class="hljs-tag"></<span class="hljs-title">param-value</span>></span> <span class="hljs-tag"></<span class="hljs-title">init-param</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet</span>></span></code></pre></li> <li><p>在servlet代码中:</p> <pre class="prettyprint"><code class="language-java hljs ">writer.println(getServletConfig().getInitParameter(<span class="hljs-string">"myEmail"</span>));</code></pre></li> </ul></li> <li><p>在servlet初始化之前不能使用servlet初始化参数。</p></li> <li>容器初始化一个servlet时,会为这个servlet建一个唯一的ServletConfig。容器从DD“读出”servlet初始化参数交给ServletConfig,然后把ServletConfig传递给servlet的init()方法。</li> <li>servlet初始化参数只能读一次——就是在容器初始化servlet的时候。</li> </ul> <h2 id="servletcontext">ServletContext</h2> <ul> <li><p>上下文初始化参数</p> <ul> <li><p>DD中:</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>Ch3 Beer<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-class</span>></span>com.cynhard.web.BeerSelect<span class="hljs-tag"></<span class="hljs-title">servlet-class</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">context-param</span>></span> <span class="hljs-tag"><<span class="hljs-title">param-name</span>></span>myEmail<span class="hljs-tag"></<span class="hljs-title">param-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">param-value</span>></span>cynhard85@126.com<span class="hljs-tag"></<span class="hljs-title">param-value</span>></span> <span class="hljs-tag"></<span class="hljs-title">context-param</span>></span></code></pre></li> <li><p>Servlet中:</p> <pre class="prettyprint"><code class="language-java hljs ">out.println(getServletContext().getInitParameter(<span class="hljs-string">"myEmail"</span>));</code></pre></li> </ul></li> <li><p><code><context-param></code>是针对整个应用的,因此放在所有<code><servlet></code>之外。</p></li> <li>上下文是针对整个应用的,因此所有servlet和JSP都可以访问。</li> <li>每个servlet有一个ServletConfig,每个Web应用有一个ServletContext。</li> <li>在分布式引用中,每个JVM有一个ServletConfig。</li> <li>要把初始化参数认为是部署时常量!可以在运行时得到这些初始化参数,但是不能设置。</li> </ul> <h2 id="servletcontextlistener">ServletContextListener</h2> <ul> <li><p>ServletContextListener使用</p> <ul> <li><p>listener 代码:</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> com.cynhard.web; <span class="hljs-keyword">import</span> javax.servlet.*; <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyServletContextListener</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ServletContextListener</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">contextInitialized</span>(ServletContextEvent event) { ServletContext sc = event.getServletContext(); <span class="hljs-comment">// ...</span> } <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">contextDestroyed</span>(ServletContextEvent event) { <span class="hljs-comment">// ...</span> } }</code></pre></li> <li><p>DD:</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">listener</span>></span> <span class="hljs-tag"><<span class="hljs-title">listener-class</span>></span> com.cynhard.MyServletContextListener <span class="hljs-tag"></<span class="hljs-title">listener-class</span>></span> <span class="hljs-tag"></<span class="hljs-title">listener</span>></span></code></pre></li> </ul></li> <li><p><code><listener></code>不放在<code><servlet></code>元素内部。</p></li> </ul> <h2 id="8个监听者">8个监听者</h2> <table> <thead> <tr> <th>场景</th> <th>监听者</th> <th>事件类型</th> </tr> </thead> <tbody> <tr> <td>你想知道一个Web应用<br>上下文中是否增加、删<br>除或替换了一个属性</td> <td>javax.servlet.ServletContextAttributeListener</td> <td>ServletContextAttributeEvent</td> </tr> <tr> <td>你想知道有多少个并发<br>用户。也就是说,你想<br>跟中活动的会话。</td> <td>javax.servlet.http.HttpSessionListener</td> <td>HttpSessionEvent</td> </tr> <tr> <td>每次请求到来时你都想<br>知道,以便建立日志记<br>录。</td> <td>javax.servlet.ServletRequestListener</td> <td>ServeltRequestEvent</td> </tr> <tr> <td>增加、删除或替换一个<br>请求属性时你希望能够<br>知道。</td> <td>javax.servlet.ServletRequestAttributeListener</td> <td>ServletRequestAttributeEvent</td> </tr> <tr> <td>你有一个属性类(这个<br>类表示的对象将放在一<br>个属性中),而且你希<br>望这个类型的对象在绑<br>定到一个会话或从会话<br>删除时得到通知。</td> <td>javax.servlet.http.HttpSessionBindingListener</td> <td>HttpSessionBindingEvent</td> </tr> <tr> <td>增加、删除或替换一个<br>会话属性时你希望能够<br>知道。</td> <td>javax.servlet.http.HttpSessionAttributeListener</td> <td><strong>HttpSessionBindingEvent</strong></td> </tr> <tr> <td>你想知道是否创建或撤<br>销了一个上下文</td> <td>javax.servlet.ServletContextListener</td> <td>ServletContextEvent</td> </tr> <tr> <td>你有一个属性类,而且希<br>望这个类型的对象在其<br>绑定的会话迁移到另一<br>个JVM时得到通知。</td> <td>javax.servlet.http.HttpSessionActivationListener</td> <td>HttpSessionEvent</td> </tr> </tbody> </table> <h2 id="属性">属性</h2> <ul> <li>属性就像是钉到公告栏上的一个对象。有人在公告栏上贴公告,以便其他人看到。</li> <li><p>属性和参数</p> <table> <tbody> <tr> <th>2</th> <th>属性</th> <th>参数</th> </tr> <tr> <th>类型</th> <td>应用/上下文<br>请求<br>会话</td> <td>应用/上下文初始化参数<br>请求参数<br>Servlet初始化参数</td> </tr> <tr> <th>设置方法</th> <td>setAttribute(String name, Object value)</td> <td>不能设置应用和Servlet初始化参数。它们都在DD中设置。</td> </tr> <tr> <th>返回类型</th> <td>Object</td> <td>String</td> </tr> <tr> <th>获取方法</th> <td>getAttribute(String name)</td> <td>getInitParameter(String name)</td> </tr> </tbody> </table></li> <li><p>属性的三个作用域:上下文、请求和会话</p></li> <li><p>属性API</p> <pre class="prettyprint"><code class="language-java hljs ">Object getAttribute(String name) <span class="hljs-keyword">void</span> setAttribute(String name, Object value) <span class="hljs-keyword">void</span> removeAttribute(String name) Enumeration getAttributeNames()</code></pre></li> <li>上下文作用域不是线程安全的。多个servlet可能有多个线程。</li> <li><p>不能通过同步服务方法的方式保护上下文属性。而是对上下文加锁。</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment">// 错误!上下文对象仍可以通过其他servlet访问</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doGet</span>(...) // 正确,对上下文加锁 <span class="hljs-title">synchronized</span>(<span class="hljs-title">getServeltContext</span>()) { <span class="hljs-comment">//...</span> }</code></pre></li> <li>会话属性同样不是线程安全的,需要保护:</li> </ul> <pre class="prettyprint"><code class="language-java hljs ">HttpSession session = request.getSession(); <span class="hljs-keyword">synchronized</span>(session) { <span class="hljs-comment">// ...</span> }</code></pre> <ul> <li>可以实现SingleThreadModel来保证servlet一次只得到一个请求。(SingleThreadModel已废弃)</li> <li>只有请求属性和局部变量是线程安全的。</li> </ul> <h2 id="requestddispatcher">RequestdDispatcher</h2> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment">// 从ServletRequest得到RequestDispatcher</span> <span class="hljs-comment">// 参数如果以/开头,则从Web应用的根开始找</span> <span class="hljs-comment">// 如果不是以/开头,则从当前位置(请求发生的位置)开始找</span> RequestDispatcher view = request.getRequestDispatcher(<span class="hljs-string">"result.jsp"</span>); <span class="hljs-comment">// 从ServletContext得到RequestDispatcher</span> <span class="hljs-comment">// 路径必须以/开头,只能从Web应用的根开始找</span> ReqeustDispatcher view = getServletContext().getRequestDispaatcher(<span class="hljs-string">"/result.jsp"</span>); <span class="hljs-comment">// 在RequestDispatcher上调用forward()分派请求</span> view.forward(request, response);</code></pre> <h1 id="会话管理">会话管理</h1> <ul> <li>HttpSession对象可以保存跨同一个客户多个请求的会话状态。换句话说,与一个特定客户的整个会话期间,HttpSession会持久存储。对于会话期间客户做的所有请求,从中得到的所有信息都可以用HttpSession对象保存。</li> </ul> <h2 id="如何实现会话">如何实现会话</h2> <ul> <li>对客户的第一个请求,容器会生成一个唯一的会话ID,并通过响应把它返回给客户。客户再在以后的每一个请求中发回这个会话ID。容器看到ID后,就会找到匹配的会话,并把这个会话与请求关联。</li> <li>容器必须以某种方式把会话ID作为响应的一部分交给客户,而客户必须把会话ID作为请求的一部分返回。最简单而且最常用的方式是通过cookie交换这个会话ID信息。</li> <li>容器几乎会做cookie的所有工作。</li> </ul> <h2 id="获取会话">获取会话</h2> <ul> <li><code>request.getSession()</code>获取Session。</li> <li><code>session.isNew()</code>返回是否新建的Session。</li> <li><code>request.getSession(fase)</code>获取已有的会话。如果得到返回HtteSession,否则返回null。</li> </ul> <h2 id="如果不能使用cookie如何完成会话">如果不能使用cookie,如何完成会话?</h2> <ul> <li>有些客户会进禁止cookie,因此无法用cookie传送SessionID。会话的isNew()方法总是返回true。</li> <li>如果客户不接受cookie,可以把URL重写作为一条后路。URL重写能够取得置于cookie中的会话ID,并把会话ID附加到访问应用的各个URL的最后。假设有一个Web页面,其中每个链接都有一些额外的信息(会话ID)附加到URL的组后。当用户点击这种“enhanced”(改进)链接时,到达容器的请求会在会后携带着这个额外信息,容器会取下请求URL中这个额外部分,并用它查找匹配的会话。</li> <li>如果不能用cookie,而且只有告诉响应要对URL编码,URL重写才能奏效。</li> <li>容器如何判断cookie是否工作?当容器看到一个getSession()调用时,而且没有从客户的请求得到会话ID,容器就知道它必须尝试与客户建立一个新的会话。此时,容器并不知道cookie是否工作,所以向客户返回第一个响应时,会同时尝试cookie和URL重写这两种做法。如果客户接受cookie,则下一个请求时会带着ID cookie,容器找到这个ID cookie,并忽略URL重写。如果找不到这个ID cookie,则容器开启URL重写。</li> <li><p>URL重写API:</p> <pre class="prettyprint"><code class="language-java hljs ">response.encodeURL(<span class="hljs-string">"/BeerTest.do"</span>) response.encodeRedirectURL(<span class="hljs-string">"/BeerTest.do"</span>)</code></pre></li> <li><p>不能对静态页面完成URL重写。因此必须在运行时动态生成HTML。</p></li> <li>要使用URL重写,页面必须是动态生成的。可以用JSP来完成URL重写。<code><c:URL></code>标签可以很容易的完成这个工作。</li> <li>URL重写以开发商特定的方式处理。我们无需知道。</li> <li>URL重写是自动的,但是只有当你对URL完成了编码时它才奏效。必须通过响应对象的一个方法(可以是encodeURL()或encodeRedirectURL())来运行所有URL,其他的所有事情都由容器来完成。</li> <li>URL编码有响应处理。</li> <li><p>要点</p> <ul> <li>在写至响应的HTML中,URL重写把会话ID增加到其中所有URL的最后。</li> <li>会话ID作为请求URL最后的“额外”信息再通过请求返回。</li> <li>如果客户不接受cookie,URL重写会自动发生,但是必须显式地对所有URL编码。</li> <li><p>要对一个URL编码,需要调用response.encodeURL(aString)。</p> <pre class="prettyprint"><code class="language-java hljs ">out.println(<span class="hljs-string">"<a href='"</span> + response.encodeURL(<span class="hljs-string">"/BeerTest.do"</span>) + <span class="hljs-string">"'>click me</a>"</span>);</code></pre></li> <li><p>没有办法对静态页面完成自动的URL重写,所以,如果你依赖于会话,就必须使用动态生成的页面。</p></li> </ul></li> </ul> <h2 id="关键的httpsession方法">关键的HttpSession方法</h2> <table> <tbody> <tr> <th></th> <th>它做什么</th> <th>你用它做什么</th> </tr> <tr> <th>getCreationTime()</th> <td>返回第一次创建会话的时间。</td> <td>得出这个会话有多“老”。你可能想把某些会话的寿命限制为一个固定的时间。例如,你可能会说“一旦登陆,就必须在10分钟之内完成这个表单……”</td> </tr> <tr> <th>getLastAccessedTime()</th> <td>返回容器最后一次得到包含这个会话ID的请求后过去了多长时间(毫秒数)</td> <td>得出客户最后一次访问这个会话是什么时候。可以用这个方法来确定客户是否已经离开很长时间,这样就可以向客户发出一封email,询问他们是否还回来。或者可以调用invalidate()结束会话。</td> </tr> <tr> <th>setMaxInactiveInterval()</th> <td>指定对于这个会话客户请求的最大间隔时间(秒数)。</td> <td>如果已经过去了指定时间,而客户未对这个会话做出任何请求,就会导致会话被撤销。可以用这个方法减少服务器中无用的会话。</td> </tr> <tr> <th>getMaxInactiveInterval()</th> <td>返回对于这个会话客户请求的最大间隔时间(秒数)。</td> <td>得出这个会话可以保持多长时间不活动但仍“存活”。可以使用这个方法来判断一个不活动的客户在会话撤销之前还有多长的“寿命”。</td> </tr> <tr> <th>invalidate()</th> <td>结束会话。当前存储在这个会话中的所有会话属性也会解除绑定。</td> <td>如果客户已经不活动,或者你知道会话已经结束,可以用这个方法杀死(撤销)会话。会话实例本身可能由容器回收,但是这一点我们并不关心。置无效意味着会话ID不再存在,而且属性会从会话对象删除。</td> </tr> </tbody> </table> <h2 id="设置会话超时">设置会话超时</h2> <ul> <li>在DD中配置,以分钟为单位</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">session-config</span>></span> <span class="hljs-tag"><<span class="hljs-title">session-timeout</span>></span>15<span class="hljs-tag"></<span class="hljs-title">session-timeout</span>></span> <span class="hljs-tag"></<span class="hljs-title">session-config</span>></span></code></pre> <ul> <li>设置某一个会话的超时</li> </ul> <pre class="prettyprint"><code class="language-java hljs ">session.setMaxInactiveInterval(<span class="hljs-number">20</span> * <span class="hljs-number">60</span>);</code></pre> <h2 id="cookie">Cookie</h2> <ul> <li>可以使用cookie在服务器和客户之间交换名/值String对。服务器把cookie发送给客户,客户再在以后的每个请求中发回这个cookie。客户的浏览器退出时,会话cookie就会消失,但是你可以告诉cookie在客户端上待得更久一些,甚至在浏览器关闭之后还持久保存。</li> </ul> <h3 id="利用servlet-api使用cookie">利用Servlet API使用Cookie</h3> <ul> <li><p>创建一个新Cookie</p> <pre class="prettyprint"><code class="language-java hljs ">Cookie cookie = <span class="hljs-keyword">new</span> Cookie(<span class="hljs-string">"username"</span>, name);</code></pre></li> <li><p>设置cookie在客户端上存活多久</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment">// 以秒为单位,如果-1,则浏览器退出时cookie消失。</span> cookie.setMaxAge(<span class="hljs-number">30</span> * <span class="hljs-number">60</span>);</code></pre></li> <li><p>把cookie发送到客户</p> <pre class="prettyprint"><code class="language-java hljs ">response.addCookie(cookie);</code></pre></li> <li><p>从客户请求得到cookie(或多个cookie)</p> <pre class="prettyprint"><code class="language-java hljs ">Cookie[] cookies = request.getCookies();</code></pre></li> </ul> <h1 id="使用jsp">使用JSP</h1> <ul> <li>JSP最终会变成一个完整的servlet在Web应用中运行。它与其他的servlet非常相似,只不过这个servlet类由容器为你编写。转换和编译只发生一次。</li> <li>JSP中可以使用scriptlet放入常规的Java代码,所谓scriptlet,就是放在<%…%>标记中的Java代码。</li> <li>指令有3种:page、include和taglib。</li> <li>Java代码放在带百分号的尖括号中间:<%和%>。而指令会为元素开始记号再增加一个字符:@</li> </ul> <h2 id="scriptlet">Scriptlet</h2> <pre class="prettyprint"><code class="language-jsp hljs avrasm"><% <span class="hljs-keyword">out</span><span class="hljs-preprocessor">.println</span>(<span class="hljs-string">""</span>)<span class="hljs-comment">; %></span></code></pre> <h2 id="使用page指令导入包">使用page指令导入包</h2> <ul> <li><p>导入单个包,指令最后没有分号</p> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%@</span> page import=<span class="hljs-string">"foo.*"</span> <span class="hljs-variable">%></span></code></pre></li> <li><p>导入多个包,逗号分隔</p> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%@</span> page import=<span class="hljs-string">"foo.*,java.util.*"</span> <span class="hljs-variable">%></span></code></pre></li> </ul> <h2 id="表达式">表达式</h2> <ul> <li><%= %></li> <li>表达式会成为out.print()的参数。</li> <li>表达式没有分号。</li> </ul> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%=</span> Counter.getCount() <span class="hljs-variable">%></span></code></pre> <h2 id="声明">声明</h2> <ul> <li><%! %></li> <li>JSP声明总是在类中定义,而且置于服务方法(或任何其他方法)之外。</li> <li>变量和方法都可以声明。</li> <li><p>需要分号结束。</p> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%!</span> <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>; <span class="hljs-variable">%></span></code></pre></li> </ul> <h2 id="隐式对象">隐式对象</h2> <table> <thead> <tr> <th>API</th> <th>隐式对象</th> </tr> </thead> <tbody> <tr> <td>JspWriter</td> <td>out</td> </tr> <tr> <td>HttpServeltRequest</td> <td>request</td> </tr> <tr> <td>HttpServletResponse</td> <td>response</td> </tr> <tr> <td>HttpSession</td> <td>session</td> </tr> <tr> <td>ServletContext</td> <td>application</td> </tr> <tr> <td>ServletConfig</td> <td>config</td> </tr> <tr> <td>Throwable</td> <td>exception</td> </tr> <tr> <td>PageContext</td> <td>pageContext</td> </tr> <tr> <td>Object</td> <td>page</td> </tr> </tbody> </table> <h2 id="注释">注释</h2> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-comment"><!-- HTML注释 --></span> <span class="vbscript"><%-- JSP注释 --%></span></code></pre> <h2 id="初始化jsp">初始化JSP</h2> <ul> <li><p>DD</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>MyTestInit<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">jsp-file</span>></span>/TestInit.jsp<span class="hljs-tag"></<span class="hljs-title">jsp-file</span>></span> <span class="hljs-tag"><<span class="hljs-title">init-param</span>></span> <span class="hljs-tag"><<span class="hljs-title">param-name</span>></span>email<span class="hljs-tag"></<span class="hljs-title">param-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">param-value</span>></span>cynhard85@126.com<span class="hljs-tag"></<span class="hljs-title">param-value</span>></span> <span class="hljs-tag"></<span class="hljs-title">init-param</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-mapping</span>></span> <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>MyTestInit<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">url-parttern</span>></span>/TestInit.jsp<span class="hljs-tag"></<span class="hljs-title">url-parttern</span>></span> <span class="hljs-tag"></<span class="hljs-title">servlet-mapping</span>></span></code></pre></li> <li><p>覆盖jspInit()</p></li> </ul> <pre class="prettyprint"><code class="language-jsp hljs cs"><%! <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">jspInit</span>() { ServletConfig sConfig = getServletConfig(); String emailAddr = sConfig.getInitParameter(<span class="hljs-string">"email"</span>); ServletContext ctx = getServletContext(); ctx.setAttribute(<span class="hljs-string">"mail"</span>, emailAddr); } %></code></pre> <h2 id="jsp中的属性">JSP中的属性</h2> <table> <tbody> <tr> <th></th> <th>servlet中</th> <th>JSP中</th> </tr> <tr> <th>应用</th> <td>getServletContext().setAttribute(“foo”, barObj);</td> <td>application.setAttribute(“foo”, barObj);</td> </tr> <tr> <th>请求</th> <td>request.setAttribute(“foo”, barObj);</td> <td>request.setAttribute(“foo”, barObj);</td> </tr> <tr> <th>会话</th> <td>request.getSession().setAttribute(“foo”, barObj);</td> <td>session.setAttribute(“foo”, barObj);</td> </tr> <tr> <th>页面</th> <td>不适用!</td> <td>pageContext.setAttribute(“foo”, barObj);</td> </tr> </tbody> </table> <h2 id="使用pagecontext得到属性">使用PageContext得到属性</h2> <pre class="prettyprint"><code class="language-jsp hljs ruby"><<span class="hljs-string">%--</span> 设置一个页面作用域属性 --%> <% <span class="hljs-constant">Float</span> one = new <span class="hljs-constant">Float</span>(<span class="hljs-number">42.5</span>); %> <% pageContext.setAttribute(<span class="hljs-string">"foo"</span>, one); %> <<span class="hljs-string">%--</span> 获得一个页面作用域属性 --%> <%= pageContext.getAttribute(<span class="hljs-string">"foo"</span>); %> <<span class="hljs-string">%--</span> 使用pageContext设置一个会话作用域属性 --%> <% <span class="hljs-constant">Float</span> two = new <span class="hljs-constant">Float</span>(<span class="hljs-number">22.4</span>); %> <% pageContext.setAttribute(<span class="hljs-string">"foo"</span>, two, <span class="hljs-constant">PageContext</span>.<span class="hljs-constant">SESSION_SCOPE</span>); %> <<span class="hljs-string">%--</span> 使用pageContext获得一个会话作用域属性 --%> <%= pageContext.getAttribute(<span class="hljs-string">"foo"</span>, <span class="hljs-constant">PageContext</span>.<span class="hljs-constant">SESSION_SCOPE</span>); %> <<span class="hljs-string">%--</span> 等价于: --%> <%= session.getAttribute(<span class="hljs-string">"foo"</span>); %> <<span class="hljs-string">%--</span> 使用pageContext获得一个应用作用域属性 --%> <%= pageContext.getAttribute(<span class="hljs-string">"mail"</span>, <span class="hljs-constant">PageContext</span>.<span class="hljs-constant">APPLICATION_SCOPE</span>); %> <<span class="hljs-string">%--</span> 等价于: --%> <%= application.getAttribute(<span class="hljs-string">"mail"</span>); %> <<span class="hljs-string">%--</span> 使用pageContext,即使不知道作用域也可以查找一个属性 --%> <<span class="hljs-string">%--</span> 查找顺序:page->request->session->application --%> <%= pageContext.findAttribute(<span class="hljs-string">"foo"</span>); %></code></pre> <h2 id="指令">指令</h2> <h3 id="page指令">page指令</h3> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%@</span> page import=<span class="hljs-string">"foo.*"</span> session=<span class="hljs-string">"false"</span> <span class="hljs-variable">%></span></code></pre> <p>定义页面的特定的属性,以及这个页面是否要有隐式的会话对象。</p> <h4 id="属性-1">属性</h4> <table> <thead> <tr> <th>属性</th> <th>意义</th> </tr> </thead> <tbody> <tr> <td>import</td> <td>定义Java import语句</td> </tr> <tr> <td>isThreadSafe</td> <td>定义生成的servlet是否需要实现SingleThreadModel(bad idea)。</td> </tr> <tr> <td>contentType</td> <td>定义JSP响应的MIME类型。</td> </tr> <tr> <td>isELIgnored</td> <td>定义转换这个页面时是否忽略EL表达式。</td> </tr> <tr> <td>isErrorPage</td> <td>定义当前页面是否是另一个JSP的错误页面。</td> </tr> <tr> <td>errorPage</td> <td>定义一个资源的URL,如果有未捕获到的Throwable,就会发送到这个资源。</td> </tr> <tr> <td>language</td> <td>定义scriptlet、表达式和声明中使用的脚本语言。</td> </tr> <tr> <td>extends</td> <td>JSP会变成一个servlet类,这个属性则定义了这个类的超类。</td> </tr> <tr> <td>session</td> <td>定义页面是否有一个隐式的session对象。默认值为true。</td> </tr> <tr> <td>buffer</td> <td>定义隐式out对象(JspWriter的引用)如何处理缓存。</td> </tr> <tr> <td>autoFlush</td> <td>定义缓存的输出是否自动刷新输出。默认值是true。</td> </tr> <tr> <td>info</td> <td>定义放到转换后页面中的串,这样就能使用所生成servlet继承的getServletInfo()方法来得到这个信息。</td> </tr> <tr> <td>pageEncoding</td> <td>定义JSP的字符编码。默认为“ISO-8859-1”</td> </tr> </tbody> </table> <h3 id="taglib指令">taglib指令</h3> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%@</span> taglib tagdir=<span class="hljs-string">"/WEB-INF/tags/cool"</span> prefix=<span class="hljs-string">"cool"</span> <span class="hljs-variable">%></span></code></pre> <p>定义JSP可以使用的标记库。</p> <h3 id="include指令">include指令</h3> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%@</span> include <span class="hljs-keyword">file</span>=<span class="hljs-string">"wickedHeader.html"</span> <span class="hljs-variable">%></span></code></pre> <p>定义在转换时增加到当前页面的文本和代码。</p> <h2 id="el表达式">EL表达式</h2> <ul> <li>用EL表达式替代scriptlet。 <br> <ul> <li>不应该要求Web页面设计人员必须懂Java。</li> <li>JSP中的Java代码很难修改和维护。</li> </ul></li> <li><p>EL和Java比较:</p> <ul> <li>EL:<code>${application.mail}</code></li> <li>Java:<code><%= application.getAttribute("mail") %></code> </li> </ul></li> <li><p>让JSP禁用脚本元素(scriptlet、Java表达式或声明):</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">jsp-config</span>></span> <span class="hljs-tag"><<span class="hljs-title">sp-property-group</span>></span> <span class="hljs-tag"><<span class="hljs-title">url-parttern</span>></span>*.jsp<span class="hljs-tag"></<span class="hljs-title">url-parttern</span>></span> <span class="hljs-tag"><<span class="hljs-title">scripting-invalid</span>></span>true<span class="hljs-tag"></<span class="hljs-title">scripting-invalid</span>></span> <span class="hljs-tag"></<span class="hljs-title">sp-property-group</span>></span> <span class="hljs-tag"></<span class="hljs-title">jsp-config</span>></span></code></pre></li> <li><p>忽略EL(默认是启用的):</p> <ul> <li><p>通过DD:</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">jsp-config</span>></span> <span class="hljs-tag"><<span class="hljs-title">sp-property-group</span>></span> <span class="hljs-tag"><<span class="hljs-title">url-parttern</span>></span>*.jsp<span class="hljs-tag"></<span class="hljs-title">url-parttern</span>></span> <span class="hljs-tag"><<span class="hljs-title">el-ignored</span>></span>true<span class="hljs-tag"></<span class="hljs-title">el-ignored</span>></span> <span class="hljs-tag"></<span class="hljs-title">sp-property-group</span>></span> <span class="hljs-tag"></<span class="hljs-title">jsp-config</span>></span></code></pre></li> <li><p>通过page指令:</p> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%@</span> page isELIgnored=<span class="hljs-string">"true"</span> <span class="hljs-variable">%></span></code></pre></li> </ul></li> </ul> <h2 id="动作">动作</h2> <ul> <li>标准动作:</li> </ul> <pre class="prettyprint"><code class="language-jsp hljs ruby"><<span class="hljs-symbol">jsp:</span><span class="hljs-keyword">include</span> page=<span class="hljs-string">"wickedFooter.jsp"</span> /></code></pre> <ul> <li>其他动作:</li> </ul> <pre class="prettyprint"><code class="language-jsp hljs cs"><c:<span class="hljs-keyword">set</span> <span class="hljs-keyword">var</span>=<span class="hljs-string">"rate"</span> <span class="hljs-keyword">value</span>=<span class="hljs-string">"32"</span> /></code></pre> <h1 id="无脚本的jsp">无脚本的JSP</h1> <h2 id="使用bean">使用bean</h2> <ul> <li>如果一个类Person有两个方法getProperty()和setProperty(),根据JavaBean规范,就称Person有property的属性。</li> <li><p>Bean应用:</p> <ul> <li><p>servlet中:</p> <pre class="prettyprint"><code class="language-java hljs ">Person person = <span class="hljs-keyword">new</span> Person(); person.setName(<span class="hljs-string">"Gopher"</span>); request.setAttribute(<span class="hljs-string">"person"</span>, person);</code></pre></li> <li><p>jsp中:</p> <pre class="prettyprint"><code class="language-jsp hljs applescript"><jsp:useBean <span class="hljs-property">id</span>=<span class="hljs-string">"person"</span> <span class="hljs-type">class</span>=<span class="hljs-string">"com.cynhard.model.Person"</span> scope=<span class="hljs-string">"request"</span> /> <jsp:getProperty <span class="hljs-property">name</span>=<span class="hljs-string">"person"</span> <span class="hljs-keyword">property</span>=<span class="hljs-string">"name"</span> /></code></pre> <p>分解: <br> <code><jsp:useBean id="person" class="com.cynhard.model.Person" scope="request" /></code></p> <ul> <li><code><jsp:useBean></code>标识标准动作</li> <li><code>id="person"</code>声明bean对象的标识符。这对应于以下servlet代码中所用的名:<code>request.setAttribute("person", p);</code></li> <li><code>class="com.cynhard.model.Person"</code>声明bean对象的类类型。</li> <li><code>scope="request"</code>标识这个bean对象的属性作用域。</li> </ul> <p><code><jsp:getProperty name="person" property="name" /></code></p> <ul> <li><code>jsp:getProperty</code>标识标准动作</li> <li><code>name="person"</code>标识具体的bean对象。这与<code><jsp:useBean></code>标记的“id”值匹配。</li> <li><code>property="name"</code>标识属性中的性质名(也就是bean类中获取方法和设置方法对应的性质)。</li> </ul></li> </ul></li> <li><p><code><jsp:useBean></code>如果找不到属性对象,则会创建一个。</p></li> <li><p>可以用<code><jsp:setProperty></code>设置属性。</p> <pre class="prettyprint"><code class="language-jsp hljs applescript"><jsp:setProperty <span class="hljs-property">name</span>=<span class="hljs-string">"person"</span> <span class="hljs-keyword">property</span>=<span class="hljs-string">"name"</span> value=<span class="hljs-string">"Cynhard"</span> /></code></pre></li> <li><p>利用<code><jsp:useBean></code>体,可以有条件地运行代码,只有找不到bean属性,而且创建了一个新bean是才会运行体中的代码。</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-comment"><!-- 只有request没有person属性时,才会设置person的name。 --></span> <span class="hljs-tag"><<span class="hljs-title">jsp:useBean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"person"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"com.cynhard.model.Person"</span> <span class="hljs-attribute">scope</span>=<span class="hljs-value">"request"</span>></span> <span class="hljs-tag"><<span class="hljs-title">jsp:setProperty</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"person"</span> <span class="hljs-attribute">property</span>=<span class="hljs-value">"name"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"Cynhard"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">jsp:useBean</span>></span></code></pre></li> <li><p>Bean标记会自动转换基本类型的性质</p></li> </ul> <h2 id="bean法则">Bean法则</h2> <ul> <li>必须提供public无参构造函数。</li> <li>必须按照命名约定来命名公共的获取和设置方法:getProperty()、isProperty()、setProperty()</li> <li>设置方法的参数类型和获取方法的返回类型必须一致。</li> <li>性质名和类型是有获取方法和设置方法得出,而不是得自于类中的一个成员。</li> <li>结合JSP使用时,性质类型必须是String,或者是一个基本类型。</li> </ul> <h2 id="为jspusebean增加一个type属性">为<code><jsp:useBean></code>增加一个type属性</h2> <ul> <li><p>class为对象类型。type为引用类型。</p> <pre class="prettyprint"><code class="language-jsp hljs fsharp"><jsp:useBean id=<span class="hljs-string">"person"</span> <span class="hljs-class"><span class="hljs-keyword">type</span>=</span><span class="hljs-string">"foo.Person"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"foo.Employee"</span> scope=<span class="hljs-string">"page"</span>></code></pre></li> <li><p>type可以是class类型、抽象类型或者是一个接口,只要能用作为bean对象class类型的声明引用类型,都可以指定为type。</p></li> <li>如果使用了type,但没有class,bean必须已经存在。如果使用了class(有或没有type),class不能是抽象类,而且必须有一个无参数的公共构造函数。</li> <li>type是你声明的类型(可以使抽象类),class是你要实例化的类(必须是具体类):<code>type x = new class()</code></li> </ul> <h2 id="scope属性默认为page">scope属性默认为“page”</h2> <pre class="prettyprint"><code class="language-jsp hljs d"><jsp:useBean id=<span class="hljs-string">"person"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"foo.Employee"</span> <span class="hljs-keyword">scope</span>=<span class="hljs-string">"page"</span>/></code></pre> <p>等价于:</p> <pre class="prettyprint"><code class="language-jsp hljs applescript"><jsp:useBean <span class="hljs-property">id</span>=<span class="hljs-string">"person"</span> <span class="hljs-type">class</span>=<span class="hljs-string">"foo.Employee"</span>/></code></pre> <h2 id="param属性">param属性</h2> <ul> <li><p>利用param属性,可以把bean的性质值设置为一个请求参数的值。只需指定请求参数!</p> <ul> <li><p>TestBean.jsp:</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">jsp:useBean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"person"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"foo.Person"</span> <span class="hljs-attribute">clas</span>=<span class="hljs-value">"foo.Employee"</span>></span> <span class="hljs-tag"><<span class="hljs-title">jsp:setProperty</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"person"</span> <span class="hljs-attribute">property</span>=<span class="hljs-value">"name"</span> <span class="hljs-attribute">param</span>=<span class="hljs-value">"userName"</span>/></span> <span class="hljs-tag"></<span class="hljs-title">jsp:useBean</span>></span></code></pre></li> <li><p>直接获取userName的值:</p> <pre class="prettyprint"><code class="language-html hljs "><span class="hljs-tag"><<span class="hljs-title">form</span> <span class="hljs-attribute">acton</span>=<span class="hljs-value">"TestBean.jsp"</span>></span> name: <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"userName"</span>/></span> ... <span class="hljs-tag"></<span class="hljs-title">form</span>></span></code></pre></li> </ul></li> <li><p>如果请求参数名与bean性质名匹配,就不需要在<code><jsp:setProperty></code>标记中为该性质指定值。</p> <ul> <li><p>TestBean.jsp,不再需要param。</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">jsp:useBean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"person"</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"foo.Person"</span> <span class="hljs-attribute">clas</span>=<span class="hljs-value">"foo.Employee"</span>></span> <span class="hljs-tag"><<span class="hljs-title">jsp:setProperty</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"person"</span> <span class="hljs-attribute">property</span>=<span class="hljs-value">"name"</span>/></span> <span class="hljs-tag"></<span class="hljs-title">jsp:useBean</span>></span></code></pre></li> <li><p>直接获取userName的值:</p> <pre class="prettyprint"><code class="language-html hljs "><span class="hljs-tag"><<span class="hljs-title">form</span> <span class="hljs-attribute">acton</span>=<span class="hljs-value">"TestBean.jsp"</span>></span> name: <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"name"</span>/></span> ... <span class="hljs-tag"></<span class="hljs-title">form</span>></span></code></pre></li> </ul></li> <li><p>如果所有请求参数名都与bean性质名匹配,则<code><jsp:setProperty></code>中可以用<code>property=*</code>来获取所有请求参数的值。</p> <pre class="prettyprint"><code class="language-jsp hljs applescript"><jsp:setProperty <span class="hljs-property">name</span>=<span class="hljs-string">"person"</span> <span class="hljs-keyword">property</span>=<span class="hljs-string">"*"</span>/></code></pre></li> </ul> <h2 id="el表达式-1">EL表达式</h2> <ul> <li><p>使用EL,打印嵌套性质变得非常容易……换句话说,可以很轻松地打印性质的性质。</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-comment"><!-- 访问person的dog属性的name属性 --></span> ${person.dog.name}</code></pre></li> <li><p>EL表达式总是放在大括号里,而且前面有一个美元符前缀。</p></li> <li><p>表达式中第一个命名变量可以是一个隐式对象,也可以是一个属性。</p> <ul> <li>EL隐式对象:<code>pageScope requestScope sessionScope applicationScope param paramValues header headerValues cookie initParam pageContext</code>。在所有隐式对象中,只有pageContext不是Map。这是pageContext对象的实际引用。</li> <li>属性:页面作用域中的属性、请求作用域中的属性、会话作用域中的属性、应用作用域中的属性。</li> </ul></li> <li><p>使用点号操作符访问性质和映射值:</p> <ul> <li>点号左边的变量要么是一个Map(有键),要么是一个bean(有性质)。不论变量是一个隐式对象还是一个属性,都是如此。</li> <li>pageContext隐式对象是一个bean,它有获取方法,所有其他隐式对象都是Map。</li> <li>如果对象是一个bean,但是指定的性质不存在,会抛出一个异常。</li> </ul></li> </ul> <h3 id="使用方括号">使用方括号</h3> <ul> <li><p><code>[]</code>就像是更好的点号:</p> <pre class="prettyprint"><code class="language-jsp hljs ruby"><span class="hljs-variable">${</span>person[<span class="hljs-string">"name"</span>]}</code></pre></li> <li><p><code>[]</code>左边可以是List、数组、Map、Bean。<code>[]</code>里面可以是键、索引、属性名。</p></li> <li>数组和List中的String索引会强制转换为int。如果中括号左边是一个数组或List,而且索引是一个String直接量,那么这个索引会强制转换为int。</li> </ul> <h2 id="点号和方括号">点号和方括号</h2> <ul> <li>对于bean和Map,这两个操作符都可以用。</li> <li><p>如果不是String直接量,就会计算。</p> <pre class="prettyprint"><code class="language-jsp hljs smalltalk"><span class="hljs-char">${</span>musicMap[<span class="hljs-class">Ambient</span>]} // 查找一个名为<span class="hljs-comment">"Ambient"</span>的属性。 <span class="hljs-char">${</span>musicMap[<span class="hljs-comment">"Ambient"</span>]}</code></pre></li> <li><p>方括号内可以使用嵌套表达式</p> <pre class="prettyprint"><code class="language-jsp hljs bash"><span class="hljs-variable">${musicMap[MusicType[0]]}</span></code></pre></li> <li><p>点号后面不能接索引:${foo.1}是不行的。如果不能用作为Java代码中的变量名,就不能把它放在点号后面。</p></li> </ul> <h3 id="el中的请求参数">EL中的请求参数</h3> <ul> <li><p>HTML中:</p> <pre class="prettyprint"><code class="language-html hljs "><span class="hljs-tag"><<span class="hljs-title">form</span> <span class="hljs-attribute">action</span>=<span class="hljs-value">"TestBean.jsp"</span>></span> Name: <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"name"</span>></span> ID#: <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"empID"</span>></span> First food: <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"food"</span>></span> Second food: <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"text"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"food"</span>></span> <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"submit"</span>></span> <span class="hljs-tag"></<span class="hljs-title">form</span>></span></code></pre></li> <li><p>JSP中:</p> <pre class="prettyprint"><code class="language-jsp hljs xml">Request param name is: ${param.name}<span class="hljs-tag"><<span class="hljs-title">br</span>></span> Request param empID is: ${param.empID}<span class="hljs-tag"><<span class="hljs-title">br</span>></span> Request param food is: ${param.food}<span class="hljs-tag"><<span class="hljs-title">br</span>></span> <span class="hljs-comment"><!-- 得到food中的第一个值 --></span> First food request param: ${paramValues.food[0]}<span class="hljs-tag"><<span class="hljs-title">br</span>></span> Second food request param: ${paramValues.food[1]}<span class="hljs-tag"><<span class="hljs-title">br</span>></span> Request param name: ${paramValues.name[0]}</code></pre></li> </ul> <h3 id="el获取更多信息">EL获取更多信息</h3> <ul> <li><p>得到“host”首部:</p> <pre class="prettyprint"><code class="language-jsp hljs ruby"><span class="hljs-variable">${</span>header[<span class="hljs-string">"host"</span>]} <span class="hljs-variable">${</span>header.host}</code></pre></li> <li><p>使用requestScope会得到请求属性,而不是request性质。要得到request性质,需要通过pageContext。</p> <pre class="prettyprint"><code class="language-jsp hljs avrasm">${pageContext<span class="hljs-preprocessor">.request</span><span class="hljs-preprocessor">.method</span>}</code></pre></li> </ul> <h3 id="得到cookie和初始化参数">得到Cookie和初始化参数</h3> <ul> <li><p>打印“useName”Cookie的值:</p> <ul> <li><p>脚本:</p> <pre class="prettyprint"><code class="language-jsp hljs matlab"><<span class="hljs-comment">%</span> Cookie<span class="hljs-matrix">[]</span> cookies = <span class="hljs-transposed_variable">request.</span>getCookies(); <span class="hljs-keyword">for</span> (int <span class="hljs-built_in">i</span> = <span class="hljs-number">0</span>; <span class="hljs-built_in">i</span> < <span class="hljs-transposed_variable">cookies.</span><span class="hljs-built_in">length</span>; <span class="hljs-built_in">i</span>++) <span class="hljs-cell">{ if ((cookies[i].getName()).equals("userName")) { out.println(cookies[i].getValue()); }</span> } <span class="hljs-comment">%></span></code></pre></li> <li><p>EL:</p></li> </ul> <pre class="prettyprint"><code class="language-jsp hljs avrasm">${cookie<span class="hljs-preprocessor">.userName</span><span class="hljs-preprocessor">.value</span>}</code></pre></li> <li><p>打印一个上下文初始化参数:</p> <ul> <li><p>DD:</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">context-param</span>></span> <span class="hljs-tag"><<span class="hljs-title">param-name</span>></span>mainEmail<span class="hljs-tag"></<span class="hljs-title">param-name</span>></span> <span class="hljs-tag"><<span class="hljs-title">parma-value</span>></span>cynhard85@126.com<span class="hljs-tag"></<span class="hljs-title">param-value</span>></span> <span class="hljs-tag"></<span class="hljs-title">context-param</span>></span></code></pre></li> <li><p>脚本:</p> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%=</span> application.getInitParameter(<span class="hljs-string">"mainEmail"</span>) <span class="hljs-variable">%></span></code></pre></li> <li><p>EL:</p> <pre class="prettyprint"><code class="language-jsp hljs bash"><span class="hljs-variable">${initParam.mainEmail}</span></code></pre></li> </ul></li> </ul> <h2 id="el函数">EL函数</h2> <ol> <li><p>编写有一个公共静态方法的Java类。</p> <ul> <li>这只是一个普通的Java类。这个方法必须是公共的,而且是一个静态方法。</li> <li><p>放在WEB-INF/classes中</p> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-keyword">package</span> foo; <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DiceRoller</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">rollDice</span>() { <span class="hljs-keyword">return</span> (<span class="hljs-keyword">int</span>)((Math.random() * <span class="hljs-number">6</span>) +1); } }</code></pre></li> </ul></li> <li><p>编写一个标记库描述文件(TLD)。</p> <ul> <li>对于一个EL函数,TLD提供了定义函数的Java类与调用函数的JSP之间的一个映射。这样一来,函数名和具体的方法名可以使不同的。</li> <li>它必须放在WEB-INF目录或者某个子目录中。</li> <li><p>确保JSP中taglib指令包含的uri属性与TLD中的<code><uri></code>元素匹配。</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-pi"><?xml version="1.0" encoding="ISO-8859-1" ?></span> <span class="hljs-doctype"><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"></span> <span class="hljs-tag"><<span class="hljs-title">taglib</span>></span> <span class="hljs-tag"><<span class="hljs-title">tlib-version</span>></span>1.2<span class="hljs-tag"></<span class="hljs-title">tlib-version</span>></span> <span class="hljs-tag"><<span class="hljs-title">uri</span>></span>DiceFunctions<span class="hljs-tag"></<span class="hljs-title">uri</span>></span> <span class="hljs-tag"><<span class="hljs-title">function</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>rollIt<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">function-class</span>></span>foo.DiceRoller<span class="hljs-tag"></<span class="hljs-title">function-class</span>></span> <span class="hljs-tag"><<span class="hljs-title">function-signature</span>></span>int rollDice()<span class="hljs-tag"></<span class="hljs-title">function-signature</span>></span> <span class="hljs-tag"></<span class="hljs-title">function</span>></span> <span class="hljs-tag"></<span class="hljs-title">taglib</span>></span></code></pre></li> </ul></li> <li><p>在JSP中放一个taglib指令。</p> <ul> <li><p>taglib指令告诉容器,“我想使用这个TLD,另外,在JSP中,使用这个TLD中的一个函数时,我想用这个名字作为前缀……”</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="vbscript"><%@ taglib prefix=<span class="hljs-string">"mine"</span> uri=<span class="hljs-string">"DiceFunctions"</span>%></span> <span class="hljs-tag"><<span class="hljs-title">html</span>></span><span class="hljs-tag"><<span class="hljs-title">body</span>></span> ${mine:rollIt()} <span class="hljs-tag"></<span class="hljs-title">body</span>></span><span class="hljs-tag"></<span class="hljs-title">html</span>></span></code></pre></li> </ul></li> <li><p>使用EL调用函数。</p> <ul> <li><code>${prefix:name()}</code></li> </ul></li> </ol> <h2 id="el操作符">EL操作符</h2> <ul> <li><p>算术操作符 <br> 加法 + <br> 减法 - <br> 乘法 * <br> 除法 /和div <br> 取模 %和mod</p></li> <li><p>逻辑操作符 <br> 与 &&和and <br> 或 ||和or <br> 非 !和not</p></li> </ul> <p>关系操作符 <br> 等于 == 和eq <br> 不等于 !=和ne <br> 小于 <和lt <br> 大于>和gt <br> 小于等于 <=和le <br> 大于等于 >=和ge</p> <h2 id="el能妥善地处理null值">EL能妥善地处理null值</h2> <ul> <li>EL能友好地处理null。它能处理unknown或null值,即使找不到表达式中指定名的属性/性质/键,也会显示页面。</li> <li>在算术表达式中,EL把null值看作是“0”。</li> <li>在逻辑表达式中,EL把null值看作是“false”。</li> </ul> <h2 id="el复习">EL复习</h2> <ul> <li>EL表达式总是用大括号括起,而且前面有一个美元符号(<code>$</code>)前缀:<code>${expression}</code></li> <li>表达式中第一个命名变量要么是一个隐式对象,要么是某个作用域(页面作用域、请求作用域、会话作用域或应用作用域)中的一个属性。</li> <li>点号操作符允许你使用一个Map键或一个bean性质名来访问值,例如,使用<code>${foo.bar}</code>可以得到bar的值,在此bar是Map foo的Map键名,或者bar是bean foo的一个性质。放在点号操作符右边的东西必须遵循Java的标识符命名规则!(换句话说,必须以一个字母,下划线或美元符号开头,第一个字符后面可以有数字,但是不能邮其他字符。)</li> <li>点号右边只能放合法的Java标识符。例如:<code>${foo.1}</code>就不允许。</li> <li><code>[]</code>操作符比点号功能更强大,因为利用<code>[]</code>可以访问数组和List,可以把包含命名变量的表达式放在中括号里,而且可以做任意层次的嵌套,只要你受得了。</li> <li>例如,如果musicList是一个ArrayList,可以用<code>${musicList[0]}</code>或<code>${musicList["0"]}</code>来访问列表中的第一个值。EL并不关心列表索引加不加引号。</li> <li>如果中括号里的内容没有用引号引起来,容器就会进行计算。如果确实放在引号里,而且不是一个数组或List的索引,容器就会把它看作是性质或键的直接量名。</li> <li>除了一个EL隐式对象(PageContext)外,其他EL隐式对象都是Map。从这些Map隐式对象可以得到任意4个作用域中的属性、请求参数值、首部值、cookie值和上下文初始化参数。非映射的隐式对象pageContext,它是PageContext对象的一个引用。</li> <li>不要把隐式EL作用域对象(属性的Map)与属性所绑定的对象混为一谈。换句话说,不要把requestScope隐式对象与具体的JSP隐式对象request混淆。访问request对象只有一条路,就是通过pageContext隐式对象来访问。(不过,想从请求得到的一些东西通过其他EL隐式对象也可以得到,包括param/paramValues,header/headerValues和cookie)</li> <li>EL函数允许你调用一个普通Java类中的公共静态方法。函数名不一定与具体的方法名匹配!例如,<code>${foo:rollIt()}</code>并不意味着包含函数的类中肯定有一个名为rollIt()的方法。</li> <li>使用一个TLD(标记库描述文件)将函数名(例如rollIt())映射到一个具体的静态方法。使用<code><function></code>元素声明一个函数,包括函数的<code><name></code>(rollIt()),完全限定类<code><function-class></code>,以及<code><function-signature></code>,其中包括返回类型以及方法名和参数表。</li> <li>要在JSP中使用函数,必须使用taglib指令声明一个命名空间。在taglib指令中放一个prefix属性,告诉容器你要调用的函数在哪个TLD里能找到。例如:<code><%@ taglib prefix="mine" uri="/WEB-INF/foo.tld"%></code></li> </ul> <h2 id="可重用的模板组件">可重用的模板组件</h2> <ul> <li>include指令:<code><%@ include file="Header.jsp"%></code></li> <li><code><jsp:include></code>标准动作:<code><jsp:include page="Header.jsp"></code></li> <li>include指令在转换时发生。<code><jsp:include></code>标准动作在运行时发生。</li> <li>include指令在转换时插入“Header.jsp”的源代码。而<code><jsp:include></code>标准动作在运行时插入“Header.jsp”的相应。</li> <li>采用include指令,被包含页面的源代码将成为有include指令的“外围”页面的一部分。</li> <li>include指令和<code><jsp:include></code>是位置敏感的。</li> <li>不要把开始和结束HTML和Body标记放在可重用部件中。设计和编写布局模板部件时(如页眉、导航条等),要假设他们会包含在其他页面中。</li> </ul> <h3 id="使用jspparam定制包含的内容">使用<code><jsp:param></code>定制包含的内容</h3> <p>包含的页面:</p> <pre class="prettyprint"><code class="language-jsp hljs livecodeserver"><jsp:<span class="hljs-built_in">include</span> page=<span class="hljs-string">"Header.jsp"</span>> <jsp:<span class="hljs-built_in">param</span> name=<span class="hljs-string">"subTitle"</span> <span class="hljs-built_in">value</span>=<span class="hljs-string">"Hello"</span>/> </jsp:<span class="hljs-built_in">include</span>></code></pre> <p>被包含的页面:</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">strong</span>></span>${param.subTitle}<span class="hljs-tag"></<span class="hljs-title">strong</span>></span></code></pre> <h3 id="jspforward标准动作"><code><jsp:forward></code>标准动作</h3> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="vbscript"><% <span class="hljs-keyword">if</span> (<span class="hljs-built_in">request</span>.getParameter(<span class="hljs-string">"useName"</span>) == <span class="hljs-literal">null</span>) { %></span> <span class="hljs-tag"><<span class="hljs-title">jsp:forward</span> <span class="hljs-attribute">page</span>=<span class="hljs-value">"HandleIt.jsp"</span>/></span> <span class="vbscript"><% } %></span></code></pre> <p>如果发生了转发,转发前些的所有内容都不会出现。</p> <h3 id="jstl">JSTL</h3> <pre class="prettyprint"><code class="language-jsp hljs bash"><c:<span class="hljs-keyword">if</span> test=<span class="hljs-string">"<span class="hljs-variable">${empty param.userName}</span>"</span>> <jsp:forward page=<span class="hljs-string">"HandleIt.jsp"</span>/> </c:<span class="hljs-keyword">if</span>></code></pre> <h2 id="bean相关标准动作复习">Bean相关标准动作复习</h2> <ul> <li><code><jsp:useBean></code>标准动作会定义一个变量,它可能是一个现有bean属性的引用,如果还不存在这样一个bean,则会创建一个新的bean,这个变量就是新bean的引用。</li> <li><code><jsp:useBean></code>必须有一个“id”属性,这个属性声明了JSP中引用bean时所用的变量名。</li> <li>如果<code><jsp:useBean></code>中没有“scope”属性,作用域默认为页面(page)作用域。</li> <li>“class”属性是可选的,它声明了创建一个新bean时使用的类类型。这个类型必须是公共的、非抽象的,而且有一个公共的无参数构造函数。</li> <li>如果在<code><jsp:useBean></code>中放了一个“type”属性,bean必须能强制转换成这种类型。</li> <li><code><jsp:useBean></code>标记可以有一个体,体中的内容会有条件地运行,只有当创建一个新的bean作为<code><jsp:useBean></code>的结果时,才会运行体中的内容[这说明,指定(或默认)作用域中不存在有该“id”的bean]。</li> <li><code><jsp:useBean></code>体的主要作用是使用<code><jsp:setProperty></code>设置新bean的性质。</li> <li><code><jsp:setProperty></code>必须有一个name属性(它要与<code><jsp:useBean></code>的“id”匹配),还要有一个“property”属性。“property”属性必须是一个具体的性质名,或者是通配符“*”。</li> <li>如果没有包含“value”属性,只有当一个请求参数的名与性质名匹配时,容器才会设置性质值。如果“property”属性使用通配符(*),容器会为所有与某个请求参数名匹配的性质设置值。(其他性质不受影响)</li> <li>如果请求参数名与性质名不同,但是你想把性质的值设置为请求参数值,可以在<code><jsp:setProperty></code>标记中使用“param”属性。</li> <li><code><jsp:setProperty></code>动作使用自省将“性质”匹配到一个JavaBean设置方法。如果性质是“*”,JSP将迭代处理所有请求参数来设置JavaBean性质。</li> <li>性质值可以是String或基本类型,<code><jsp:setProperty></code>标准动作会自动完成转换。</li> </ul> <h2 id="包含复习">包含复习</h2> <ul> <li>通过使用两种包含机制之一(include指令或<code><jsp:include></code>标准动作),可以利用可重用的组件创建页面。</li> <li>include指令在转换时完成包含,只发生一次。所以如果包含的内容一经部署后不太可能改变,使用include指令就很合适。</li> <li>include指令实际上只是复制被包含文件中的所有内容,把它粘贴到有include指令的页面中。容器把所有被包含文件的内容合并起来,只编译一个文件来生成servlet。在运行时,有include指令的页面将成为一个“大”页面,就像是你自己把所有源代码键入到一个文件中一样。</li> <li><code><jsp:incldue></code>标准动作在运行时把被包含页面的响应包含到原页面中。所以如果包含的内容在部署之后可能更新,include标准动作就很适用,此时不适用include指令。</li> <li>这两种机制都能包含静态HTML页面,也可包含动态元素(例如,有EL表达式的JSP代码)。</li> <li>include指令是唯一一个对位置敏感的指令,所包含的内容会插入到页面中include指令所在的位置。</li> <li>include指令和include标准动作的属性命名不一致,指令使用“file”属性,而标准动作使用“page”属性。</li> <li>在你的可重用组建中,一定要去掉开始和结束标记。否则,生成的输出会有嵌套的开始和结束标记,对于这种嵌套的开始和结束标记,并非所有浏览器都能处理。设计和构造可重用部件时,要知道它们会包含/插入到别的页面中。</li> <li>可以在<code><jsp:include></code>的体中使用<code><jsp:param></code>标准动作设置(或替换)请求参数,用来定制所包含的文件。</li> <li><code><jsp:param></code>也可以用在<code><jsp:forward></code>标记的体中。</li> <li><code><jsp:param></code>只能放在<code><jsp:include></code>或<code><jsp:forward></code>标准动作中。</li> <li>如果<code><jsp:param></code>中使用的参数名已经有一个值(作为请求参数),新值会覆盖原来的值。否则,就会向请求增加一个新的请求参数。</li> <li>对被包含资源有一些限制:它不能改变相应状态码或设置首部。</li> <li><code><jsp:forward></code>标准动作可以把请求转发到同一个Web应用中的另一个资源(就像使用RequestDispatcher一样)。</li> <li>发生转发时,会首先清空响应缓冲区!请求转发到的目标资源会先清空输出。所以转发前写至相应的所有内容都会清掉。</li> <li>如果在转发之前先提交响应(例如,通过调用out.flush()),会把刷新输出的内容发送给客户,但是仅此而已。不会发生转发,原页面的余下部分不会得到处理。</li> </ul> <h1 id="jstl-1">JSTL</h1> <h2 id="cout"><code><c:out></code></h2> <ul> <li><p><code><c:out></code>用于输出,可以通过escapeXml指定是否转义XML字符,默认值为true</p> <pre class="prettyprint"><code class="language-jsp hljs cs"><c:<span class="hljs-keyword">out</span> <span class="hljs-keyword">value</span>=<span class="hljs-string">'${pageContext.currentTip}'</span> escapeXml=<span class="hljs-string">'true'</span>/></code></pre></li> <li><p><code><c:out></code>可以指定默认值:</p> <pre class="prettyprint"><code class="language-jsp hljs cs"><c:<span class="hljs-keyword">out</span> <span class="hljs-keyword">value</span>=<span class="hljs-string">'${user}'</span> <span class="hljs-keyword">default</span>=<span class="hljs-string">'guest'</span>/></code></pre></li> </ul> <h2 id="cforeach"><code><c:forEach></code></h2> <ul> <li><p><code><c:forEach></code>用于循环:</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">c:forEach</span> <span class="hljs-attribute">var</span>=<span class="hljs-value">"movie"</span> <span class="hljs-attribute">items</span>=<span class="hljs-value">"${movieList}"</span>></span> <span class="hljs-tag"><<span class="hljs-title">tr</span>></span><span class="hljs-tag"><<span class="hljs-title">td</span>></span>${movie}<span class="hljs-tag"></<span class="hljs-title">td</span>></span><span class="hljs-tag"></<span class="hljs-title">tr</span>></span> <span class="hljs-tag"></<span class="hljs-title">c:forEach</span>></span></code></pre></li> <li><p><code><c:forEach></code>可以嵌套</p></li> </ul> <h2 id="cif"><code><c:if></code></h2> <pre class="prettyprint"><code class="language-jsp hljs bash"><c:<span class="hljs-keyword">if</span> test=<span class="hljs-string">"<span class="hljs-variable">${useType eq 'member'}</span>"</span>> <jsp:include page=<span class="hljs-string">"inputComments.jsp"</span>/> </c:<span class="hljs-keyword">if</span>></code></pre> <h2 id="cchoosecwhencotherwise"><code><c:choose></code>、<code><c:when></code>、<code><c:otherwise></code></h2> <pre class="prettyprint"><code class="language-jsp hljs r"><c:choose> <c:when test=<span class="hljs-string">"${user} == 'admin'"</span>> <span class="hljs-keyword">...</span> </c:when> <c:when test=<span class="hljs-string">"${user} == 'guest'"</span>> <span class="hljs-keyword">...</span> </c:when> <c:other> <span class="hljs-keyword">...</span> </c:other> </c:choose></code></pre> <h2 id="cset"><code><c:set></code></h2> <ul> <li><p>“var”用于设置属性。可以有体也可以没体。</p> <pre class="prettyprint"><code class="language-jsp hljs cs"><c:<span class="hljs-keyword">set</span> <span class="hljs-keyword">var</span>=<span class="hljs-string">"userLevel"</span> scope=<span class="hljs-string">"session"</span> <span class="hljs-keyword">value</span>=<span class="hljs-string">"Cowboy"</span>/> <c:<span class="hljs-keyword">set</span> <span class="hljs-keyword">var</span>=<span class="hljs-string">"userLevel"</span> scope=<span class="hljs-string">"session"</span>> Cowboy </c:<span class="hljs-keyword">set</span>></code></pre> <ul> <li>scope是可选的。</li> </ul></li> <li><p>“target”用于设置bean性质或Map值。可以有体也可以没体。</p> <pre class="prettyprint"><code class="language-jsp hljs bash"><c:<span class="hljs-keyword">set</span> target=<span class="hljs-string">"<span class="hljs-variable">${PetMap}</span>"</span> property=<span class="hljs-string">"dogName"</span> value=<span class="hljs-string">"Clover"</span>/> <c:<span class="hljs-keyword">set</span> target=<span class="hljs-string">"<span class="hljs-variable">${person}</span>"</span> property=<span class="hljs-string">"name"</span>> <span class="hljs-variable">${foo.name}</span> </c:<span class="hljs-keyword">set</span>></code></pre></li> <li><p><code><c:set></code>中不能同时有“var”和“target”属性。</p></li> <li>“scope”是可选的,如果没有这个属性,则默认为页面(page)作用域。</li> <li>如果“value”为null,“var”指定的属性将被删除!</li> <li>如果“var”指定的属性不存在,则会创建一个属性,但仅当“value”不为null时才会创建新属性。</li> <li>如果“target”表达式为null,容器会抛出一个异常。</li> <li>“target”中要放入一个能解析为实际对象的表达式。如果放入一个String直接量(表示bean或Map的“id”名),这是不行的。换句话说,“target”并非用来放bean或Map的属性名,而是用于指定具体的属性对象。</li> <li>如果“target”表达式不是一个Map或bean,容器会抛出一个异常。</li> <li>如果“target”表达式是一个bean,但是这个bean没有与“property”匹配的性质,容器就会抛出一个异常。记住EL表达式<code>${bean.notAProperty}</code>也会抛出一个异常。</li> </ul> <h2 id="cremove"><code><c:remove></code></h2> <ul> <li><p>删除属性:</p> <pre class="prettyprint"><code class="language-jsp hljs cs"><c:remove <span class="hljs-keyword">var</span>=<span class="hljs-string">"userStatus"</span> scope=<span class="hljs-string">"request"</span>></code></pre></li> </ul> <h2 id="cimport和cparam"><code><c:import></code>和<code><c:param></code></h2> <ul> <li><p>包含内容</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">c:import</span> <span class="hljs-attribute">url</span>=<span class="hljs-value">"http://www.cynhard.com/index.html"</span>/></span></code></pre></li> <li><p>可以到包含应用之外的内容</p></li> <li><code><c:param></code>定制包含的内容</li> </ul> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">c:import</span> <span class="hljs-attribute">url</span>=<span class="hljs-value">"Header.jsp"</span>></span> <span class="hljs-tag"><<span class="hljs-title">c:param</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"subTitle"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"We are good"</span>/></span> <span class="hljs-tag"></<span class="hljs-title">c:import</span>></span></code></pre> <h2 id="curl"><code><c:url></code></h2> <ul> <li><p>在需要时重写URL</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">a</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"<c:url value='inputComments.jsp'/>"</span>></span>Click here<span class="hljs-tag"></<span class="hljs-title">a</span>></span></code></pre></li> <li><p>URL需要编码时,可以在体内写参数</p> <pre class="prettyprint"><code class="language-jsp hljs livecodeserver"><c:url <span class="hljs-built_in">value</span>=<span class="hljs-string">"/inputComments.jsp"</span> var=<span class="hljs-string">"inputURL"</span>> <c:<span class="hljs-built_in">param</span> name=<span class="hljs-string">"firstName"</span> <span class="hljs-built_in">value</span>=<span class="hljs-string">"${first}"</span>/> <c:<span class="hljs-built_in">param</span> name=<span class="hljs-string">"lastName"</span> <span class="hljs-built_in">value</span>=<span class="hljs-string">"${last}"</span>/> </c:url></code></pre></li> </ul> <h2 id="错误页面">错误页面</h2> <h3 id="通过page指令建立错误页面">通过page指令建立错误页面</h3> <ul> <li><p>错误页面(errorPage.jsp):</p> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%@</span> page isErrorPage=<span class="hljs-string">"true"</span><span class="hljs-variable">%></span></code></pre></li> <li><p>处理页面:</p> <pre class="prettyprint"><code class="language-jsp hljs mel"><<span class="hljs-variable">%@</span> page errorPage=<span class="hljs-string">"errorPage.jsp"</span> <span class="hljs-variable">%></span></code></pre></li> </ul> <h3 id="dd中配置错误页面">DD中配置错误页面</h3> <ul> <li><p>通过异常配置错误页面</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">error-page</span>></span> <span class="hljs-tag"><<span class="hljs-title">exception-type</span>></span>java.lang.Throwable<span class="hljs-tag"></<span class="hljs-title">exception-type</span>></span> <span class="hljs-tag"><<span class="hljs-title">location</span>></span>/errorPage.jsp<span class="hljs-tag"></<span class="hljs-title">location</span>></span> <span class="hljs-tag"></<span class="hljs-title">error-page</span>></span></code></pre></li> <li><p>通过状态码配置错误页面</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">error-page</span>></span> <span class="hljs-tag"><<span class="hljs-title">error-code</span>></span>404<span class="hljs-tag"></<span class="hljs-title">error-code</span>></span> <span class="hljs-tag"><<span class="hljs-title">location</span>></span>/notFoundError.jsp<span class="hljs-tag"></<span class="hljs-title">location</span>></span> <span class="hljs-tag"></<span class="hljs-title">error-page</span>></span></code></pre></li> </ul> <h3 id="获取错误对象">获取错误对象</h3> <pre class="prettyprint"><code class="language-jsp hljs r"><%@ page isErrorPage=<span class="hljs-string">"true"</span>%> <span class="hljs-keyword">...</span> ${pageContext.exception}</code></pre> <h3 id="ccatch捕获异常"><code><c:catch></code>捕获异常</h3> <ul> <li><p>捕获并吞掉异常</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">c:catch</span>></span> <span class="vbscript"><% <span class="hljs-built_in">int</span> x = <span class="hljs-number">10</span>/<span class="hljs-number">0</span>; %></span> <span class="hljs-tag"></<span class="hljs-title">c:catch</span>></span></code></pre></li> <li><p>获取异常对象</p></li> </ul> <pre class="prettyprint"><code class="language-jsp hljs cs"><c:<span class="hljs-keyword">catch</span> <span class="hljs-keyword">var</span>=<span class="hljs-string">"myException"</span>> <% <span class="hljs-keyword">int</span> x = <span class="hljs-number">10</span>/<span class="hljs-number">0</span>; %> </c:<span class="hljs-keyword">catch</span>> ${myException.message}</code></pre> <h2 id="定制标记库">定制标记库</h2> <h3 id="tld文件解析">TLD文件解析</h3> <ul> <li><p>TLD文件</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-pi"><?xml version="1.0" encoding="ISO-8859-1"?></span> <span class="hljs-doctype"><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"></span> <span class="hljs-tag"><<span class="hljs-title">taglib</span>></span> <span class="hljs-tag"><<span class="hljs-title">tlibversion</span>></span>1.0<span class="hljs-tag"></<span class="hljs-title">tlibversion</span>></span> <span class="hljs-tag"><<span class="hljs-title">jspversion</span>></span>1.1<span class="hljs-tag"></<span class="hljs-title">jspversion</span>></span> <span class="hljs-tag"><<span class="hljs-title">shortname</span>></span>Tag Library for Openfire 2.0<span class="hljs-tag"></<span class="hljs-title">shortname</span>></span> <span class="hljs-tag"><<span class="hljs-title">uri</span>></span>http://www.igniterealtime.org/<span class="hljs-tag"></<span class="hljs-title">uri</span>></span> <span class="hljs-tag"><<span class="hljs-title">info</span>></span>Tab Library for Openfire Admin Console<span class="hljs-tag"></<span class="hljs-title">info</span>></span> <span class="hljs-tag"><<span class="hljs-title">tag</span>></span> <span class="hljs-tag"><<span class="hljs-title">description</span>></span>some thing<span class="hljs-tag"></<span class="hljs-title">description</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>tabs<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">tagclass</span>></span>org.jivesoftware.admin.TabsTag<span class="hljs-tag"></<span class="hljs-title">tagclass</span>></span> <span class="hljs-tag"><<span class="hljs-title">bodycontent</span>></span>JSP<span class="hljs-tag"></<span class="hljs-title">bodycontent</span>></span> <span class="hljs-tag"><<span class="hljs-title">info</span> /></span> <span class="hljs-tag"><<span class="hljs-title">attribute</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>css<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">required</span>></span>false<span class="hljs-tag"></<span class="hljs-title">required</span>></span> <span class="hljs-tag"><<span class="hljs-title">rtexprvalue</span>></span>true<span class="hljs-tag"></<span class="hljs-title">rtexprvalue</span>></span> <span class="hljs-tag"></<span class="hljs-title">attribute</span>></span> <span class="hljs-tag"><<span class="hljs-title">attribute</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>currentcss<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">required</span>></span>false<span class="hljs-tag"></<span class="hljs-title">required</span>></span> <span class="hljs-tag"><<span class="hljs-title">rtexprvalue</span>></span>true<span class="hljs-tag"></<span class="hljs-title">rtexprvalue</span>></span> <span class="hljs-tag"></<span class="hljs-title">attribute</span>></span> <span class="hljs-tag"></<span class="hljs-title">tag</span>></span> <span class="hljs-tag"></<span class="hljs-title">taglib</span>></span></code></pre></li> <li><p>解析</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">tlibversion</span>></span>1.0<span class="hljs-tag"></<span class="hljs-title">tlibversion</span>></span></code></pre> <ul> <li>必要,开发人员方这个标记来声明标记库的版本。</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">shortname</span>></span>Tag Library for Openfire 2.0<span class="hljs-tag"></<span class="hljs-title">shortname</span>></span></code></pre> <ul> <li>必要,主要由工具使用</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">uri</span>></span>http://www.igniterealtime.org/<span class="hljs-tag"></<span class="hljs-title">uri</span>></span></code></pre> <ul> <li>必要,taglib指令中使用的唯一名</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">description</span>></span>some thing<span class="hljs-tag"></<span class="hljs-title">description</span>></span></code></pre> <ul> <li>可选,但是有这个标记确实很有好处</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">name</span>></span>tabs<span class="hljs-tag"></<span class="hljs-title">name</span>></span></code></pre> <ul> <li>必要!标记中的名字</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">tagclass</span>></span>org.jivesoftware.admin.TabsTag<span class="hljs-tag"></<span class="hljs-title">tagclass</span>></span></code></pre> <ul> <li>必要!容器根据此找到实现tag功能的类。</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">bodycontent</span>></span>JSP<span class="hljs-tag"></<span class="hljs-title">bodycontent</span>></span></code></pre> <ul> <li>必要!说明标记的体中应该是什么内容。</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">attribute</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>css<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">required</span>></span>false<span class="hljs-tag"></<span class="hljs-title">required</span>></span> <span class="hljs-tag"><<span class="hljs-title">rtexprvalue</span>></span>true<span class="hljs-tag"></<span class="hljs-title">rtexprvalue</span>></span> <span class="hljs-tag"></<span class="hljs-title">attribute</span>></span></code></pre> <ul> <li><p>标记的属性</p> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">name</span>></span>css<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">required</span>></span>false<span class="hljs-tag"></<span class="hljs-title">required</span>></span></code></pre> <ul> <li>指定属性名,required说明该属性是否必须</li> </ul> <pre class="prettyprint"><code class="language-xml hljs "><span class="hljs-tag"><<span class="hljs-title">rtexprvalue</span>></span>true<span class="hljs-tag"></<span class="hljs-title">rtexprvalue</span>></span></code></pre> <ul> <li>指定属性是否运行时表达式(也就是说,不必非得是String直接量)</li> </ul></li> </ul></li> </ul> <h3 id="使用定制标记">使用定制标记</h3> <ul> <li><p>jsp</p> <pre class="prettyprint"><code class="language-jsp hljs r"><%@ taglib prefix=<span class="hljs-string">"mine"</span> uri=<span class="hljs-string">"http://www.igniterealtime.org/"</span>%> <span class="hljs-keyword">...</span> <mine:tabs css=<span class="hljs-string">"${userName}"</span>%></code></pre></li> <li><p>解析</p> <pre class="prettyprint"><code class="language-jsp hljs ini"><span class="hljs-setting">prefix=<span class="hljs-value"><span class="hljs-string">"mine"</span></span></span></code></pre> <ul> <li>指定前缀</li> </ul> <pre class="prettyprint"><code class="language-jsp hljs ini"><span class="hljs-setting">uri=<span class="hljs-value"><span class="hljs-string">"http://www.igniterealtime.org/"</span></span></span></code></pre> <ul> <li>对应TLD中的uri:<code><uri>http://www.igniterealtime.org/</uri></code></li> </ul> <pre class="prettyprint"><code class="language-jsp hljs css"><span class="hljs-tag">mine</span><span class="hljs-pseudo">:tabs</span></code></pre> <ul> <li>mine对应前缀,tabs对应TLD中的tag名字:<code><name>tabs</name></code></li> </ul> <pre class="prettyprint"><code class="language-jsp hljs bash">css=<span class="hljs-string">"<span class="hljs-variable">${userName}</span>"</span></code></pre> <ul> <li>css对应TLD中的属性名:<code><name>css</name></code></li> <li>由于TLD中指定css属性可以为运行时表达式:<code><rtexprvalue>true</rtexprvalue></code>,因此这里可以放置表达式:<code>${useName}</code></li> </ul></li> </ul> <h3 id="定制标记处理器">定制标记处理器</h3> <pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment">// SimpleTagSupport实现了定制标记所要完成的工作。</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AdvisorTagHandler</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SimpleTagSupport</span> {</span> <span class="hljs-comment">// JSP使用TLD中声明的名字调用标记时,容器会调用doTag()。</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doTag</span>() <span class="hljs-keyword">throws</span> JspException, IOException { <span class="hljs-comment">// ...</span> } <span class="hljs-comment">// 容器调用这个方法将值设置为标记属性的值。它使用JavaBean性质命名约定得出应该向setUser()方法发送一个“user”属性。</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setUser</span>(String user) { } }</code></pre> <h3 id="rtexprvalue"><code><rtexprvalue></code></h3> <ul> <li>如果没有<code><rtexprvalue></code>或<code><rtexprvalue></code>的值为false,则不能在属性值中用表达式。</li> <li><p>属性的值允许rtexprvalue时,可以使用3种表达式。</p> <ul> <li><p>EL表达式</p> <pre class="prettyprint"><code class="language-jsp hljs bash"><mine:advice user=<span class="hljs-string">"<span class="hljs-variable">${userName}</span>"</span>/></code></pre></li> <li><p>脚本表达式</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">mine:advide</span> <span class="hljs-attribute">user</span>=<span class="hljs-value">'<%= request.getAttribute("username") %>'</span> /></span></code></pre></li> <li><p><code><jsp:attribute></code>标准动作</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">mine:advice</span>></span> <span class="hljs-tag"><<span class="hljs-title">jsp:attribute</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"user"</span>></span>${userName}<span class="hljs-tag"></<span class="hljs-title">jsp:attribute</span>></span> <span class="hljs-tag"></<span class="hljs-title">mine:advice</span>></span></code></pre></li> </ul></li> </ul> <h3 id="标记体">标记体</h3> <ul> <li><p><code><bodycontent></code>的取值</p> <ul> <li><code><bodycontent>empty</bodycontent></code> 不能有体</li> <li><code><bodycontent>scriptless</bodycontent></code> 不能有脚本元素(scriptlet、脚本表达式和声明),但是可以是模板文本和EL,还可以是定制和标准动作。</li> <li><code><bodycontent>tagdependent</bodycontent></code>标记体要看作是纯文本,所以不会计算EL,也不会触发标记/动作。</li> <li><code><bodycontent>JSP</bodycontent></code> 能放在JSP中的东西都能放在这个标记体中</li> </ul></li> <li><p>没有体的标记,有3种调用方法</p> <ul> <li>空标记: <code><mine:advice user="${userName}"/></code></li> <li>开始和结束标记之间没有内容的标记:<code><mine:advice user="${userName}"></mine:advice></code></li> <li><p>在开始和结束之间只有<code><jsp:attribute></code>标记</p> <pre class="prettyprint"><code class="language-jsp hljs xml"><span class="hljs-tag"><<span class="hljs-title">mine:advice</span>></span> <span class="hljs-tag"><<span class="hljs-title">jsp:attribute</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"user"</span>></span>${userName}<span class="hljs-tag"></<span class="hljs-title">jsp:attribute</span>></span> <span class="hljs-tag"></<span class="hljs-title">mine:advice</span>></span></code></pre></li> </ul></li> </ul> <h3 id="tagliburi">taglib<code><uri></code></h3> <ul> <li>容器会查找TLD中<code><uri></code>与taglib指令中uri值之间的匹配。uri不一定是具体标记处理器的位置。</li> </ul> <h3 id="tld部署位置">TLD部署位置</h3> <ul> <li>容器会在4个位置查找TLD: <br> <ol> <li>在WEB-INF目录中查找</li> <li>在WEB-INF的一个字目录中查找</li> <li>在WEB-INF/lib下一个JAR文件中的META-INF目录中查找</li> <li>在WEB-INF/lib下一个JAR文件中的META-INF目录的子目录中查找</li> </ol></li> </ul> <h3 id="使用多个标记库">使用多个标记库</h3> <ul> <li>确保taglib uri名是唯一的。</li> <li>不要使用保留的前缀。(jsp,jspx,java,javax,servlet,sun,sunw)</li> </ul> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1276560836910923776"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(Web)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1950230804957294592.htm" title="SpringMVC执行流程(原理),通俗易懂" target="_blank">SpringMVC执行流程(原理),通俗易懂</a> <span class="text-muted">国服冰</span> <a class="tag" taget="_blank" href="/search/SpringMVC/1.htm">SpringMVC</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a> <div>SpringMVC执行流程(原理),通俗易懂一、图解SpringMVC流程二、进一步理解Springmvc的执行流程1、导入依赖2、建立展示的视图3、web.xml4、spring配置文件springmvc-servlet5、Controller6、tomcat配置7、访问的url8、视图页面一、图解SpringMVC流程图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提</div> </li> <li><a href="/article/1950219166367674368.htm" title="包含日志获取webshell" target="_blank">包含日志获取webshell</a> <span class="text-muted">陈望_ning</span> <div>日志文件关闭:Apache目录下的httpd.conf文件#ErrorLog"logs/error.log"#CustomLog"logs/access.log"common加#号为注释不产生日志文件如果去掉#将会在Apache/logs/目录下产生日志文件linux:access_logerror_logwindows:access.logerror.logaccess_log每一行记录了一次网</div> </li> <li><a href="/article/1950208989954371584.htm" title="Selenium 特殊控件操作与 ActionChains 实践详解" target="_blank">Selenium 特殊控件操作与 ActionChains 实践详解</a> <span class="text-muted">小馋喵知识杂货铺</span> <a class="tag" taget="_blank" href="/search/selenium/1.htm">selenium</a><a class="tag" taget="_blank" href="/search/%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/1.htm">测试工具</a> <div>1.下拉框单选操作(a)使用SeleniumSelect类(标准HTML标签)Selenium提供了内置的Select类用于操作标准下拉框,这种方式简单且直观。fromselenium.webdriver.support.uiimportSelect#定位下拉框dropdown=Select(driver.find_element("id","dropdown_id"))#通过以下三种方式选择单个</div> </li> <li><a href="/article/1950205711409541120.htm" title="selenium特殊场景处理" target="_blank">selenium特殊场景处理</a> <span class="text-muted">Monica_ll</span> <a class="tag" taget="_blank" href="/search/Selenium/1.htm">Selenium</a><a class="tag" taget="_blank" href="/search/selenium/1.htm">selenium</a><a class="tag" taget="_blank" href="/search/chrome/1.htm">chrome</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a> <div>文章目录前言一、多窗口处理二、浏览器弹窗处理包含alert、confirm、prompt三、鼠标和键盘事件处理前言在使用selenium操作浏览器的过程中可能需要借助键盘和鼠标功能完成一些操作,或者操作弹窗处理,本文主要是整理自己工作过程中使用过的一些方法一、多窗口处理在实际测试过程中经常会有通过点击或者连接打开新的窗口,这种情况下就需要切换webDriver到对应浏览器对象才能操作新窗口的元素。</div> </li> <li><a href="/article/1950193733681082368.htm" title="基于Python的AI健康助手:开发与部署全攻略" target="_blank">基于Python的AI健康助手:开发与部署全攻略</a> <span class="text-muted">AI算力网络与通信</span> <a class="tag" taget="_blank" href="/search/AI%E7%AE%97%E5%8A%9B%E7%BD%91%E7%BB%9C%E4%B8%8E%E9%80%9A%E4%BF%A1%E5%8E%9F%E7%90%86/1.htm">AI算力网络与通信原理</a><a class="tag" taget="_blank" href="/search/AI%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%A4%A7%E6%95%B0%E6%8D%AE%E6%9E%B6%E6%9E%84/1.htm">AI人工智能大数据架构</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a> <div>基于Python的AI健康助手:开发与部署全攻略关键词:Python、AI健康助手、机器学习、自然语言处理、Flask、部署、健康管理摘要:本文将详细介绍如何使用Python开发一个AI健康助手,从需求分析、技术选型到核心功能实现,再到最终部署上线的完整过程。我们将使用自然语言处理技术理解用户健康咨询,通过机器学习模型提供个性化建议,并展示如何用Flask框架构建Web应用接口。文章包含大量实际代</div> </li> <li><a href="/article/1950190325960077312.htm" title="Jupyter Notebook:数据科学的“瑞士军刀”" target="_blank">Jupyter Notebook:数据科学的“瑞士军刀”</a> <span class="text-muted">a小胡哦</span> <a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%9F%BA%E7%A1%80/1.htm">机器学习基础</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a> <div>在数据科学的世界里,JupyterNotebook是一个不可或缺的工具,它就像是数据科学家手中的“瑞士军刀”,功能强大且灵活多变。今天,就让我们一起深入了解这个神奇的工具。一、JupyterNotebook是什么?JupyterNotebook是一个开源的Web应用程序,它允许你创建和共享包含实时代码、方程、可视化和解释性文本的文档。它支持多种编程语言,其中Python是最常用的语言之一。Jupy</div> </li> <li><a href="/article/1950190199627640832.htm" title="selenium 特殊场景处理" target="_blank">selenium 特殊场景处理</a> <span class="text-muted"></span> <div>文章目录前言一、windows的弹窗二、内嵌网页frame三、页签切换四、截图五、弹窗六、JS执行总结前言selenium处理web操作师,有很多特殊的情况需要处理,例如弹窗、内嵌网页,页签切换,js执行等,下面介绍一些可能会遇到的特殊场景一、windows的弹窗importwin32com.client'''创建了一个WScript.ShellCOM(ComponentObjectModel)对</div> </li> <li><a href="/article/1950187554129113088.htm" title="Django学习笔记(一)" target="_blank">Django学习笔记(一)</a> <span class="text-muted"></span> <div>学习视频为:pythondjangoweb框架开发入门全套视频教程一、安装pipinstalldjango==****检查是否安装成功django.get_version()二、django新建项目操作1、新建一个项目django-adminstartprojectproject_name2、新建APPcdproject_namedjango-adminstartappApp注:一个project</div> </li> <li><a href="/article/1950185537319006208.htm" title="新手如何通过github pages静态网站托管搭建个人网站和项目站点" target="_blank">新手如何通过github pages静态网站托管搭建个人网站和项目站点</a> <span class="text-muted">vvandre</span> <a class="tag" taget="_blank" href="/search/Web%E6%8A%80%E6%9C%AF/1.htm">Web技术</a><a class="tag" taget="_blank" href="/search/github/1.htm">github</a> <div>一、githubpages静态网站托管介绍githubpages它是一个免费快捷的静态网站托管服务。对比传统建站,它有哪些优点呢?在传统方式中,首先要租用服务器,服务器上需要运行外部程序,还需要再购买域名,要配置SSL证书,最后还要配置DNS,将域名解析到服务器。这一套繁琐操作,基本上就把小白劝退了。graphTDA[租用服务器]-->B[部署Web应用(运行外部程序,如Nginx)]B-->C[</div> </li> <li><a href="/article/1950174441992417280.htm" title="使用Python和Gradio构建实时数据可视化工具" target="_blank">使用Python和Gradio构建实时数据可视化工具</a> <span class="text-muted">PythonAI编程架构实战家</span> <a class="tag" taget="_blank" href="/search/%E4%BF%A1%E6%81%AF%E5%8F%AF%E8%A7%86%E5%8C%96/1.htm">信息可视化</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a> <div>使用Python和Gradio构建实时数据可视化工具关键词:Python、Gradio、数据可视化、实时数据、Web应用、交互式界面、数据科学摘要:本文将详细介绍如何使用Python和Gradio框架构建一个实时数据可视化工具。我们将从基础概念开始,逐步深入到核心算法实现,包括数据处理、可视化技术以及Gradio的交互式界面设计。通过实际项目案例,读者将学习如何创建一个功能完整、响应迅速的实时数据</div> </li> <li><a href="/article/1950174315609649152.htm" title="Python Gradio:实现交互式图像编辑" target="_blank">Python Gradio:实现交互式图像编辑</a> <span class="text-muted">PythonAI编程架构实战家</span> <a class="tag" taget="_blank" href="/search/Python%E7%BC%96%E7%A8%8B%E4%B9%8B%E9%81%93/1.htm">Python编程之道</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a> <div>PythonGradio:实现交互式图像编辑关键词:Python,Gradio,交互式图像编辑,计算机视觉,深度学习,图像处理,Web应用摘要:本文将深入探讨如何使用Python的Gradio库构建交互式图像编辑应用。我们将从基础概念开始,逐步介绍Gradio的核心功能,并通过实际代码示例展示如何实现各种图像处理功能。文章将涵盖图像滤镜应用、对象检测、风格迁移等高级功能,同时提供完整的项目实战案例</div> </li> <li><a href="/article/1950170156898512896.htm" title="登录功能详解" target="_blank">登录功能详解</a> <span class="text-muted">开往1982</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%99%BB%E5%BD%95/1.htm">登录</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a> <div>本项目由maven项目改造springboot项目导入依赖org.springframework.bootspring-boot-starter-parent2.7.6org.springframework.bootspring-boot-starter-web2.7.6org.springframework.bootspring-boot-starter-test2.7.5org.springf</div> </li> <li><a href="/article/1950169524384886784.htm" title="【Java Web实战】从零到一打造企业级网上购书网站系统 | 完整开发实录(三)" target="_blank">【Java Web实战】从零到一打造企业级网上购书网站系统 | 完整开发实录(三)</a> <span class="text-muted">笙囧同学</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F/1.htm">状态模式</a> <div>核心功能设计用户管理系统用户管理是整个系统的基础,我设计了完整的用户生命周期管理:用户注册流程验证失败验证通过验证失败验证通过用户名已存在用户名可用失败成功用户访问注册页面填写注册信息前端表单验证显示错误提示提交到后端后端数据验证返回错误信息用户名唯一性检查提示用户名重复密码加密处理保存用户信息保存成功?显示系统错误注册成功跳转登录页面登录认证机制深度解析我实现了一套企业级的多层次安全认证机制:认</div> </li> <li><a href="/article/1950169525244719104.htm" title="从零到一:基于差分隐私决策树的客户购买预测系统实战开发" target="_blank">从零到一:基于差分隐私决策树的客户购买预测系统实战开发</a> <span class="text-muted">笙囧同学</span> <a class="tag" taget="_blank" href="/search/%E5%86%B3%E7%AD%96%E6%A0%91/1.htm">决策树</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a> <div>作者简介:笙囧同学,中科院计算机大模型方向硕士,全栈开发爱好者联系方式:3251736703@qq.com各大平台账号:笙囧同学座右铭:偷懒是人生进步的阶梯文章导航快速导航前言-项目背景与价值项目概览-系统架构与功能技术深度解析-核心算法原理️系统实现详解-工程实践细节性能评估与分析-实验结果分析Web系统开发-前后端开发部署与运维-DevOps实践完整复现指南-手把手教程️实践案例与故障排除-问</div> </li> <li><a href="/article/1950164483057971200.htm" title="14.tornado操作之应用Websocket协议实现聊天室功能" target="_blank">14.tornado操作之应用Websocket协议实现聊天室功能</a> <span class="text-muted">孤寒者</span> <a class="tag" taget="_blank" href="/search/Tornado%E6%A1%86%E6%9E%B6%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E6%88%98/1.htm">Tornado框架从入门到实战</a><a class="tag" taget="_blank" href="/search/websocket/1.htm">websocket</a><a class="tag" taget="_blank" href="/search/tornado/1.htm">tornado</a><a class="tag" taget="_blank" href="/search/%E8%81%8A%E5%A4%A9%E5%AE%A4%E5%8A%9F%E8%83%BD%E5%AE%9E%E7%8E%B0/1.htm">聊天室功能实现</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a> <div>目录:每篇前言:1.什么是WebSocket(1)定义(2)优点(3)和HTTP对比(4)适用场景2.WebSocket关键方法3.本tornado项目中使用WebSocket(1)准备一个聊天室的页面:第一步:编写视图:第二步:编写接口:(app.py中加入以下接口!)第三步:编写前端页面:测试接口——响应OK!(2)使用WebSocket:(3)聊天室的聊天功能的最终实现:第一步:战前准备第二</div> </li> <li><a href="/article/1950163219788132352.htm" title="webSocket双向通信" target="_blank">webSocket双向通信</a> <span class="text-muted">@泽栖</span> <a class="tag" taget="_blank" href="/search/websocket/1.htm">websocket</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/1.htm">网络协议</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a> <div>webSocket基础使用webSocket小说明:作用浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。WebSocket与HTTP最大的区别HTTP通信是单向的,基于请求响应模式WebSocket支持双向通信。实现长连接适用场景:消息通信,视频弹幕,实时信息,等双向通信的使用需求使用:引入maven依赖org.springfram</div> </li> <li><a href="/article/1950145701786742784.htm" title="java web开发实战经典 当当_java web项目实战开发" target="_blank">java web开发实战经典 当当_java web项目实战开发</a> <span class="text-muted">飞翔的酋长大人</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/web%E5%BC%80%E5%8F%91%E5%AE%9E%E6%88%98%E7%BB%8F%E5%85%B8/1.htm">web开发实战经典</a><a class="tag" taget="_blank" href="/search/%E5%BD%93%E5%BD%93/1.htm">当当</a> <div>本书以问题为导向,涵盖JavaWeb开发技术中所有的核心知识点;实战开发案例丰富,所有的知识案例都来源于企业真实项目,实战性和可操作性强;代码注释详细准确,结构简洁清晰;语言简明易懂,由浅入深地带你学会JavaWeb技术及应用。本书面向广大Java开发工程师和普通高校学生,可作为高等学校计算机及其相关专业Web编程技术课程教材,也可供从事JavaWeb应用开发的技术人员学习参考。¥80.00定价:</div> </li> <li><a href="/article/1950145702407499776.htm" title="构建高性能Web应用:深入Spring WebFlux" target="_blank">构建高性能Web应用:深入Spring WebFlux</a> <span class="text-muted">李多田</span> <div>本文还有配套的精品资源,点击获取简介:SpringWebFlux是Spring框架的一部分,支持反应式编程模型,适合高并发和低延迟Web应用。它提供了非阻塞I/O和事件驱动模型,优化了多核处理器资源的使用。SpringWebFlux拥有两种编程模式,核心组件包括WebHandler,RouterFunction,WebFilter,和WebSession。它与高性能服务器集成,并提供反应式HTTP</div> </li> <li><a href="/article/1950144218282389504.htm" title="为什么学习Web前端一定要掌握JavaScript?" target="_blank">为什么学习Web前端一定要掌握JavaScript?</a> <span class="text-muted">web前端学习指南</span> <div>为什么学习Web前端一定要掌握JavaScript?在前端的世界里,没有什么是JavaScript实现不了的,关于JS有一句话:凡是可以用JavaScript来写的应用,最终都会用JavaScript,JavaScript可运行在所有主要平台的所有主流浏览器上,也可运行在每一个主流操作系统的服务器端上。现如今我们在为网站写任何一个主要功能的时候都需要有懂能够用JavaScript写前端的开发人员。</div> </li> <li><a href="/article/1950143304347742208.htm" title="使用Java和Spring WebFlux构建响应式微服务" target="_blank">使用Java和Spring WebFlux构建响应式微服务</a> <span class="text-muted">微赚淘客系统开发者@聚娃科技</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>使用Java和SpringWebFlux构建响应式微服务大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何使用Java和SpringWebFlux构建响应式微服务。SpringWebFlux是Spring框架的一部分,专为创建响应式应用程序而设计。在这篇文章中,我们将介绍如何使用SpringWebFlux构建响应式微服务,包括基本概念、代码示例以及如何</div> </li> <li><a href="/article/1950141157006700544.htm" title="【Spring WebFlux】为什么 Spring 要拥抱响应式" target="_blank">【Spring WebFlux】为什么 Spring 要拥抱响应式</a> <span class="text-muted">会飞的架狗师</span> <a class="tag" taget="_blank" href="/search/Spring/1.htm">Spring</a><a class="tag" taget="_blank" href="/search/WebFlux/1.htm">WebFlux</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>在现代分布式系统中,响应式系统已成为应对高并发、低延迟需求的核心方案。但构建响应式系统并非易事——它需要框架级别的支持来解决异步处理、资源调度、背压控制等底层问题。作为Java生态中最具影响力的框架,Spring对响应式的支持并非偶然,而是技术演进的必然选择。本文将从响应式系统的构建挑战出发,剖析Spring拥抱响应式的底层逻辑。一、响应式系统的构建困境:现有方案的局限性响应式系统的核心诉求是在有</div> </li> <li><a href="/article/1950140903616212992.htm" title="Java朴实无华按天计划从入门到实战(强化速战版-66天)" target="_blank">Java朴实无华按天计划从入门到实战(强化速战版-66天)</a> <span class="text-muted">岫珩</span> <a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/%E6%97%B6%E9%97%B4%E5%AE%89%E6%8E%92/1.htm">时间安排</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E8%AE%A1%E5%88%92/1.htm">学习计划</a> <div>致敬读者感谢阅读笑口常开生日快乐⬛早点睡觉博主相关博主信息博客首页专栏推荐活动信息文章目录Java朴实无华按天计划从入门到实战(强化速战版-66天)1.基础(18)1.1JavaSE核心(5天)1.2数据库与SQL(5天)1.3前端基础(8天)2.进阶(17天)2.1JavaWeb核心(5天)2.2Mybatis与Spring全家桶(6天)2.3中间件入门(4天)2.4实践项目(2天)3.高阶(1</div> </li> <li><a href="/article/1950138256133779456.htm" title="响应式编程实践:Spring Boot WebFlux构建高性能非阻塞服务" target="_blank">响应式编程实践:Spring Boot WebFlux构建高性能非阻塞服务</a> <span class="text-muted">fanxbl957</span> <a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>博主介绍:Java、Python、js全栈开发“多面手”,精通多种编程语言和技术,痴迷于人工智能领域。秉持着对技术的热爱与执着,持续探索创新,愿在此分享交流和学习,与大家共进步。全栈开发环境搭建运行攻略:多语言一站式指南(环境搭建+运行+调试+发布+保姆级详解)感兴趣的可以先收藏起来,希望帮助更多的人响应式编程实践:SpringBootWebFlux构建高性能非阻塞服务一、引言在当今数字化时代,互</div> </li> <li><a href="/article/1950137877904027648.htm" title="Docker部署Minio" target="_blank">Docker部署Minio</a> <span class="text-muted">YiShuoChen666</span> <a class="tag" taget="_blank" href="/search/eureka/1.htm">eureka</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a><a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/minio/1.htm">minio</a> <div>一、拉取镜像dockerpullminio/minio:RELEASE.2025-04-22T22-12-26Z注:这里使用的版本是RELEASE.2025-04-22T22-12-26Z,最新的版本Web-UI界面没有管理bucket和其它的操作按钮,需要通过mc命令来实现,这对于新手很不友好二、创建目录,来存放minio的配置和将来放的文件mkdir-p/home/minio/configmk</div> </li> <li><a href="/article/1950132582230323200.htm" title="使用 C# 实现 FTP 上传的方法,包括详细的代码示例和测试代码" target="_blank">使用 C# 实现 FTP 上传的方法,包括详细的代码示例和测试代码</a> <span class="text-muted">zhxup606</span> <a class="tag" taget="_blank" href="/search/%E6%9D%8E%E5%B7%A5%E7%AF%87/1.htm">李工篇</a><a class="tag" taget="_blank" href="/search/C%23%E5%AE%9E%E6%88%98%E6%95%99%E7%A8%8B/1.htm">C#实战教程</a><a class="tag" taget="_blank" href="/search/c%23/1.htm">c#</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>以下是使用C#实现FTP上传的方法,包括详细的代码示例和测试代码。以下代码使用System.Net.FtpWebRequest实现文件上传,并附带一个简单的测试用例。C#FTP上传方法csharpusingSystem;usingSystem.IO;usingSystem.Net;publicclassFtpClient{//////上传文件到FTP服务器//////FTP服务器地址,例如ftp:</div> </li> <li><a href="/article/1950132204336115712.htm" title="《跨域资源共享CORS的深层逻辑与前端实践精要》" target="_blank">《跨域资源共享CORS的深层逻辑与前端实践精要》</a> <span class="text-muted"></span> <div>不同源头的资源交互已成为常态,而跨域资源共享(CORS)正是支撑这种交互的隐形架构。现代Web安全体系中平衡开放与防护的精妙设计。理解CORS的深层逻辑,不仅能解决实际开发中的跨域难题,更能触及网络安全与资源流通的核心矛盾,为前端工程师构建稳健的应用提供底层认知支撑。跨域资源共享的诞生,源于网络安全与应用发展的必然冲突。浏览器的同源策略,作为早期网络安全的基石,通过限制不同源文档的交互,有效阻挡了</div> </li> <li><a href="/article/1950131700457598976.htm" title="【移动端知识】移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现" target="_blank">【移动端知识】移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现</a> <span class="text-muted">问道飞鱼</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E6%8A%80%E6%9C%AF/1.htm">前端开发技术</a><a class="tag" taget="_blank" href="/search/harmonyos/1.htm">harmonyos</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/ios/1.htm">ios</a><a class="tag" taget="_blank" href="/search/%E5%A4%9Awebview%E4%BA%92%E8%AE%BF/1.htm">多webview互访</a> <div>移动端多WebView互访方案:Android、iOS与鸿蒙实现移动端多WebView互访方案:Android、iOS与鸿蒙实现一、核心架构设计二、Android平台实现1.基础通信架构2.控制器实现3.WebView安全配置三、iOS平台实现(Swift)1.WKWebView通信桥接2.AppDelegate路由控制四、鸿蒙平台实现(HarmonyOS)1.WebView通信桥接2.Abili</div> </li> <li><a href="/article/1950125273672380416.htm" title="3步搞定群晖NAS Synology Drive远程同步Obsidian笔记" target="_blank">3步搞定群晖NAS Synology Drive远程同步Obsidian笔记</a> <span class="text-muted"></span> <div>文章目录1.简介1.1软件特色演示:2.使用免费群晖虚拟机搭建群晖SynologyDrive服务,实现局域网同步2.1安装并设置SynologyDrive套件2.1局域网内同步文件测试3.内网穿透群晖SynologyDrive,实现异地多端同步3.1安装Cpolar步骤4.实现固定TCP地址同步1.简介之前我们介绍过如何免费多端同步Zotero科研文献管理软件,使用了群晖NAS虚拟机和WebDav</div> </li> <li><a href="/article/1950121289456873472.htm" title="native.js设置可缩放的webview并隐藏缩放控件" target="_blank">native.js设置可缩放的webview并隐藏缩放控件</a> <span class="text-muted">Nanayai</span> <div>需求明确:webview页面可以手指缩放,并且不要那个原生控件;实现思路:1.使用h5+封装好的方法:设置scalable属性,并在html中设置meta标签:user-scalable=yes或不设置,minimum-scale和maximum-scale需要注意不要都设为1:mui.openWindow({url:"someThing",id:"someThing",styles:{scala</div> </li> <li><a href="/article/1950119224630374400.htm" title="大厂都在用的前端缓存策略,你掌握了吗?" target="_blank">大厂都在用的前端缓存策略,你掌握了吗?</a> <span class="text-muted">AI架构全栈开发实战笔记</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E7%BC%93%E5%AD%98/1.htm">缓存</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a> <div>大厂都在用的前端缓存策略,你掌握了吗?关键词:前端缓存、HTTP缓存、ServiceWorker、CDN缓存、缓存策略、性能优化、浏览器缓存摘要:本文将深入探讨前端开发中常用的缓存策略,从浏览器缓存到ServiceWorker,从HTTP缓存头到CDN缓存,全面解析大厂都在使用的高效缓存技术。通过生动的比喻和实际代码示例,帮助开发者理解并掌握这些提升Web应用性能的关键技术。背景介绍目的和范围本文</div> </li> <li><a href="/article/16.htm" title="深入浅出Java Annotation(元注解和自定义注解)" target="_blank">深入浅出Java Annotation(元注解和自定义注解)</a> <span class="text-muted">Josh_Persistence</span> <a class="tag" taget="_blank" href="/search/Java+Annotation/1.htm">Java Annotation</a><a class="tag" taget="_blank" href="/search/%E5%85%83%E6%B3%A8%E8%A7%A3/1.htm">元注解</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3/1.htm">自定义注解</a> <div>一、基本概述        Annontation是Java5开始引入的新特征。中文名称一般叫注解。它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。     更通俗的意思是为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且是供指定的工具或</div> </li> <li><a href="/article/143.htm" title="mysql优化特定类型的查询" target="_blank">mysql优化特定类型的查询</a> <span class="text-muted">annan211</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C/1.htm">工作</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div> 本节所介绍的查询优化的技巧都是和特定版本相关的,所以对于未来mysql的版本未必适用。 1 优化count查询 对于count这个函数的网上的大部分资料都是错误的或者是理解的都是一知半解的。在做优化之前我们先来看看 真正的count()函数的作用到底是什么。 count()是一个特殊的函数,有两种非常不同的作用,他可以统计某个列值的数量,也可以统计行数。 在统</div> </li> <li><a href="/article/270.htm" title="MAC下安装多版本JDK和切换几种方式" target="_blank">MAC下安装多版本JDK和切换几种方式</a> <span class="text-muted">棋子chessman</span> <a class="tag" taget="_blank" href="/search/jdk/1.htm">jdk</a> <div>环境: MAC AIR,OS X 10.10,64位   历史: 过去 Mac 上的 Java 都是由 Apple 自己提供,只支持到 Java 6,并且OS X 10.7 开始系统并不自带(而是可选安装)(原自带的是1.6)。 后来 Apple 加入 OpenJDK 继续支持 Java 6,而 Java 7 将由 Oracle 负责提供。   在终端中输入jav</div> </li> <li><a href="/article/397.htm" title="javaScript (1)" target="_blank">javaScript (1)</a> <span class="text-muted">Array_06</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%B5%8F%E8%A7%88%E5%99%A8/1.htm">浏览器</a> <div>JavaScript 1、运算符   运算符就是完成操作的一系列符号,它有七类:   赋值运算符(=,+=,-=,*=,/=,%=,<<=,>>=,|=,&=)、算术运算符(+,-,*,/,++,--,%)、比较运算符(>,<,<=,>=,==,===,!=,!==)、逻辑运算符(||,&&,!)、条件运算(?:)、位</div> </li> <li><a href="/article/524.htm" title="国内顶级代码分享网站" target="_blank">国内顶级代码分享网站</a> <span class="text-muted">袁潇含</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/jdk/1.htm">jdk</a><a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a><a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a> <div>       现在国内很多开源网站感觉都是为了利益而做的                  当然利益是肯定的,否则谁也不会免费的去做网站      &</div> </li> <li><a href="/article/651.htm" title="Elasticsearch、MongoDB和Hadoop比较" target="_blank">Elasticsearch、MongoDB和Hadoop比较</a> <span class="text-muted">随意而生</span> <a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a><a class="tag" taget="_blank" href="/search/hadoop/1.htm">hadoop</a><a class="tag" taget="_blank" href="/search/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E/1.htm">搜索引擎</a> <div>  IT界在过去几年中出现了一个有趣的现象。很多新的技术出现并立即拥抱了“大数据”。稍微老一点的技术也会将大数据添进自己的特性,避免落大部队太远,我们看到了不同技术之间的边际的模糊化。假如你有诸如Elasticsearch或者Solr这样的搜索引擎,它们存储着JSON文档,MongoDB存着JSON文档,或者一堆JSON文档存放在一个Hadoop集群的HDFS中。你可以使用这三种配</div> </li> <li><a href="/article/778.htm" title="mac os 系统科研软件总结" target="_blank">mac os 系统科研软件总结</a> <span class="text-muted">张亚雄</span> <a class="tag" taget="_blank" href="/search/mac+os/1.htm">mac os</a> <div>1.1 Microsoft Office for Mac 2011      大客户版,自行搜索。      1.2 Latex (MacTex):      系统环境:https://tug.org/mactex/     &nb</div> </li> <li><a href="/article/905.htm" title="Maven实战(四)生命周期" target="_blank">Maven实战(四)生命周期</a> <span class="text-muted">AdyZhang</span> <a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a> <div>1. 三套生命周期     Maven拥有三套相互独立的生命周期,它们分别为clean,default和site。 每个生命周期包含一些阶段,这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段,用户和Maven最直接的交互方式就是调用这些生命周期阶段。 以clean生命周期为例,它包含的阶段有pre-clean, clean 和 post</div> </li> <li><a href="/article/1032.htm" title="Linux下Jenkins迁移" target="_blank">Linux下Jenkins迁移</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/Jenkins/1.htm">Jenkins</a> <div>1. 将Jenkins程序目录copy过去      源程序在/export/data/tomcatRoot/ofctest-jenkins.jd.com下面            tar -cvzf jenkins.tar.gz ofctest-jenkins.jd.com &</div> </li> <li><a href="/article/1159.htm" title="request.getInputStream()只能获取一次的问题" target="_blank">request.getInputStream()只能获取一次的问题</a> <span class="text-muted">ayaoxinchao</span> <a class="tag" taget="_blank" href="/search/request/1.htm">request</a><a class="tag" taget="_blank" href="/search/Inputstream/1.htm">Inputstream</a> <div>问题:在使用HTTP协议实现应用间接口通信时,服务端读取客户端请求过来的数据,会用到request.getInputStream(),第一次读取的时候可以读取到数据,但是接下来的读取操作都读取不到数据   原因: 1. 一个InputStream对象在被读取完成后,将无法被再次读取,始终返回-1; 2. InputStream并没有实现reset方法(可以重</div> </li> <li><a href="/article/1286.htm" title="数据库SQL优化大总结之 百万级数据库优化方案" target="_blank">数据库SQL优化大总结之 百万级数据库优化方案</a> <span class="text-muted">BigBird2012</span> <a class="tag" taget="_blank" href="/search/SQL%E4%BC%98%E5%8C%96/1.htm">SQL优化</a> <div>网上关于SQL优化的教程很多,但是比较杂乱。近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充。 这篇文章我花费了大量的时间查找资料、修改、排版,希望大家阅读之后,感觉好的话推荐给更多的人,让更多的人看到、纠正以及补充。 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 2.应尽量避免在 where </div> </li> <li><a href="/article/1413.htm" title="jsonObject的使用" target="_blank">jsonObject的使用</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/json/1.htm">json</a> <div>        在项目中难免会用java处理json格式的数据,因此封装了一个JSONUtil工具类。 JSONUtil.java package com.bijian.json.study; import java.util.ArrayList; import java.util.Date; import java.util.HashMap;</div> </li> <li><a href="/article/1540.htm" title="[Zookeeper学习笔记之六]Zookeeper源代码分析之Zookeeper.WatchRegistration" target="_blank">[Zookeeper学习笔记之六]Zookeeper源代码分析之Zookeeper.WatchRegistration</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a> <div>Zookeeper类是Zookeeper提供给用户访问Zookeeper service的主要API,它包含了如下几个内部类     首先分析它的内部类,从WatchRegistration开始,为指定的znode path注册一个Watcher,   /** * Register a watcher for a particular p</div> </li> <li><a href="/article/1667.htm" title="【Scala十三】Scala核心七:部分应用函数" target="_blank">【Scala十三】Scala核心七:部分应用函数</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/scala/1.htm">scala</a> <div>何为部分应用函数? Partially applied function: A function that’s used in an expression and that misses some of its arguments.For instance, if function f has type Int => Int => Int, then f and f(1) are p</div> </li> <li><a href="/article/1794.htm" title="Tomcat Error listenerStart 终极大法" target="_blank">Tomcat Error listenerStart 终极大法</a> <span class="text-muted">ronin47</span> <a class="tag" taget="_blank" href="/search/tomcat/1.htm">tomcat</a> <div>Tomcat报的错太含糊了,什么错都没报出来,只提示了Error listenerStart。为了调试,我们要获得更详细的日志。可以在WEB-INF/classes目录下新建一个文件叫logging.properties,内容如下 Java代码  handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHa</div> </li> <li><a href="/article/1921.htm" title="不用加减符号实现加减法" target="_blank">不用加减符号实现加减法</a> <span class="text-muted">BrokenDreams</span> <a class="tag" taget="_blank" href="/search/%E5%AE%9E%E7%8E%B0/1.htm">实现</a> <div>        今天有群友发了一个问题,要求不用加减符号(包括负号)来实现加减法。         分析一下,先看最简单的情况,假设1+1,按二进制算的话结果是10,可以看到从右往左的第一位变为0,第二位由于进位变为1。    </div> </li> <li><a href="/article/2048.htm" title="读《研磨设计模式》-代码笔记-状态模式-State" target="_blank">读《研磨设计模式》-代码笔记-状态模式-State</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a> <div>声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/ /* 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类 状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况 把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化 如果在</div> </li> <li><a href="/article/2175.htm" title="CUDA程序block和thread超出硬件允许值时的异常" target="_blank">CUDA程序block和thread超出硬件允许值时的异常</a> <span class="text-muted">cherishLC</span> <a class="tag" taget="_blank" href="/search/CUDA/1.htm">CUDA</a> <div>调用CUDA的核函数时指定block 和 thread大小,该大小可以是dim3类型的(三维数组),只用一维时可以是usigned int型的。 以下程序验证了当block或thread大小超出硬件允许值时会产生异常!!!GPU根本不会执行运算!!! 所以验证结果的正确性很重要!!! 在VS中创建CUDA项目会有一个模板,里面有更详细的状态验证。 以下程序在K5000GPU上跑的。</div> </li> <li><a href="/article/2302.htm" title="诡异的超长时间GC问题定位" target="_blank">诡异的超长时间GC问题定位</a> <span class="text-muted">chenchao051</span> <a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/cms/1.htm">cms</a><a class="tag" taget="_blank" href="/search/GC/1.htm">GC</a><a class="tag" taget="_blank" href="/search/hbase/1.htm">hbase</a><a class="tag" taget="_blank" href="/search/swap/1.htm">swap</a> <div>HBase的GC策略采用PawNew+CMS, 这是大众化的配置,ParNew经常会出现停顿时间特别长的情况,有时候甚至长到令人发指的地步,例如请看如下日志: 2012-10-17T05:54:54.293+0800: 739594.224: [GC 739606.508: [ParNew: 996800K->110720K(996800K), 178.8826900 secs] 3700</div> </li> <li><a href="/article/2429.htm" title="maven环境快速搭建" target="_blank">maven环境快速搭建</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/%E5%AE%89%E8%A3%85/1.htm">安装</a><a class="tag" taget="_blank" href="/search/mavne/1.htm">mavne</a><a class="tag" taget="_blank" href="/search/%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/1.htm">环境配置</a> <div>一 下载maven 安装maven之前,要先安装jdk及配置JAVA_HOME环境变量。这个安装和配置java环境不用多说。 maven下载地址:http://maven.apache.org/download.html,目前最新的是这个apache-maven-3.2.5-bin.zip,然后解压在任意位置,最好地址中不要带中文字符,这个做java 的都知道,地址中出现中文会出现很多</div> </li> <li><a href="/article/2556.htm" title="PHP网站安全,避免PHP网站受到攻击的方法" target="_blank">PHP网站安全,避免PHP网站受到攻击的方法</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a> <div> 对于PHP网站安全主要存在这样几种攻击方式:1、命令注入(Command Injection)2、eval注入(Eval Injection)3、客户端脚本攻击(Script Insertion)4、跨网站脚本攻击(Cross Site Scripting, XSS)5、SQL注入攻击(SQL injection)6、跨网站请求伪造攻击(Cross Site Request Forgerie</div> </li> <li><a href="/article/2683.htm" title="yii中给CGridView设置默认的排序根据时间倒序的方法" target="_blank">yii中给CGridView设置默认的排序根据时间倒序的方法</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/GridView/1.htm">GridView</a> <div>public function searchWithRelated() {         $criteria = new CDbCriteria;         $criteria->together = true; //without th</div> </li> <li><a href="/article/2810.htm" title="Java集合对象和数组对象的转换" target="_blank">Java集合对象和数组对象的转换</a> <span class="text-muted">dyy_gusi</span> <a class="tag" taget="_blank" href="/search/java%E9%9B%86%E5%90%88/1.htm">java集合</a> <div>    在开发中,我们经常需要将集合对象(List,Set)转换为数组对象,或者将数组对象转换为集合对象。Java提供了相互转换的工具,但是我们使用的时候需要注意,不能乱用滥用。 1、数组对象转换为集合对象     最暴力的方式是new一个集合对象,然后遍历数组,依次将数组中的元素放入到新的集合中,但是这样做显然过</div> </li> <li><a href="/article/2937.htm" title="nginx同一主机部署多个应用" target="_blank">nginx同一主机部署多个应用</a> <span class="text-muted">geeksun</span> <a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a> <div>近日有一需求,需要在一台主机上用nginx部署2个php应用,分别是wordpress和wiki,探索了半天,终于部署好了,下面把过程记录下来。 1.   在nginx下创建vhosts目录,用以放置vhost文件。 mkdir vhosts   2.   修改nginx.conf的配置, 在http节点增加下面内容设置,用来包含vhosts里的配置文件 #</div> </li> <li><a href="/article/3064.htm" title="ubuntu添加admin权限的用户账号" target="_blank">ubuntu添加admin权限的用户账号</a> <span class="text-muted">hongtoushizi</span> <a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/useradd/1.htm">useradd</a> <div>ubuntu创建账号的方式通常用到两种:useradd 和adduser . 本人尝试了useradd方法,步骤如下: 1:useradd    使用useradd时,如果后面不加任何参数的话,如:sudo useradd sysadm 创建出来的用户将是默认的三无用户:无home directory ,无密码,无系统shell。 顾应该如下操作:   </div> </li> <li><a href="/article/3191.htm" title="第五章 常用Lua开发库2-JSON库、编码转换、字符串处理" target="_blank">第五章 常用Lua开发库2-JSON库、编码转换、字符串处理</a> <span class="text-muted">jinnianshilongnian</span> <a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/lua/1.htm">lua</a> <div>  JSON库   在进行数据传输时JSON格式目前应用广泛,因此从Lua对象与JSON字符串之间相互转换是一个非常常见的功能;目前Lua也有几个JSON库,本人用过cjson、dkjson。其中cjson的语法严格(比如unicode \u0020\u7eaf),要求符合规范否则会解析失败(如\u002),而dkjson相对宽松,当然也可以通过修改cjson的源码来完成</div> </li> <li><a href="/article/3318.htm" title="Spring定时器配置的两种实现方式OpenSymphony Quartz和java Timer详解" target="_blank">Spring定时器配置的两种实现方式OpenSymphony Quartz和java Timer详解</a> <span class="text-muted">yaerfeng1989</span> <a class="tag" taget="_blank" href="/search/timer/1.htm">timer</a><a class="tag" taget="_blank" href="/search/quartz/1.htm">quartz</a><a class="tag" taget="_blank" href="/search/%E5%AE%9A%E6%97%B6%E5%99%A8/1.htm">定时器</a> <div>原创整理不易,转载请注明出处:Spring定时器配置的两种实现方式OpenSymphony Quartz和java Timer详解 代码下载地址:http://www.zuidaima.com/share/1772648445103104.htm 有两种流行Spring定时器配置:Java的Timer类和OpenSymphony的Quartz。 1.Java Timer定时 首先继承jav</div> </li> <li><a href="/article/3445.htm" title="Linux下df与du两个命令的差别?" target="_blank">Linux下df与du两个命令的差别?</a> <span class="text-muted">pda158</span> <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a> <div> 一、df显示文件系统的使用情况,与du比較,就是更全盘化。   最经常使用的就是 df -T,显示文件系统的使用情况并显示文件系统的类型。   举比例如以下:   [root@localhost ~]# df -T   Filesystem                   Type &n</div> </li> <li><a href="/article/3572.htm" title="[转]SQLite的工具类 ---- 通过反射把Cursor封装到VO对象" target="_blank">[转]SQLite的工具类 ---- 通过反射把Cursor封装到VO对象</a> <span class="text-muted">ctfzh</span> <a class="tag" taget="_blank" href="/search/VO/1.htm">VO</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/sqlite/1.htm">sqlite</a><a class="tag" taget="_blank" href="/search/%E5%8F%8D%E5%B0%84/1.htm">反射</a><a class="tag" taget="_blank" href="/search/Cursor/1.htm">Cursor</a> <div>在写DAO层时,觉得从Cursor里一个一个的取出字段值再装到VO(值对象)里太麻烦了,就写了一个工具类,用到了反射,可以把查询记录的值装到对应的VO里,也可以生成该VO的List。   使用时需要注意: 考虑到Android的性能问题,VO没有使用Setter和Getter,而是直接用public的属性。 表中的字段名需要和VO的属性名一样,要是不一样就得在查询的SQL中</div> </li> <li><a href="/article/3699.htm" title="该学习笔记用到的Employee表" target="_blank">该学习笔记用到的Employee表</a> <span class="text-muted">vipbooks</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C/1.htm">工作</a> <div>    这是我在学习Oracle是用到的Employee表,在该笔记中用到的就是这张表,大家可以用它来学习和练习。 drop table Employee; -- 员工信息表 create table Employee( -- 员工编号 EmpNo number(3) primary key, -- 姓</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>