httpServlet源码:

 

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements.  See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License.  You may obtain a copy of the License at
  8. *
  9. *     http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package javax.servlet.http;
  18. import java.io.IOException;
  19. import java.io.OutputStreamWriter;
  20. import java.io.PrintWriter;
  21. import java.io.UnsupportedEncodingException;
  22. import java.lang.reflect.Method;
  23. import java.text.MessageFormat;
  24. import java.util.Enumeration;
  25. import java.util.ResourceBundle;
  26. import javax.servlet.DispatcherType;
  27. import javax.servlet.GenericServlet;
  28. import javax.servlet.ServletException;
  29. import javax.servlet.ServletOutputStream;
  30. import javax.servlet.ServletRequest;
  31. import javax.servlet.ServletResponse;
  32. /**
  33. * Provides an abstract class to be subclassed to create
  34. * an HTTP servlet suitable for a Web site. A subclass of
  35. * <code>HttpServlet</code> must override at least
  36. * one method, usually one of these:
  37. *
  38. * <ul>
  39. * <li> <code>doGet</code>, if the servlet supports HTTP GET requests
  40. * <li> <code>doPost</code>, for HTTP POST requests
  41. * <li> <code>doPut</code>, for HTTP PUT requests
  42. * <li> <code>doDelete</code>, for HTTP DELETE requests
  43. * <li> <code>init</code> and <code>destroy</code>,
  44. * to manage resources that are held for the life of the servlet
  45. * <li> <code>getServletInfo</code>, which the servlet uses to
  46. * provide information about itself
  47. * </ul>
  48. *
  49. * <p>There's almost no reason to override the <code>service</code>
  50. * method. <code>service</code> handles standard HTTP
  51. * requests by dispatching them to the handler methods
  52. * for each HTTP request type (the <code>do</code><i>Method</i>
  53. * methods listed above).
  54. *
  55. * <p>Likewise, there's almost no reason to override the
  56. * <code>doOptions</code> and <code>doTrace</code> methods.
  57. *
  58. * <p>Servlets typically run on multithreaded servers,
  59. * so be aware that a servlet must handle concurrent
  60. * requests and be careful to synchronize access to shared resources.
  61. * Shared resources include in-memory data such as
  62. * instance or class variables and external objects
  63. * such as files, database connections, and network
  64. * connections.
  65. * See the
  66. * <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">
  67. * Java Tutorial on Multithreaded Programming</a> for more
  68. * information on handling multiple threads in a Java program.
  69. */
  70. public abstract class HttpServlet extends GenericServlet {
  71. private static final long serialVersionUID = 1L;
  72. private static final String METHOD_DELETE = "DELETE";
  73. private static final String METHOD_HEAD = "HEAD";
  74. private static final String METHOD_GET = "GET";
  75. private static final String METHOD_OPTIONS = "OPTIONS";
  76. private static final String METHOD_POST = "POST";
  77. private static final String METHOD_PUT = "PUT";
  78. private static final String METHOD_TRACE = "TRACE";
  79. private static final String HEADER_IFMODSINCE = "If-Modified-Since";
  80. private static final String HEADER_LASTMOD = "Last-Modified";
  81. private static final String LSTRING_FILE =
  82. "javax.servlet.http.LocalStrings";
  83. private static final ResourceBundle lStrings =
  84. ResourceBundle.getBundle(LSTRING_FILE);
  85. /**
  86. * Does nothing, because this is an abstract class.
  87. */
  88. public HttpServlet() {
  89. // NOOP
  90. }
  91. /**
  92. * Called by the server (via the <code>service</code> method) to
  93. * allow a servlet to handle a GET request.
  94. *
  95. * <p>Overriding this method to support a GET request also
  96. * automatically supports an HTTP HEAD request. A HEAD
  97. * request is a GET request that returns no body in the
  98. * response, only the request header fields.
  99. *
  100. * <p>When overriding this method, read the request data,
  101. * write the response headers, get the response's writer or
  102. * output stream object, and finally, write the response data.
  103. * It's best to include content type and encoding. When using
  104. * a <code>PrintWriter</code> object to return the response,
  105. * set the content type before accessing the
  106. * <code>PrintWriter</code> object.
  107. *
  108. * <p>The servlet container must write the headers before
  109. * committing the response, because in HTTP the headers must be sent
  110. * before the response body.
  111. *
  112. * <p>Where possible, set the Content-Length header (with the
  113. * {@link javax.servlet.ServletResponse#setContentLength} method),
  114. * to allow the servlet container to use a persistent connection
  115. * to return its response to the client, improving performance.
  116. * The content length is automatically set if the entire response fits
  117. * inside the response buffer.
  118. *
  119. * <p>When using HTTP 1.1 chunked encoding (which means that the response
  120. * has a Transfer-Encoding header), do not set the Content-Length header.
  121. *
  122. * <p>The GET method should be safe, that is, without
  123. * any side effects for which users are held responsible.
  124. * For example, most form queries have no side effects.
  125. * If a client request is intended to change stored data,
  126. * the request should use some other HTTP method.
  127. *
  128. * <p>The GET method should also be idempotent, meaning
  129. * that it can be safely repeated. Sometimes making a
  130. * method safe also makes it idempotent. For example,
  131. * repeating queries is both safe and idempotent, but
  132. * buying a product online or modifying data is neither
  133. * safe nor idempotent.
  134. *
  135. * <p>If the request is incorrectly formatted, <code>doGet</code>
  136. * returns an HTTP "Bad Request" message.
  137. *
  138. * @param req   an {@link HttpServletRequest} object that
  139. *                  contains the request the client has made
  140. *                  of the servlet
  141. *
  142. * @param resp  an {@link HttpServletResponse} object that
  143. *                  contains the response the servlet sends
  144. *                  to the client
  145. *
  146. * @exception IOException   if an input or output error is
  147. *                              detected when the servlet handles
  148. *                              the GET request
  149. *
  150. * @exception ServletException  if the request for the GET
  151. *                                  could not be handled
  152. *
  153. * @see javax.servlet.ServletResponse#setContentType
  154. */
  155. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  156. throws ServletException, IOException
  157. {
  158. String protocol = req.getProtocol();
  159. String msg = lStrings.getString("http.method_get_not_supported");
  160. if (protocol.endsWith("1.1")) {
  161. resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
  162. } else {
  163. resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
  164. }
  165. }
  166. /**
  167. * Returns the time the <code>HttpServletRequest</code>
  168. * object was last modified,
  169. * in milliseconds since midnight January 1, 1970 GMT.
  170. * If the time is unknown, this method returns a negative
  171. * number (the default).
  172. *
  173. * <p>Servlets that support HTTP GET requests and can quickly determine
  174. * their last modification time should override this method.
  175. * This makes browser and proxy caches work more effectively,
  176. * reducing the load on server and network resources.
  177. *
  178. * @param req   the <code>HttpServletRequest</code>
  179. *                  object that is sent to the servlet
  180. *
  181. * @return  a <code>long</code> integer specifying
  182. *              the time the <code>HttpServletRequest</code>
  183. *              object was last modified, in milliseconds
  184. *              since midnight, January 1, 1970 GMT, or
  185. *              -1 if the time is not known
  186. */
  187. protected long getLastModified(HttpServletRequest req) {
  188. return -1;
  189. }
  190. /**
  191. * <p>Receives an HTTP HEAD request from the protected
  192. * <code>service</code> method and handles the
  193. * request.
  194. * The client sends a HEAD request when it wants
  195. * to see only the headers of a response, such as
  196. * Content-Type or Content-Length. The HTTP HEAD
  197. * method counts the output bytes in the response
  198. * to set the Content-Length header accurately.
  199. *
  200. * <p>If you override this method, you can avoid computing
  201. * the response body and just set the response headers
  202. * directly to improve performance. Make sure that the
  203. * <code>doHead</code> method you write is both safe
  204. * and idempotent (that is, protects itself from being
  205. * called multiple times for one HTTP HEAD request).
  206. *
  207. * <p>If the HTTP HEAD request is incorrectly formatted,
  208. * <code>doHead</code> returns an HTTP "Bad Request"
  209. * message.
  210. *
  211. * @param req   the request object that is passed to the servlet
  212. *
  213. * @param resp  the response object that the servlet
  214. *                  uses to return the headers to the client
  215. *
  216. * @exception IOException   if an input or output error occurs
  217. *
  218. * @exception ServletException  if the request for the HEAD
  219. *                                  could not be handled
  220. */
  221. protected void doHead(HttpServletRequest req, HttpServletResponse resp)
  222. throws ServletException, IOException {
  223. if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
  224. doGet(req, resp);
  225. } else {
  226. NoBodyResponse response = new NoBodyResponse(resp);
  227. doGet(req, response);
  228. response.setContentLength();
  229. }
  230. }
  231. /**
  232. * Called by the server (via the <code>service</code> method)
  233. * to allow a servlet to handle a POST request.
  234. *
  235. * The HTTP POST method allows the client to send
  236. * data of unlimited length to the Web server a single time
  237. * and is useful when posting information such as
  238. * credit card numbers.
  239. *
  240. * <p>When overriding this method, read the request data,
  241. * write the response headers, get the response's writer or output
  242. * stream object, and finally, write the response data. It's best
  243. * to include content type and encoding. When using a
  244. * <code>PrintWriter</code> object to return the response, set the
  245. * content type before accessing the <code>PrintWriter</code> object.
  246. *
  247. * <p>The servlet container must write the headers before committing the
  248. * response, because in HTTP the headers must be sent before the
  249. * response body.
  250. *
  251. * <p>Where possible, set the Content-Length header (with the
  252. * {@link javax.servlet.ServletResponse#setContentLength} method),
  253. * to allow the servlet container to use a persistent connection
  254. * to return its response to the client, improving performance.
  255. * The content length is automatically set if the entire response fits
  256. * inside the response buffer.
  257. *
  258. * <p>When using HTTP 1.1 chunked encoding (which means that the response
  259. * has a Transfer-Encoding header), do not set the Content-Length header.
  260. *
  261. * <p>This method does not need to be either safe or idempotent.
  262. * Operations requested through POST can have side effects for
  263. * which the user can be held accountable, for example,
  264. * updating stored data or buying items online.
  265. *
  266. * <p>If the HTTP POST request is incorrectly formatted,
  267. * <code>doPost</code> returns an HTTP "Bad Request" message.
  268. *
  269. *
  270. * @param req   an {@link HttpServletRequest} object that
  271. *                  contains the request the client has made
  272. *                  of the servlet
  273. *
  274. * @param resp  an {@link HttpServletResponse} object that
  275. *                  contains the response the servlet sends
  276. *                  to the client
  277. *
  278. * @exception IOException   if an input or output error is
  279. *                              detected when the servlet handles
  280. *                              the request
  281. *
  282. * @exception ServletException  if the request for the POST
  283. *                                  could not be handled
  284. *
  285. * @see javax.servlet.ServletOutputStream
  286. * @see javax.servlet.ServletResponse#setContentType
  287. */
  288. protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  289. throws ServletException, IOException {
  290. String protocol = req.getProtocol();
  291. String msg = lStrings.getString("http.method_post_not_supported");
  292. if (protocol.endsWith("1.1")) {
  293. resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
  294. } else {
  295. resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
  296. }
  297. }
  298. /**
  299. * Called by the server (via the <code>service</code> method)
  300. * to allow a servlet to handle a PUT request.
  301. *
  302. * The PUT operation allows a client to
  303. * place a file on the server and is similar to
  304. * sending a file by FTP.
  305. *
  306. * <p>When overriding this method, leave intact
  307. * any content headers sent with the request (including
  308. * Content-Length, Content-Type, Content-Transfer-Encoding,
  309. * Content-Encoding, Content-Base, Content-Language, Content-Location,
  310. * Content-MD5, and Content-Range). If your method cannot
  311. * handle a content header, it must issue an error message
  312. * (HTTP 501 - Not Implemented) and discard the request.
  313. * For more information on HTTP 1.1, see RFC 2616
  314. * <a href="http://www.ietf.org/rfc/rfc2616.txt"></a>.
  315. *
  316. * <p>This method does not need to be either safe or idempotent.
  317. * Operations that <code>doPut</code> performs can have side
  318. * effects for which the user can be held accountable. When using
  319. * this method, it may be useful to save a copy of the
  320. * affected URL in temporary storage.
  321. *
  322. * <p>If the HTTP PUT request is incorrectly formatted,
  323. * <code>doPut</code> returns an HTTP "Bad Request" message.
  324. *
  325. * @param req   the {@link HttpServletRequest} object that
  326. *                  contains the request the client made of
  327. *                  the servlet
  328. *
  329. * @param resp  the {@link HttpServletResponse} object that
  330. *                  contains the response the servlet returns
  331. *                  to the client
  332. *
  333. * @exception IOException   if an input or output error occurs
  334. *                              while the servlet is handling the
  335. *                              PUT request
  336. *
  337. * @exception ServletException  if the request for the PUT
  338. *                                  cannot be handled
  339. */
  340. protected void doPut(HttpServletRequest req, HttpServletResponse resp)
  341. throws ServletException, IOException {
  342. String protocol = req.getProtocol();
  343. String msg = lStrings.getString("http.method_put_not_supported");
  344. if (protocol.endsWith("1.1")) {
  345. resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
  346. } else {
  347. resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
  348. }
  349. }
  350. /**
  351. * Called by the server (via the <code>service</code> method)
  352. * to allow a servlet to handle a DELETE request.
  353. *
  354. * The DELETE operation allows a client to remove a document
  355. * or Web page from the server.
  356. *
  357. * <p>This method does not need to be either safe
  358. * or idempotent. Operations requested through
  359. * DELETE can have side effects for which users
  360. * can be held accountable. When using
  361. * this method, it may be useful to save a copy of the
  362. * affected URL in temporary storage.
  363. *
  364. * <p>If the HTTP DELETE request is incorrectly formatted,
  365. * <code>doDelete</code> returns an HTTP "Bad Request"
  366. * message.
  367. *
  368. * @param req   the {@link HttpServletRequest} object that
  369. *                  contains the request the client made of
  370. *                  the servlet
  371. *
  372. *
  373. * @param resp  the {@link HttpServletResponse} object that
  374. *                  contains the response the servlet returns
  375. *                  to the client
  376. *
  377. * @exception IOException   if an input or output error occurs
  378. *                              while the servlet is handling the
  379. *                              DELETE request
  380. *
  381. * @exception ServletException  if the request for the
  382. *                                  DELETE cannot be handled
  383. */
  384. protected void doDelete(HttpServletRequest req,
  385. HttpServletResponse resp)
  386. throws ServletException, IOException {
  387. String protocol = req.getProtocol();
  388. String msg = lStrings.getString("http.method_delete_not_supported");
  389. if (protocol.endsWith("1.1")) {
  390. resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
  391. } else {
  392. resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
  393. }
  394. }
  395. private static Method[] getAllDeclaredMethods(Class<?> c) {
  396. if (c.equals(javax.servlet.http.HttpServlet.class)) {
  397. return null;
  398. }
  399. Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
  400. Method[] thisMethods = c.getDeclaredMethods();
  401. if ((parentMethods != null) && (parentMethods.length > 0)) {
  402. Method[] allMethods =
  403. new Method[parentMethods.length + thisMethods.length];
  404. System.arraycopy(parentMethods, 0, allMethods, 0,
  405. parentMethods.length);
  406. System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
  407. thisMethods.length);
  408. thisMethods = allMethods;
  409. }
  410. return thisMethods;
  411. }
  412. /**
  413. * Called by the server (via the <code>service</code> method)
  414. * to allow a servlet to handle a OPTIONS request.
  415. *
  416. * The OPTIONS request determines which HTTP methods
  417. * the server supports and
  418. * returns an appropriate header. For example, if a servlet
  419. * overrides <code>doGet</code>, this method returns the
  420. * following header:
  421. *
  422. * <p><code>Allow: GET, HEAD, TRACE, OPTIONS</code>
  423. *
  424. * <p>There's no need to override this method unless the
  425. * servlet implements new HTTP methods, beyond those
  426. * implemented by HTTP 1.1.
  427. *
  428. * @param req   the {@link HttpServletRequest} object that
  429. *                  contains the request the client made of
  430. *                  the servlet
  431. *
  432. * @param resp  the {@link HttpServletResponse} object that
  433. *                  contains the response the servlet returns
  434. *                  to the client
  435. *
  436. * @exception IOException   if an input or output error occurs
  437. *                              while the servlet is handling the
  438. *                              OPTIONS request
  439. *
  440. * @exception ServletException  if the request for the
  441. *                                  OPTIONS cannot be handled
  442. */
  443. protected void doOptions(HttpServletRequest req,
  444. HttpServletResponse resp)
  445. throws ServletException, IOException {
  446. Method[] methods = getAllDeclaredMethods(this.getClass());
  447. boolean ALLOW_GET = false;
  448. boolean ALLOW_HEAD = false;
  449. boolean ALLOW_POST = false;
  450. boolean ALLOW_PUT = false;
  451. boolean ALLOW_DELETE = false;
  452. boolean ALLOW_TRACE = true;
  453. boolean ALLOW_OPTIONS = true;
  454. for (int i=0; i<methods.length; i++) {
  455. Method m = methods[i];
  456. if (m.getName().equals("doGet")) {
  457. ALLOW_GET = true;
  458. ALLOW_HEAD = true;
  459. }
  460. if (m.getName().equals("doPost"))
  461. ALLOW_POST = true;
  462. if (m.getName().equals("doPut"))
  463. ALLOW_PUT = true;
  464. if (m.getName().equals("doDelete"))
  465. ALLOW_DELETE = true;
  466. }
  467. String allow = null;
  468. if (ALLOW_GET)
  469. allow=METHOD_GET;
  470. if (ALLOW_HEAD)
  471. if (allow==null) allow=METHOD_HEAD;
  472. else allow += ", " + METHOD_HEAD;
  473. if (ALLOW_POST)
  474. if (allow==null) allow=METHOD_POST;
  475. else allow += ", " + METHOD_POST;
  476. if (ALLOW_PUT)
  477. if (allow==null) allow=METHOD_PUT;
  478. else allow += ", " + METHOD_PUT;
  479. if (ALLOW_DELETE)
  480. if (allow==null) allow=METHOD_DELETE;
  481. else allow += ", " + METHOD_DELETE;
  482. if (ALLOW_TRACE)
  483. if (allow==null) allow=METHOD_TRACE;
  484. else allow += ", " + METHOD_TRACE;
  485. if (ALLOW_OPTIONS)
  486. if (allow==null) allow=METHOD_OPTIONS;
  487. else allow += ", " + METHOD_OPTIONS;
  488. resp.setHeader("Allow", allow);
  489. }
  490. /**
  491. * Called by the server (via the <code>service</code> method)
  492. * to allow a servlet to handle a TRACE request.
  493. *
  494. * A TRACE returns the headers sent with the TRACE
  495. * request to the client, so that they can be used in
  496. * debugging. There's no need to override this method.
  497. *
  498. * @param req   the {@link HttpServletRequest} object that
  499. *                  contains the request the client made of
  500. *                  the servlet
  501. *
  502. * @param resp  the {@link HttpServletResponse} object that
  503. *                  contains the response the servlet returns
  504. *                  to the client
  505. *
  506. * @exception IOException   if an input or output error occurs
  507. *                              while the servlet is handling the
  508. *                              TRACE request
  509. *
  510. * @exception ServletException  if the request for the
  511. *                                  TRACE cannot be handled
  512. */
  513. protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
  514. throws ServletException, IOException
  515. {
  516. int responseLength;
  517. String CRLF = "\r\n";
  518. StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI())
  519. .append(" ").append(req.getProtocol());
  520. Enumeration<String> reqHeaderEnum = req.getHeaderNames();
  521. while( reqHeaderEnum.hasMoreElements() ) {
  522. String headerName = reqHeaderEnum.nextElement();
  523. buffer.append(CRLF).append(headerName).append(": ")
  524. .append(req.getHeader(headerName));
  525. }
  526. buffer.append(CRLF);
  527. responseLength = buffer.length();
  528. resp.setContentType("message/http");
  529. resp.setContentLength(responseLength);
  530. ServletOutputStream out = resp.getOutputStream();
  531. out.print(buffer.toString());
  532. out.close();
  533. return;
  534. }
  535. /**
  536. * Receives standard HTTP requests from the public
  537. * <code>service</code> method and dispatches
  538. * them to the <code>do</code><i>Method</i> methods defined in
  539. * this class. This method is an HTTP-specific version of the
  540. * {@link javax.servlet.Servlet#service} method. There's no
  541. * need to override this method.
  542. *
  543. * @param req   the {@link HttpServletRequest} object that
  544. *                  contains the request the client made of
  545. *                  the servlet
  546. *
  547. * @param resp  the {@link HttpServletResponse} object that
  548. *                  contains the response the servlet returns
  549. *                  to the client
  550. *
  551. * @exception IOException   if an input or output error occurs
  552. *                              while the servlet is handling the
  553. *                              HTTP request
  554. *
  555. * @exception ServletException  if the HTTP request
  556. *                                  cannot be handled
  557. *
  558. * @see javax.servlet.Servlet#service
  559. */
  560. protected void service(HttpServletRequest req, HttpServletResponse resp)
  561. throws ServletException, IOException {
  562. String method = req.getMethod();
  563. if (method.equals(METHOD_GET)) {
  564. long lastModified = getLastModified(req);
  565. if (lastModified == -1) {
  566. // servlet doesn't support if-modified-since, no reason
  567. // to go through further expensive logic
  568. doGet(req, resp);
  569. } else {
  570. long ifModifiedSince;
  571. try {
  572. ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
  573. } catch (IllegalArgumentException iae) {
  574. // Invalid date header - proceed as if none was set
  575. ifModifiedSince = -1;
  576. }
  577. if (ifModifiedSince < (lastModified / 1000 * 1000)) {
  578. // If the servlet mod time is later, call doGet()
  579. // Round down to the nearest second for a proper compare
  580. // A ifModifiedSince of -1 will always be less
  581. maybeSetLastModified(resp, lastModified);
  582. doGet(req, resp);
  583. } else {
  584. resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
  585. }
  586. }
  587. } else if (method.equals(METHOD_HEAD)) {
  588. long lastModified = getLastModified(req);
  589. maybeSetLastModified(resp, lastModified);
  590. doHead(req, resp);
  591. } else if (method.equals(METHOD_POST)) {
  592. doPost(req, resp);
  593. } else if (method.equals(METHOD_PUT)) {
  594. doPut(req, resp);
  595. } else if (method.equals(METHOD_DELETE)) {
  596. doDelete(req, resp);
  597. } else if (method.equals(METHOD_OPTIONS)) {
  598. doOptions(req,resp);
  599. } else if (method.equals(METHOD_TRACE)) {
  600. doTrace(req,resp);
  601. } else {
  602. //
  603. // Note that this means NO servlet supports whatever
  604. // method was requested, anywhere on this server.
  605. //
  606. String errMsg = lStrings.getString("http.method_not_implemented");
  607. Object[] errArgs = new Object[1];
  608. errArgs[0] = method;
  609. errMsg = MessageFormat.format(errMsg, errArgs);
  610. resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
  611. }
  612. }
  613. /*
  614. * Sets the Last-Modified entity header field, if it has not
  615. * already been set and if the value is meaningful.  Called before
  616. * doGet, to ensure that headers are set before response data is
  617. * written.  A subclass might have set this header already, so we
  618. * check.
  619. */
  620. private void maybeSetLastModified(HttpServletResponse resp,
  621. long lastModified) {
  622. if (resp.containsHeader(HEADER_LASTMOD))
  623. return;
  624. if (lastModified >= 0)
  625. resp.setDateHeader(HEADER_LASTMOD, lastModified);
  626. }
  627. /**
  628. * Dispatches client requests to the protected
  629. * <code>service</code> method. There's no need to
  630. * override this method.
  631. *
  632. * @param req   the {@link HttpServletRequest} object that
  633. *                  contains the request the client made of
  634. *                  the servlet
  635. *
  636. * @param res   the {@link HttpServletResponse} object that
  637. *                  contains the response the servlet returns
  638. *                  to the client
  639. *
  640. * @exception IOException   if an input or output error occurs
  641. *                              while the servlet is handling the
  642. *                              HTTP request
  643. *
  644. * @exception ServletException  if the HTTP request cannot
  645. *                                  be handled
  646. *
  647. * @see javax.servlet.Servlet#service
  648. */
  649. @Override
  650. public void service(ServletRequest req, ServletResponse res)
  651. throws ServletException, IOException {
  652. HttpServletRequest  request;
  653. HttpServletResponse response;
  654. try {
  655. request = (HttpServletRequest) req;
  656. response = (HttpServletResponse) res;
  657. } catch (ClassCastException e) {
  658. throw new ServletException("non-HTTP request or response");
  659. }
  660. service(request, response);
  661. }
  662. }
  663. /*
  664. * A response wrapper for use in (dumb) "HEAD" support.
  665. * This just swallows that body, counting the bytes in order to set
  666. * the content length appropriately.  All other methods delegate to the
  667. * wrapped HTTP Servlet Response object.
  668. */
  669. // file private
  670. class NoBodyResponse extends HttpServletResponseWrapper {
  671. private final NoBodyOutputStream noBody;
  672. private PrintWriter writer;
  673. private boolean didSetContentLength;
  674. // file private
  675. NoBodyResponse(HttpServletResponse r) {
  676. super(r);
  677. noBody = new NoBodyOutputStream();
  678. }
  679. // file private
  680. void setContentLength() {
  681. if (!didSetContentLength) {
  682. if (writer != null) {
  683. writer.flush();
  684. }
  685. super.setContentLength(noBody.getContentLength());
  686. }
  687. }
  688. // SERVLET RESPONSE interface methods
  689. @Override
  690. public void setContentLength(int len) {
  691. super.setContentLength(len);
  692. didSetContentLength = true;
  693. }
  694. @Override
  695. public void setContentLengthLong(long len) {
  696. super.setContentLengthLong(len);
  697. didSetContentLength = true;
  698. }
  699. @Override
  700. public void setHeader(String name, String value) {
  701. super.setHeader(name, value);
  702. checkHeader(name);
  703. }
  704. @Override
  705. public void addHeader(String name, String value) {
  706. super.addHeader(name, value);
  707. checkHeader(name);
  708. }
  709. @Override
  710. public void setIntHeader(String name, int value) {
  711. super.setIntHeader(name, value);
  712. checkHeader(name);
  713. }
  714. @Override
  715. public void addIntHeader(String name, int value) {
  716. super.addIntHeader(name, value);
  717. checkHeader(name);
  718. }
  719. private void checkHeader(String name) {
  720. if ("content-length".equalsIgnoreCase(name)) {
  721. didSetContentLength = true;
  722. }
  723. }
  724. @Override
  725. public ServletOutputStream getOutputStream() throws IOException {
  726. return noBody;
  727. }
  728. @Override
  729. public PrintWriter getWriter() throws UnsupportedEncodingException {
  730. if (writer == null) {
  731. OutputStreamWriter w;
  732. w = new OutputStreamWriter(noBody, getCharacterEncoding());
  733. writer = new PrintWriter(w);
  734. }
  735. return writer;
  736. }
  737. }
  738. /*
  739. * Servlet output stream that gobbles up all its data.
  740. */
  741. // file private
  742. class NoBodyOutputStream extends ServletOutputStream {
  743. private static final String LSTRING_FILE =
  744. "javax.servlet.http.LocalStrings";
  745. private static final ResourceBundle lStrings =
  746. ResourceBundle.getBundle(LSTRING_FILE);
  747. private int contentLength = 0;
  748. // file private
  749. NoBodyOutputStream() {
  750. // NOOP
  751. }
  752. // file private
  753. int getContentLength() {
  754. return contentLength;
  755. }
  756. @Override
  757. public void write(int b) {
  758. contentLength++;
  759. }
  760. @Override
  761. public void write(byte buf[], int offset, int len) throws IOException {
  762. if (buf == null) {
  763. throw new NullPointerException(
  764. lStrings.getString("err.io.nullArray"));
  765. }
  766. if (offset < 0 || len < 0 || offset+len > buf.length) {
  767. String msg = lStrings.getString("err.io.indexOutOfBounds");
  768. Object[] msgArgs = new Object[3];
  769. msgArgs[0] = Integer.valueOf(offset);
  770. msgArgs[1] = Integer.valueOf(len);
  771. msgArgs[2] = Integer.valueOf(buf.length);
  772. msg = MessageFormat.format(msg, msgArgs);
  773. throw new IndexOutOfBoundsException(msg);
  774. }
  775. contentLength += len;
  776. }
  777. @Override
  778. public boolean isReady() {
  779. // TODO SERVLET 3.1
  780. return false;
  781. }
  782. @Override
  783. public void setWriteListener(javax.servlet.WriteListener listener) {
  784. // TODO SERVLET 3.1
  785. }
  786. }

 

GenericServlet源码:

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements.  See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License.  You may obtain a copy of the License at
  8. *
  9. *     http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package javax.servlet;
  18. import java.io.IOException;
  19. import java.util.Enumeration;
  20. /**
  21. * Defines a generic, protocol-independent servlet. To write an HTTP servlet for
  22. * use on the Web, extend {@link javax.servlet.http.HttpServlet} instead.
  23. * <p>
  24. * <code>GenericServlet</code> implements the <code>Servlet</code> and
  25. * <code>ServletConfig</code> interfaces. <code>GenericServlet</code> may be
  26. * directly extended by a servlet, although it's more common to extend a
  27. * protocol-specific subclass such as <code>HttpServlet</code>.
  28. * <p>
  29. * <code>GenericServlet</code> makes writing servlets easier. It provides simple
  30. * versions of the lifecycle methods <code>init</code> and <code>destroy</code>
  31. * and of the methods in the <code>ServletConfig</code> interface.
  32. * <code>GenericServlet</code> also implements the <code>log</code> method,
  33. * declared in the <code>ServletContext</code> interface.
  34. * <p>
  35. * To write a generic servlet, you need only override the abstract
  36. * <code>service</code> method.
  37. */
  38. public abstract class GenericServlet implements Servlet, ServletConfig,
  39. java.io.Serializable {
  40. private static final long serialVersionUID = 1L;
  41. private transient ServletConfig config;
  42. /**
  43. * Does nothing. All of the servlet initialization is done by one of the
  44. * <code>init</code> methods.
  45. */
  46. public GenericServlet() {
  47. // NOOP
  48. }
  49. /**
  50. * Called by the servlet container to indicate to a servlet that the servlet
  51. * is being taken out of service. See {@link Servlet#destroy}.
  52. */
  53. @Override
  54. public void destroy() {
  55. // NOOP by default
  56. }
  57. /**
  58. * Returns a <code>String</code> containing the value of the named
  59. * initialization parameter, or <code>null</code> if the parameter does not
  60. * exist. See {@link ServletConfig#getInitParameter}.
  61. * <p>
  62. * This method is supplied for convenience. It gets the value of the named
  63. * parameter from the servlet's <code>ServletConfig</code> object.
  64. *
  65. * @param name
  66. *            a <code>String</code> specifying the name of the
  67. *            initialization parameter
  68. * @return String a <code>String</code> containing the value of the
  69. *         initialization parameter
  70. */
  71. @Override
  72. public String getInitParameter(String name) {
  73. return getServletConfig().getInitParameter(name);
  74. }
  75. /**
  76. * Returns the names of the servlet's initialization parameters as an
  77. * <code>Enumeration</code> of <code>String</code> objects, or an empty
  78. * <code>Enumeration</code> if the servlet has no initialization parameters.
  79. * See {@link ServletConfig#getInitParameterNames}.
  80. * <p>
  81. * This method is supplied for convenience. It gets the parameter names from
  82. * the servlet's <code>ServletConfig</code> object.
  83. *
  84. * @return Enumeration an enumeration of <code>String</code> objects
  85. *         containing the names of the servlet's initialization parameters
  86. */
  87. @Override
  88. public Enumeration<String> getInitParameterNames() {
  89. return getServletConfig().getInitParameterNames();
  90. }
  91. /**
  92. * Returns this servlet's {@link ServletConfig} object.
  93. *
  94. * @return ServletConfig the <code>ServletConfig</code> object that
  95. *         initialized this servlet
  96. */
  97. @Override
  98. public ServletConfig getServletConfig() {
  99. return config;
  100. }
  101. /**
  102. * Returns a reference to the {@link ServletContext} in which this servlet
  103. * is running. See {@link ServletConfig#getServletContext}.
  104. * <p>
  105. * This method is supplied for convenience. It gets the context from the
  106. * servlet's <code>ServletConfig</code> object.
  107. *
  108. * @return ServletContext the <code>ServletContext</code> object passed to
  109. *         this servlet by the <code>init</code> method
  110. */
  111. @Override
  112. public ServletContext getServletContext() {
  113. return getServletConfig().getServletContext();
  114. }
  115. /**
  116. * Returns information about the servlet, such as author, version, and
  117. * copyright. By default, this method returns an empty string. Override this
  118. * method to have it return a meaningful value. See
  119. * {@link Servlet#getServletInfo}.
  120. *
  121. * @return String information about this servlet, by default an empty string
  122. */
  123. @Override
  124. public String getServletInfo() {
  125. return "";
  126. }
  127. /**
  128. * Called by the servlet container to indicate to a servlet that the servlet
  129. * is being placed into service. See {@link Servlet#init}.
  130. * <p>
  131. * This implementation stores the {@link ServletConfig} object it receives
  132. * from the servlet container for later use. When overriding this form of
  133. * the method, call <code>super.init(config)</code>.
  134. *
  135. * @param config
  136. *            the <code>ServletConfig</code> object that contains
  137. *            configuration information for this servlet
  138. * @exception ServletException
  139. *                if an exception occurs that interrupts the servlet's
  140. *                normal operation
  141. * @see UnavailableException
  142. */
  143. @Override
  144. public void init(ServletConfig config) throws ServletException {
  145. this.config = config;
  146. this.init();
  147. }
  148. /**
  149. * A convenience method which can be overridden so that there's no need to
  150. * call <code>super.init(config)</code>.
  151. * <p>
  152. * Instead of overriding {@link #init(ServletConfig)}, simply override this
  153. * method and it will be called by
  154. * <code>GenericServlet.init(ServletConfig config)</code>. The
  155. * <code>ServletConfig</code> object can still be retrieved via
  156. * {@link #getServletConfig}.
  157. *
  158. * @exception ServletException
  159. *                if an exception occurs that interrupts the servlet's
  160. *                normal operation
  161. */
  162. public void init() throws ServletException {
  163. // NOOP by default
  164. }
  165. /**
  166. * Writes the specified message to a servlet log file, prepended by the
  167. * servlet's name. See {@link ServletContext#log(String)}.
  168. *
  169. * @param msg
  170. *            a <code>String</code> specifying the message to be written to
  171. *            the log file
  172. */
  173. public void log(String msg) {
  174. getServletContext().log(getServletName() + ": " + msg);
  175. }
  176. /**
  177. * Writes an explanatory message and a stack trace for a given
  178. * <code>Throwable</code> exception to the servlet log file, prepended by
  179. * the servlet's name. See {@link ServletContext#log(String, Throwable)}.
  180. *
  181. * @param message
  182. *            a <code>String</code> that describes the error or exception
  183. * @param t
  184. *            the <code>java.lang.Throwable</code> error or exception
  185. */
  186. public void log(String message, Throwable t) {
  187. getServletContext().log(getServletName() + ": " + message, t);
  188. }
  189. /**
  190. * Called by the servlet container to allow the servlet to respond to a
  191. * request. See {@link Servlet#service}.
  192. * <p>
  193. * This method is declared abstract so subclasses, such as
  194. * <code>HttpServlet</code>, must override it.
  195. *
  196. * @param req
  197. *            the <code>ServletRequest</code> object that contains the
  198. *            client's request
  199. * @param res
  200. *            the <code>ServletResponse</code> object that will contain the
  201. *            servlet's response
  202. * @exception ServletException
  203. *                if an exception occurs that interferes with the servlet's
  204. *                normal operation occurred
  205. * @exception IOException
  206. *                if an input or output exception occurs
  207. */
  208. @Override
  209. public abstract void service(ServletRequest req, ServletResponse res)
  210. throws ServletException, IOException;
  211. /**
  212. * Returns the name of this servlet instance. See
  213. * {@link ServletConfig#getServletName}.
  214. *
  215. * @return the name of this servlet instance
  216. */
  217. @Override
  218. public String getServletName() {
  219. return config.getServletName();
  220. }
  221. }

 

 

Servlet源码:

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements.  See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License.  You may obtain a copy of the License at
  8. *
  9. *     http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package javax.servlet;
  18. import java.io.IOException;
  19. /**
  20. * Defines methods that all servlets must implement.
  21. *
  22. * <p>
  23. * A servlet is a small Java program that runs within a Web server. Servlets
  24. * receive and respond to requests from Web clients, usually across HTTP, the
  25. * HyperText Transfer Protocol.
  26. *
  27. * <p>
  28. * To implement this interface, you can write a generic servlet that extends
  29. * <code>javax.servlet.GenericServlet</code> or an HTTP servlet that extends
  30. * <code>javax.servlet.http.HttpServlet</code>.
  31. *
  32. * <p>
  33. * This interface defines methods to initialize a servlet, to service requests,
  34. * and to remove a servlet from the server. These are known as life-cycle
  35. * methods and are called in the following sequence:
  36. * <ol>
  37. * <li>The servlet is constructed, then initialized with the <code>init</code>
  38. * method.
  39. * <li>Any calls from clients to the <code>service</code> method are handled.
  40. * <li>The servlet is taken out of service, then destroyed with the
  41. * <code>destroy</code> method, then garbage collected and finalized.
  42. * </ol>
  43. *
  44. * <p>
  45. * In addition to the life-cycle methods, this interface provides the
  46. * <code>getServletConfig</code> method, which the servlet can use to get any
  47. * startup information, and the <code>getServletInfo</code> method, which allows
  48. * the servlet to return basic information about itself, such as author,
  49. * version, and copyright.
  50. *
  51. * @see GenericServlet
  52. * @see javax.servlet.http.HttpServlet
  53. */
  54. public interface Servlet {
  55. /**
  56. * Called by the servlet container to indicate to a servlet that the servlet
  57. * is being placed into service.
  58. *
  59. * <p>
  60. * The servlet container calls the <code>init</code> method exactly once
  61. * after instantiating the servlet. The <code>init</code> method must
  62. * complete successfully before the servlet can receive any requests.
  63. *
  64. * <p>
  65. * The servlet container cannot place the servlet into service if the
  66. * <code>init</code> method
  67. * <ol>
  68. * <li>Throws a <code>ServletException</code>
  69. * <li>Does not return within a time period defined by the Web server
  70. * </ol>
  71. *
  72. *
  73. * @param config
  74. *            a <code>ServletConfig</code> object containing the servlet's
  75. *            configuration and initialization parameters
  76. *
  77. * @exception ServletException
  78. *                if an exception has occurred that interferes with the
  79. *                servlet's normal operation
  80. *
  81. * @see UnavailableException
  82. * @see #getServletConfig
  83. */
  84. public void init(ServletConfig config) throws ServletException;
  85. /**
  86. *
  87. * Returns a {@link ServletConfig} object, which contains initialization and
  88. * startup parameters for this servlet. The <code>ServletConfig</code>
  89. * object returned is the one passed to the <code>init</code> method.
  90. *
  91. * <p>
  92. * Implementations of this interface are responsible for storing the
  93. * <code>ServletConfig</code> object so that this method can return it. The
  94. * {@link GenericServlet} class, which implements this interface, already
  95. * does this.
  96. *
  97. * @return the <code>ServletConfig</code> object that initializes this
  98. *         servlet
  99. *
  100. * @see #init
  101. */
  102. public ServletConfig getServletConfig();
  103. /**
  104. * Called by the servlet container to allow the servlet to respond to a
  105. * request.
  106. *
  107. * <p>
  108. * This method is only called after the servlet's <code>init()</code> method
  109. * has completed successfully.
  110. *
  111. * <p>
  112. * The status code of the response always should be set for a servlet that
  113. * throws or sends an error.
  114. *
  115. *
  116. * <p>
  117. * Servlets typically run inside multithreaded servlet containers that can
  118. * handle multiple requests concurrently. Developers must be aware to
  119. * synchronize access to any shared resources such as files, network
  120. * connections, and as well as the servlet's class and instance variables.
  121. * More information on multithreaded programming in Java is available in <a
  122. * href
  123. * ="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">
  124. * the Java tutorial on multi-threaded programming</a>.
  125. *
  126. *
  127. * @param req
  128. *            the <code>ServletRequest</code> object that contains the
  129. *            client's request
  130. *
  131. * @param res
  132. *            the <code>ServletResponse</code> object that contains the
  133. *            servlet's response
  134. *
  135. * @exception ServletException
  136. *                if an exception occurs that interferes with the servlet's
  137. *                normal operation
  138. *
  139. * @exception IOException
  140. *                if an input or output exception occurs
  141. */
  142. public void service(ServletRequest req, ServletResponse res)
  143. throws ServletException, IOException;
  144. /**
  145. * Returns information about the servlet, such as author, version, and
  146. * copyright.
  147. *
  148. * <p>
  149. * The string that this method returns should be plain text and not markup
  150. * of any kind (such as HTML, XML, etc.).
  151. *
  152. * @return a <code>String</code> containing servlet information
  153. */
  154. public String getServletInfo();
  155. /**
  156. * Called by the servlet container to indicate to a servlet that the servlet
  157. * is being taken out of service. This method is only called once all
  158. * threads within the servlet's <code>service</code> method have exited or
  159. * after a timeout period has passed. After the servlet container calls this
  160. * method, it will not call the <code>service</code> method again on this
  161. * servlet.
  162. *
  163. * <p>
  164. * This method gives the servlet an opportunity to clean up any resources
  165. * that are being held (for example, memory, file handles, threads) and make
  166. * sure that any persistent state is synchronized with the servlet's current
  167. * state in memory.
  168. */
  169. public void destroy();
  170. }

httpServlet,GenericServlet,Servlet源码分析的更多相关文章

  1. Servlet源码分析

    Servlet API的核心就是javax.servlet.Servlet接口,所有的Servlet 类(抽象的或者自己写的)都必须实现这个接口.在Servlet接口中定义了5个方法,其中有3个方法是 ...

  2. JavaWeb高级:Servlet源码分析

    很多东西归根结底是对Servlet源代码的了解,通过学习源代码加深了解Java高级特性

  3. Servlet和Tomcat底层源码分析

    Servlet 源码分析   Servlet 结构图 Servlet 和 ServletConfig 都是顶层接口,而 GenericServlet 实现了这两个顶层接口,然后HttpServlet ...

  4. Spring mvc源码分析系列--Servlet的前世今生

    Spring mvc源码分析系列--Servlet的前世今生 概述 上一篇文章Spring mvc源码分析系列--前言挖了坑,但是由于最近需求繁忙,一直没有时间填坑.今天暂且来填一个小坑,这篇文章我们 ...

  5. Servlet容器Tomcat中web.xml中url-pattern的配置详解[附带源码分析]

    目录 前言 现象 源码分析 实战例子 总结 参考资料 前言 今天研究了一下tomcat上web.xml配置文件中url-pattern的问题. 这个问题其实毕业前就困扰着我,当时忙于找工作. 找到工作 ...

  6. springmvc源码分析系列-请求处理流程

    接上一篇-springmvc源码分析开头片 上一节主要说了一下springmvc与struts2的作为MVC中的C(controller)控制层的一些区别及两者在作为控制层方面的一些优缺点.今天就结合 ...

  7. 【原创】005 | 搭上SpringBoot请求处理源码分析专车

    前言 如果这是你第二次看到师长,说明你在觊觎我的美色! 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 专车介绍 该趟专车是开往Spring Boot请求处理源码分析专车,主要用来分析S ...

  8. 深入理解 spring 容器,源码分析加载过程

    Spring框架提供了构建Web应用程序的全功能MVC模块,叫Spring MVC,通过Spring Core+Spring MVC即可搭建一套稳定的Java Web项目.本文通过Spring MVC ...

  9. springmvc源码分析

    Spring MVC源码分析--初始化过程 标签: springmvcconstructioniocclass 2012-09-09 21:32 26578人阅读 评论(3) 收藏 举报 版权声明:本 ...

随机推荐

  1. Python Journey

    1. 开发环境搭建 - Eclipse + PyDev搭建开发环境: http://www.cnblogs.com/Bonker/p/3584707.html (其实,如果不是License限制,推荐 ...

  2. 关于erlang反编译的东西

    在查阅了相关文档,想了解erlang反编译的东西.当然,源码可以打包成可以获取源码的,也可以保护源码的. 在ebin下,如果没有或者找不到源码,可以进行反编译,由beam文件得到erl文件. 可以通过 ...

  3. IGP和EGP(转载)

    AS(自治系统) - 也称为路由域,是指一个共同管理区域内的一组路由器.例如公司的内部网络和 Internet 服务提供商的网络.由于 Internet 基于自治系统,因此既需要使用内部路由协议,也需 ...

  4. 协议分析之qq协议---qq登录

    QQ 协议分析:获取各类登录会话密钥 我们知道QQ的一些会话密钥是在登录过程中生成的,尤其是Session Key,有了它便可以解密出聊天文本内容.本文主要是了解一下QQ的加密机制,首先是用嗅探工具W ...

  5. SAM4E单片机之旅——7、LED闪烁之TC中断

    RTT主要用做一个全局的定时器,而且不太通用.现在尝试使用一个更为通用的定时器进行定时:定时计数器(Timer Counter, TC). TC提供了广泛的功能,主要可以分为对输入的测量,以及波形的输 ...

  6. SAM4E单片机之旅——1、LED闪烁之空循环

    最近因为导师要写一本关于SAME4单片机的书籍,而我也作为一个嵌入式的初学者看了这本书.现在也让我写写几个小的程序,做做示例.既然写了文档之类的,就发到博客上来吧. 目前关于这芯片能参考的书籍大概就只 ...

  7. Colly provides a clean interface to write any kind of crawler/scraper/spider

    Scraping Framework for Golang http://go-colly.org/ https://github.com/gocolly/colly package main imp ...

  8. Win32对话框工程笔记

    Main.cpp #include <Windows.h> #include "resource.h" INT_PTR CALLBACK dialogProc(HWND ...

  9. java.lang.ClassNotFoundException: Didn't find class "org.reactivestreams.Publisher" on path

    缺少jar包  reactive-streams-1.0.0.jar  和  reactive-streams-1.0.0-sources.jar 常用于  Rxjava 开发过程中 <?xml ...

  10. Linux ARM交叉编译工具链制作过程【转】

    本文转载自:http://www.cnblogs.com/Charles-Zhang-Blog/archive/2013/02/21/2920999.html 一.下载源文件 源代码文件及其版本与下载 ...