Writer :BYSocket(泥沙砖瓦浆木匠)
微 博: BYSocket
豆 瓣: BYSocket
FaceBook: BYSocket
Twitter : BYSocket
上一篇的《 Servlet必会必知 》受到大家一致好评 — ( 感谢 读者 及 OSC 推荐 每日一’搏’)
后来觉得还有些东西没点到,这边补充补充。
private static final String METHOD_DELETE = "DELETE"; private static final String METHOD_HEAD = "HEAD"; private static final String METHOD_GET = "GET"; private static final String METHOD_OPTIONS = "OPTIONS"; private static final String METHOD_POST = "POST"; private static final String METHOD_PUT = "PUT"; private static final String METHOD_TRACE = "TRACE"; private static final String HEADER_IFMODSINCE = "If-Modified-Since"; private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings"; private static ResourceBundle lStrings = ResourceBundle.getBundle(LSTRING_FILE); /** * HTTP状态码304 */ public static final int SC_NOT_MODIFIED = 304; /** * 接收来自 public service方法的标准HTTP请求, * 并将它们分发给此类中定义的doXXX方法。 */ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取请求方法名 String method = req.getMethod(); // 如果是GET请求 if (method.equals(METHOD_GET)) { // 上一次修改HttpServletRequest对象的时间 long lastModified = getLastModified(req); // 没有改变 if (lastModified == -1) { doGet(req, resp); } else { long ifModifiedSince; try { // 获取请求头中服务器修改时间 ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); } catch (IllegalArgumentException iae) { // 获取无效 ifModifiedSince = -1; } // 如果请求头服务器修改时间迟 if (ifModifiedSince < (lastModified / 1000 * 1000)) { // 设置修改HttpServletResponse对象的时间,重新设置浏览器的参数 //maybeSetLastModified(resp, lastModified); // 调用doGet方法 doGet(req, resp); } else { // 304 HTTP状态码 resp.setStatus(SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); //maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // 如果没有被请求到的话 String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); // 501 HTTP状态码 resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
休息休息,小广告插一下 :(维持生计,O(∩_∩)O~)
涉及到的 代码 都会在 开源项目 servlet-core-learning 。 简介 — Servlet/JSP学习积累的例子,是Java EE初学者及Servlet/JSP核心技术巩固的 最佳实践
1、接受 public service接收的标准HTTP请求。
2、分发到定义的doXXX方法
上面对于GET请求代码处理如下:
// 如果是GET请求 if (method.equals(METHOD_GET)) { // 上一次修改HttpServletRequest对象的时间 long lastModified = getLastModified(req); // 没有改变 if (lastModified == -1) { doGet(req, resp); } else { long ifModifiedSince; try { // 获取请求头中服务器修改时间 ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); } catch (IllegalArgumentException iae) { // 获取无效 ifModifiedSince = -1; } // 如果请求头服务器修改时间迟 if (ifModifiedSince < (lastModified / 1000 * 1000)) { // 设置修改HttpServletResponse对象的时间,重新设置浏览器的参数 //maybeSetLastModified(resp, lastModified); // 调用doGet方法 doGet(req, resp); } else { // 304 HTTP状态码 resp.setStatus(SC_NOT_MODIFIED); } } }
这里,
这个getLastModified,是HttpServlet定义了用于支持有条件GET操作。即当客户端通过GET请求获取资源时,当资源自第一次获取那个实际点发生更改后才再次发生数据,否则将使用客户端缓存的数据。
在一些适当的场合,实现此方法可以更有效的利用网络资源,减少不必要的数据发送。
比如说 304 这个场景我在《 JavaEE 要懂的小事:一、图解Http协议 》文章中提到,第一次访问 百度 首页时,有些资源会成功获取 返回 200 。 再次F5 ,有些资源或直接调用客户端的缓存数据,则返回 304 。
Servlet容器可以 并发 路由多个请求到 Servlet 的 service 方法。为了处理这些请求,Servlet必须在并发及线程安全问题做好处理。上一篇的《 Servlet必会必知 》提到定义 全局变量会造成线程安全问题 。在开发Servlet时,考虑线程安全问题提出了一下 解决 :
1、实现 SingleThreadModel 接口
Servlet2.4 已经提出不提倡使用。实现此接口,Servlet容器为每个新的请求创建一个单独的Servlet实例。这会有 严重性能问题 。
使用synchronized关键字,虽然可以保证只有一个线程可以访问被保护区段,已达到保证线程安全。但是系统性能及并发量大大降低。不可取~
方法中的 局部变量 分配在 栈 空间, 每个线程 有私有的 栈空间 。因此访问是 线程安全 的。
我想到了以下一个问题:
既然Sevlet的全局变量是线程不安全的,那 SpringMVC Controller 也一样。那我们在 Controller 定义个 XXXService 变量 会不会造成线程安全呢?
答:因为这是Spring的一个Service Bean,是 线程安全 的,所以可以作为 单例 使用,不会造成线程安全。
补充文章内容要点:
HttpServlet service 方法详解
深入理解 代码 对HTTP状态码的运用
Servlet的线程安全问题
欢迎点击我的博客及GitHub — 博客提供RSS订阅哦
———- http://www.bysocket.com/ ————- https://github.com/JeffLi1993 ———-