• Java web基础知识


    Servlet

    Servlet是sun公司开发的动态web技术
    sun在API中提供了一个接口叫做 Servlet ,一个简单的Servlet 程序只需要完成两个步骤
    • 编写一个实现了Servlet接口的类
    • 把这个Java部署到web服务器中

    一般来说把实现了Servlet接口的java程序叫做,Servlet

    初步认识Servlet

    Servlet接口sun公司有两个默认的实现抽象类:HttpServlet,GenericServlet

    看看Serlvet接口是怎么在这两个类中实现的

    Servlet接口

    1. package javax.servlet;
    2. import java.io.IOException;
    3. public interface Servlet {
    4. void init(ServletConfig var1) throws ServletException;
    5. ServletConfig getServletConfig();
    6. void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    7. String getServletInfo();
    8. void destroy();
    9. }

    这个接口里有五个抽象方法

    • init(ServletConfig var1)
    • getServletConfig()
    • service(ServletRequest var1, ServletResponse var2)
    • getServletInfo()
    • destroy()

    这五个方法建立起了Servlet的基本框架:初始化、获取配置、服务功能、获取状态信息、销毁

    也体现了servlet的生命周期

    • Servlet 初始化后调用 init () 方法。
    • Servlet 调用 service() 方法来处理客户端的请求。
    • Servlet 销毁前调用 destroy() 方法。
    • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

    其中比较值得观察的是service方法

    GenericServlet

    1. package javax.servlet;
    2. import java.io.IOException;
    3. import java.io.Serializable;
    4. import java.util.Enumeration;
    5. public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    6. private static final long serialVersionUID = 1L;
    7. private transient ServletConfig config;
    8. public GenericServlet() {
    9. }
    10. public void destroy() {
    11. }
    12. public String getInitParameter(String name) {
    13. return this.getServletConfig().getInitParameter(name);
    14. }
    15. public Enumeration getInitParameterNames() {
    16. return this.getServletConfig().getInitParameterNames();
    17. }
    18. public ServletConfig getServletConfig() {
    19. return this.config;
    20. }
    21. public ServletContext getServletContext() {
    22. return this.getServletConfig().getServletContext();
    23. }
    24. public String getServletInfo() {
    25. return "";
    26. }
    27. public void init(ServletConfig config) throws ServletException {
    28. this.config = config;
    29. this.init();
    30. }
    31. public void init() throws ServletException {
    32. }
    33. public void log(String message) {
    34. this.getServletContext().log(this.getServletName() + ": " + message);
    35. }
    36. public void log(String message, Throwable t) {
    37. this.getServletContext().log(this.getServletName() + ": " + message, t);
    38. }
    39. public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    40. public String getServletName() {
    41. return this.config.getServletName();
    42. }
    43. }

    还是那五个抽象方法

    • init(ServletConfig var1)
    • getServletConfig()
    • service(ServletRequest var1, ServletResponse var2)
    • getServletInfo()
    • destroy()

    可以看到对于service方法这个类并没有做任何的改变,只是对初始化和状态信息获取做出了改变

    HttpServlet

    1. package javax.servlet.http;
    2. import java.io.IOException;
    3. import java.lang.reflect.Method;
    4. import java.text.MessageFormat;
    5. import java.util.Enumeration;
    6. import java.util.ResourceBundle;
    7. import javax.servlet.GenericServlet;
    8. import javax.servlet.ServletException;
    9. import javax.servlet.ServletOutputStream;
    10. import javax.servlet.ServletRequest;
    11. import javax.servlet.ServletResponse;
    12. public abstract class HttpServlet extends GenericServlet {
    13. private static final String METHOD_DELETE = "DELETE";
    14. private static final String METHOD_HEAD = "HEAD";
    15. private static final String METHOD_GET = "GET";
    16. private static final String METHOD_OPTIONS = "OPTIONS";
    17. private static final String METHOD_POST = "POST";
    18. private static final String METHOD_PUT = "PUT";
    19. private static final String METHOD_TRACE = "TRACE";
    20. private static final String HEADER_IFMODSINCE = "If-Modified-Since";
    21. private static final String HEADER_LASTMOD = "Last-Modified";
    22. private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
    23. private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");
    24. public HttpServlet() {
    25. }
    26. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    27. String protocol = req.getProtocol();
    28. String msg = lStrings.getString("http.method_get_not_supported");
    29. if (protocol.endsWith("1.1")) {
    30. resp.sendError(405, msg);
    31. } else {
    32. resp.sendError(400, msg);
    33. }
    34. }
    35. protected long getLastModified(HttpServletRequest req) {
    36. return -1L;
    37. }
    38. protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    39. NoBodyResponse response = new NoBodyResponse(resp);
    40. this.doGet(req, response);
    41. response.setContentLength();
    42. }
    43. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    44. String protocol = req.getProtocol();
    45. String msg = lStrings.getString("http.method_post_not_supported");
    46. if (protocol.endsWith("1.1")) {
    47. resp.sendError(405, msg);
    48. } else {
    49. resp.sendError(400, msg);
    50. }
    51. }
    52. protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    53. String protocol = req.getProtocol();
    54. String msg = lStrings.getString("http.method_put_not_supported");
    55. if (protocol.endsWith("1.1")) {
    56. resp.sendError(405, msg);
    57. } else {
    58. resp.sendError(400, msg);
    59. }
    60. }
    61. protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    62. String protocol = req.getProtocol();
    63. String msg = lStrings.getString("http.method_delete_not_supported");
    64. if (protocol.endsWith("1.1")) {
    65. resp.sendError(405, msg);
    66. } else {
    67. resp.sendError(400, msg);
    68. }
    69. }
    70. private Method[] getAllDeclaredMethods(Classextends HttpServlet> c) {
    71. Class clazz = c;
    72. Method[] allMethods;
    73. for(allMethods = null; !clazz.equals(HttpServlet.class); clazz = clazz.getSuperclass()) {
    74. Method[] thisMethods = clazz.getDeclaredMethods();
    75. if (allMethods != null && allMethods.length > 0) {
    76. Method[] subClassMethods = allMethods;
    77. allMethods = new Method[thisMethods.length + allMethods.length];
    78. System.arraycopy(thisMethods, 0, allMethods, 0, thisMethods.length);
    79. System.arraycopy(subClassMethods, 0, allMethods, thisMethods.length, subClassMethods.length);
    80. } else {
    81. allMethods = thisMethods;
    82. }
    83. }
    84. return allMethods != null ? allMethods : new Method[0];
    85. }
    86. protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    87. Method[] methods = this.getAllDeclaredMethods(this.getClass());
    88. boolean ALLOW_GET = false;
    89. boolean ALLOW_HEAD = false;
    90. boolean ALLOW_POST = false;
    91. boolean ALLOW_PUT = false;
    92. boolean ALLOW_DELETE = false;
    93. boolean ALLOW_TRACE = true;
    94. boolean ALLOW_OPTIONS = true;
    95. for(int i = 0; i < methods.length; ++i) {
    96. String methodName = methods[i].getName();
    97. if (methodName.equals("doGet")) {
    98. ALLOW_GET = true;
    99. ALLOW_HEAD = true;
    100. } else if (methodName.equals("doPost")) {
    101. ALLOW_POST = true;
    102. } else if (methodName.equals("doPut")) {
    103. ALLOW_PUT = true;
    104. } else if (methodName.equals("doDelete")) {
    105. ALLOW_DELETE = true;
    106. }
    107. }
    108. StringBuilder allow = new StringBuilder();
    109. if (ALLOW_GET) {
    110. allow.append("GET");
    111. }
    112. if (ALLOW_HEAD) {
    113. if (allow.length() > 0) {
    114. allow.append(", ");
    115. }
    116. allow.append("HEAD");
    117. }
    118. if (ALLOW_POST) {
    119. if (allow.length() > 0) {
    120. allow.append(", ");
    121. }
    122. allow.append("POST");
    123. }
    124. if (ALLOW_PUT) {
    125. if (allow.length() > 0) {
    126. allow.append(", ");
    127. }
    128. allow.append("PUT");
    129. }
    130. if (ALLOW_DELETE) {
    131. if (allow.length() > 0) {
    132. allow.append(", ");
    133. }
    134. allow.append("DELETE");
    135. }
    136. if (ALLOW_TRACE) {
    137. if (allow.length() > 0) {
    138. allow.append(", ");
    139. }
    140. allow.append("TRACE");
    141. }
    142. if (ALLOW_OPTIONS) {
    143. if (allow.length() > 0) {
    144. allow.append(", ");
    145. }
    146. allow.append("OPTIONS");
    147. }
    148. resp.setHeader("Allow", allow.toString());
    149. }
    150. protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    151. String CRLF = "\r\n";
    152. StringBuilder buffer = (new StringBuilder("TRACE ")).append(req.getRequestURI()).append(" ").append(req.getProtocol());
    153. Enumeration reqHeaderEnum = req.getHeaderNames();
    154. while(reqHeaderEnum.hasMoreElements()) {
    155. String headerName = (String)reqHeaderEnum.nextElement();
    156. buffer.append(CRLF).append(headerName).append(": ").append(req.getHeader(headerName));
    157. }
    158. buffer.append(CRLF);
    159. int responseLength = buffer.length();
    160. resp.setContentType("message/http");
    161. resp.setContentLength(responseLength);
    162. ServletOutputStream out = resp.getOutputStream();
    163. out.print(buffer.toString());
    164. }
    165. protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    166. String method = req.getMethod();
    167. long lastModified;
    168. if (method.equals("GET")) {
    169. lastModified = this.getLastModified(req);
    170. if (lastModified == -1L) {
    171. this.doGet(req, resp);
    172. } else {
    173. long ifModifiedSince = req.getDateHeader("If-Modified-Since");
    174. if (ifModifiedSince < lastModified) {
    175. this.maybeSetLastModified(resp, lastModified);
    176. this.doGet(req, resp);
    177. } else {
    178. resp.setStatus(304);
    179. }
    180. }
    181. } else if (method.equals("HEAD")) {
    182. lastModified = this.getLastModified(req);
    183. this.maybeSetLastModified(resp, lastModified);
    184. this.doHead(req, resp);
    185. } else if (method.equals("POST")) {
    186. this.doPost(req, resp);
    187. } else if (method.equals("PUT")) {
    188. this.doPut(req, resp);
    189. } else if (method.equals("DELETE")) {
    190. this.doDelete(req, resp);
    191. } else if (method.equals("OPTIONS")) {
    192. this.doOptions(req, resp);
    193. } else if (method.equals("TRACE")) {
    194. this.doTrace(req, resp);
    195. } else {
    196. String errMsg = lStrings.getString("http.method_not_implemented");
    197. Object[] errArgs = new Object[]{method};
    198. errMsg = MessageFormat.format(errMsg, errArgs);
    199. resp.sendError(501, errMsg);
    200. }
    201. }
    202. private void maybeSetLastModified(HttpServletResponse resp, long lastModified) {
    203. if (!resp.containsHeader("Last-Modified")) {
    204. if (lastModified >= 0L) {
    205. resp.setDateHeader("Last-Modified", lastModified);
    206. }
    207. }
    208. }
    209. public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    210. if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
    211. HttpServletRequest request = (HttpServletRequest)req;
    212. HttpServletResponse response = (HttpServletResponse)res;
    213. this.service(request, response);
    214. } else {
    215. throw new ServletException("non-HTTP request or response");
    216. }
    217. }
    218. }

    可以看到这层的类实现了service方法的处理,每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

    但是它默认处理并不是我们所需要的,所以我们自己写的java类就是要重写这些方法。

    现在,这个简单的Servlet基础使用链就明了了

    RMI

    RMI (Java Remote Method Invocation) Java 远程方法调用,是一种允许一个 JVM 上的 object 调用另一个 JVM 上 object 方法的机制

    ⼀个RMI Server分为三部分:

    • ⼀个继承了 java.rmi.Remote 的接⼝,其中定义我们要远程调⽤的函数
    • ⼀个实现了此接⼝的类
    • ⼀个主类,⽤来创建Registry,并将上⾯的类实例化后绑定到⼀个地址

    来分析一下这个RMI设计的意图

    一个RMI服务器的三个部分:一个接口、两个类,我理解的它们的作用如下:

    • 接口:作为远程方法调用的调用目标
    • 实现接口的类:用来承载接口方法
    为什么要有这样一个类?
    有类就可以序列化,序列化之后就可以把一个难以传输的目标变成一个便于传输的流
    • 一个主类:作为Registry存在。
    打个比方,它就像一个车站的售票处一样,你来坐车你就要先去它哪里找他买票,你有了对应的票才能找到、乘坐对应的车。
    在RMI整体流程它也差不多扮演这个角色,客户端去向Registry请求某个方法,Registry返回一个stub给客户端,客户端在通过stub种的信息找到对应的地址端口建立TCP连接

    RMI简单流程

    一个简单的demo

    服务端

    1. package rmilearn;
    2. import java.net.MalformedURLException;
    3. import java.rmi.Naming;
    4. import java.rmi.RemoteException;
    5. import java.rmi.registry.LocateRegistry;
    6. import java.rmi.server.UnicastRemoteObject;
    7. public class Learn01 {
    8. public static void main(String[] args) throws RemoteException, MalformedURLException {
    9. HelloRmi rmi = new HelloRmi();
    10. LocateRegistry.createRegistry(1099);
    11. Naming.rebind("rmi://127.0.0.1:1099/hello",rmi);
    12. }
    13. }
    14. class HelloRmi extends UnicastRemoteObject implements Hello {
    15. protected HelloRmi() throws RemoteException {
    16. super();
    17. }
    18. @Override
    19. public String HelloRm() throws RemoteException {
    20. return "hello rmi";
    21. }
    22. }
    23. --------------------------------------------------------------------------
    24. package rmilearn;
    25. import java.rmi.Remote;
    26. import java.rmi.RemoteException;
    27. public interface Hello extends Remote {
    28. String HelloRm() throws RemoteException;
    29. }

    客户端

    1. public class client {
    2. public static void main(String[] args) throws RemoteException, NotBoundException {
    3. Registry re = LocateRegistry.getRegistry("localhost",1099);
    4. Hello h = (Hello) re.lookup("hello");
    5. String s = h.HelloRm();
    6. System.out.println(s);
    7. }
    8. }
  • 相关阅读:
    [经验] 玄殿社区qq堂4.2 #笔记#媒体
    安装 Red Hat Enterprise Linux 9.1 虚拟机
    Django老项目升级到新版本
    网络编程扩展
    ambari搭建HDP集群后修改存储元数据的mysql数据库配置
    闭关三个月,腾讯大咖手写Framework最新源码笔记,从基础到进阶直接封神
    中国程序员做独立开发者的怎么这么少呢?
    堪比坐牢!深圳一公司给每个工位都装监控,只为防止泄密?
    Elasticsearch 8.9 Bulk批量给索引增加数据源码
    微信小程序反编译 2024 unveilr.exe
  • 原文地址:https://blog.csdn.net/why811/article/details/133020263