Tomcat学习2.1(简单的Servlet容器)

本文是学习《Tomcat深入剖析》后,对书中内容的总结,主要用于自己学习记录,纯手打。。。

Servlet定义:Servlet是运行在服务的一个小程序(由若干个类组成,并完成指定的功能)。

Servlet的调用过程:浏览器发送请求到服务器端,服务器端(如:Tomcat)接收请求后按照Http协议提取出URI,然后再根据URI中Servlet的名字,利用Java反射机制加载Servlet,最后执行相应的业务逻辑。

所有的Servlet必须实现javax.servlet.Servlet这个接口(为什么必须实现这个接口呢?百度搜索  实现接口的好处得意

下面将建立一个非常简单的Servlet容器,它不会像Tomcat那样完成所有功能,仅仅有以下功能:

1、等待HTTP请求;

2、创建一个servletRequest对象(解析HTTP请求)和一个servletResponse对象(发送数据到浏览器);

3、判断请求的是一个静态资源还是一个Servlet类,并执行对应的方法。

本程序一共有6个类:MyHttpServer(启动程序)、Request(解析请求)、Response(发送数据)、StaticResourceProcessor(处理静态请求)、ServletProcessor(处理Servlet请求)、Constans(常量存放)

以下是容器的UML类图:


================分割线================

[java]  view plain  copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.io.OutputStream;  
  4. import java.net.InetAddress;  
  5. import java.net.ServerSocket;  
  6. import java.net.Socket;  
  7. import java.net.UnknownHostException;  
  8. /** 
  9.  *  
  10.  * MyHttpServer类主要作用: 
  11.  * 设置服务器根路径WEB_ROOT 
  12.  * new一个SeverSocket实例监听对应的端口当有响应到达时,调用accept方法返回一个Socket实例 
  13.  * 获取Socket实例的输入输出流,使用自定义的Request对输入流按照Http协议进行解析,Response则按照Http协议进行数据的发送 
  14.  */  
  15. public class MyHttpServer {  
  16.     /** 
  17.      * 定义服务关闭指令 
  18.      */  
  19.     private static final String SHUTDOWN_COMMAND="/SHUTDOWN";  
  20.       
  21.     /** 
  22.      * 定义服务器关闭状态,例如:shutdown=false表示服务正在运行 
  23.      */  
  24.     private boolean shutdown=false;  
  25.       
  26.     public  static void main(String[] args){  
  27.         MyHttpServer myMailServer=new MyHttpServer();  
  28.         myMailServer.await();  
  29.     }  
  30.       
  31.     public void await(){  
  32.         ServerSocket serverSocket=null;  
  33.         /** 
  34.          * 指定服务器默认监听端口 
  35.          */  
  36.         int port = 8888;  
  37.         /** 
  38.          * 指定服务器请求队列最大长度 
  39.          */  
  40.         int backlog=1;  
  41.         /** 
  42.          * 指定serverSocket监听的主机 
  43.          */  
  44.         InetAddress address= null;  
  45.         try {  
  46.             address= InetAddress.getByName("127.0.0.1");  
  47.             serverSocket=new ServerSocket(port, backlog, address);  
  48.         }catch(UnknownHostException e){  
  49.             e.printStackTrace();  
  50.             System.exit(1);  
  51.         }catch (IOException e) {  
  52.             e.printStackTrace();  
  53.             System.exit(1);  
  54.         }  
  55.         System.out.println("服务器已成功启动");  
  56.         while(!shutdown){  
  57.             Socket socket=null;  
  58.             InputStream inputStream=null;  
  59.             OutputStream outputStream=null;  
  60.               
  61.             try {  
  62.                 socket=serverSocket.accept();  
  63.                 System.out.println("服务器收到一个请求");  
  64.                 inputStream=socket.getInputStream();  
  65.                 outputStream=socket.getOutputStream();  
  66.             /** 
  67.              * 构建一个Request类,用以解析Http请求的原始数据 
  68.              */   
  69.             Request request =new Request(inputStream);  
  70.             /** 
  71.              * 解析Http请求 
  72.              */  
  73.             request.parse();  
  74.             /** 
  75.              * 构建一个Response类,用以返回请求 
  76.              */  
  77.             Response response=new Response(outputStream);  
  78.             /** 
  79.              * 设置response,为返回请求做准备 
  80.              */  
  81.             response.setRequest(request);  
  82.             /** 
  83.              * 判断Http请求静态资源还是servlet 
  84.              *  例如浏览器中输入 127.0.0.1:8888/servlet/MyFirstServlet , 
  85.              * 其中/servlet/表示请求的是一个servlet,servlet名称为MyFirstServlet 
  86.              */  
  87.             if(request.getUri().startsWith("/servlet")){  
  88.                 /** 
  89.                  * 如果Http请求servlet,调用ServletProcessor进行处理 
  90.                  */  
  91.                 ServletProcessor servletProcessor=new ServletProcessor();  
  92.                 servletProcessor.process(request,response);  
  93.             }else{  
  94.                 /** 
  95.                  * 如果Http请求静态资源,调用StaticResourceProcessor进行处理 
  96.                  */  
  97.                 StaticResourceProcessor staticResourceProcessor=new StaticResourceProcessor();  
  98.                 staticResourceProcessor.process(request,response);  
  99.             }  
  100.               
  101.             socket.close();  
  102.   
  103.             shutdown=request.getUri().equals(SHUTDOWN_COMMAND);  
  104.               
  105.             } catch (Exception e) {  
  106.                 e.printStackTrace();  
  107.             }     
  108.         }  
  109.         System.out.println("服务器关闭");  
  110.     }  
  111. }  
================分割线================
[java]  view plain  copy
  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStream;  
  4. import java.io.UnsupportedEncodingException;  
  5. import java.util.Enumeration;  
  6. import java.util.Locale;  
  7. import java.util.Map;  
  8.   
  9. import javax.servlet.AsyncContext;  
  10. import javax.servlet.DispatcherType;  
  11. import javax.servlet.RequestDispatcher;  
  12. import javax.servlet.ServletContext;  
  13. import javax.servlet.ServletInputStream;  
  14. import javax.servlet.ServletRequest;  
  15. import javax.servlet.ServletResponse;  
  16.   
  17. public class Request implements ServletRequest{  
  18.   
  19.     private InputStream inputStream;  
  20.     private String uri;  
  21.       
  22.     /** 
  23.      * 创建Request时传入一个InputStream对象 
  24.      */  
  25.     public Request(InputStream inputStream) {  
  26.         this.inputStream=inputStream;  
  27.     }  
  28.     /** 
  29.      * parse()方法作用是将浏览器发送到服务器到数据转换为一个字符串 
  30.      */  
  31.     public void parse() {  
  32.         /** 
  33.          * 定义一个StringBuffer对象,用以存储InputStream中传入的数据 
  34.          */  
  35.         StringBuffer request=new StringBuffer(2048);  
  36.         byte[] bytes=new byte[2048];  
  37.         int i=-1;  
  38.         try {  
  39.             /** 
  40.              * 读取inputStream中的数据,并把读取的存入一个byte数组中 
  41.              */  
  42.             i=this.inputStream.read(bytes);  
  43.         } catch (IOException e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.         for(int j=0;j<i;j++){  
  47.             /** 
  48.              * 将byte数组中的数据放入StringBuffer中 
  49.              */  
  50.             request.append((char)bytes[j]);  
  51.         }  
  52.         System.out.println(request.toString());  
  53.           
  54.         this.uri=parseUri(request.toString());  
  55.     }  
  56.     /** 
  57.      * parseUri()的作用是提取字符串request中的Uri 
  58.      */  
  59.     private String parseUri(String requestString){  
  60.         int index1,index2;  
  61.         index1=requestString.indexOf(' ');  
  62.         if(index1!=-1){  
  63.             index2=requestString.indexOf(' ',index1+1);  
  64.             if(index2>index1){  
  65.                 return requestString.substring(index1+1, index2);  
  66.             }  
  67.         }  
  68.         return null;  
  69.     }  
  70.       
  71.     public String getUri() {  
  72.         return this.uri;  
  73.     }  
  74.   
  75.     @Override  
  76.     public AsyncContext getAsyncContext() {  
  77.         // TODO Auto-generated method stub  
  78.         return null;  
  79.     }  
  80.   
  81.     @Override  
  82.     public Object getAttribute(String name) {  
  83.         // TODO Auto-generated method stub  
  84.         return null;  
  85.     }  
  86.   
  87.     @Override  
  88.     public Enumeration<String> getAttributeNames() {  
  89.         // TODO Auto-generated method stub  
  90.         return null;  
  91.     }  
  92.   
  93.     @Override  
  94.     public String getCharacterEncoding() {  
  95.         // TODO Auto-generated method stub  
  96.         return null;  
  97.     }  
  98.   
  99.     @Override  
  100.     public int getContentLength() {  
  101.         // TODO Auto-generated method stub  
  102.         return 0;  
  103.     }  
  104.   
  105.     @Override  
  106.     public String getContentType() {  
  107.         // TODO Auto-generated method stub  
  108.         return null;  
  109.     }  
  110.   
  111.     @Override  
  112.     public DispatcherType getDispatcherType() {  
  113.         // TODO Auto-generated method stub  
  114.         return null;  
  115.     }  
  116.   
  117.     @Override  
  118.     public ServletInputStream getInputStream() throws IOException {  
  119.         // TODO Auto-generated method stub  
  120.         return null;  
  121.     }  
  122.   
  123.     @Override  
  124.     public String getLocalAddr() {  
  125.         // TODO Auto-generated method stub  
  126.         return null;  
  127.     }  
  128.   
  129.     @Override  
  130.     public String getLocalName() {  
  131.         // TODO Auto-generated method stub  
  132.         return null;  
  133.     }  
  134.   
  135.     @Override  
  136.     public int getLocalPort() {  
  137.         // TODO Auto-generated method stub  
  138.         return 0;  
  139.     }  
  140.   
  141.     @Override  
  142.     public Locale getLocale() {  
  143.         // TODO Auto-generated method stub  
  144.         return null;  
  145.     }  
  146.   
  147.     @Override  
  148.     public Enumeration<Locale> getLocales() {  
  149.         // TODO Auto-generated method stub  
  150.         return null;  
  151.     }  
  152.   
  153.     @Override  
  154.     public String getParameter(String name) {  
  155.         // TODO Auto-generated method stub  
  156.         return null;  
  157.     }  
  158.   
  159.     @Override  
  160.     public Map<String, String[]> getParameterMap() {  
  161.         // TODO Auto-generated method stub  
  162.         return null;  
  163.     }  
  164.   
  165.     @Override  
  166.     public Enumeration<String> getParameterNames() {  
  167.         // TODO Auto-generated method stub  
  168.         return null;  
  169.     }  
  170.   
  171.     @Override  
  172.     public String[] getParameterValues(String name) {  
  173.         // TODO Auto-generated method stub  
  174.         return null;  
  175.     }  
  176.   
  177.     @Override  
  178.     public String getProtocol() {  
  179.         // TODO Auto-generated method stub  
  180.         return null;  
  181.     }  
  182.   
  183.     @Override  
  184.     public BufferedReader getReader() throws IOException {  
  185.         // TODO Auto-generated method stub  
  186.         return null;  
  187.     }  
  188.   
  189.     @Override  
  190.     public String getRealPath(String path) {  
  191.         // TODO Auto-generated method stub  
  192.         return null;  
  193.     }  
  194.   
  195.     @Override  
  196.     public String getRemoteAddr() {  
  197.         // TODO Auto-generated method stub  
  198.         return null;  
  199.     }  
  200.   
  201.     @Override  
  202.     public String getRemoteHost() {  
  203.         // TODO Auto-generated method stub  
  204.         return null;  
  205.     }  
  206.   
  207.     @Override  
  208.     public int getRemotePort() {  
  209.         // TODO Auto-generated method stub  
  210.         return 0;  
  211.     }  
  212.   
  213.     @Override  
  214.     public RequestDispatcher getRequestDispatcher(String path) {  
  215.         // TODO Auto-generated method stub  
  216.         return null;  
  217.     }  
  218.   
  219.     @Override  
  220.     public String getScheme() {  
  221.         // TODO Auto-generated method stub  
  222.         return null;  
  223.     }  
  224.   
  225.     @Override  
  226.     public String getServerName() {  
  227.         // TODO Auto-generated method stub  
  228.         return null;  
  229.     }  
  230.   
  231.     @Override  
  232.     public int getServerPort() {  
  233.         // TODO Auto-generated method stub  
  234.         return 0;  
  235.     }  
  236.   
  237.     @Override  
  238.     public ServletContext getServletContext() {  
  239.         // TODO Auto-generated method stub  
  240.         return null;  
  241.     }  
  242.   
  243.     @Override  
  244.     public boolean isAsyncStarted() {  
  245.         // TODO Auto-generated method stub  
  246.         return false;  
  247.     }  
  248.   
  249.     @Override  
  250.     public boolean isAsyncSupported() {  
  251.         // TODO Auto-generated method stub  
  252.         return false;  
  253.     }  
  254.   
  255.     @Override  
  256.     public boolean isSecure() {  
  257.         // TODO Auto-generated method stub  
  258.         return false;  
  259.     }  
  260.   
  261.     @Override  
  262.     public void removeAttribute(String name) {  
  263.         // TODO Auto-generated method stub  
  264.           
  265.     }  
  266.   
  267.     @Override  
  268.     public void setAttribute(String name, Object o) {  
  269.         // TODO Auto-generated method stub  
  270.           
  271.     }  
  272.   
  273.     @Override  
  274.     public void setCharacterEncoding(String env)  
  275.             throws UnsupportedEncodingException {  
  276.         // TODO Auto-generated method stub  
  277.           
  278.     }  
  279.   
  280.     @Override  
  281.     public AsyncContext startAsync() throws IllegalStateException {  
  282.         // TODO Auto-generated method stub  
  283.         return null;  
  284.     }  
  285.   
  286.     @Override  
  287.     public AsyncContext startAsync(ServletRequest servletRequest,  
  288.             ServletResponse servletResponse) throws IllegalStateException {  
  289.         // TODO Auto-generated method stub  
  290.         return null;  
  291.     }  
  292.   
  293.   
  294. }  
================分割线================
[java]  view plain  copy
  1. import java.io.File;  
  2. import java.io.FileInputStream;  
  3. import java.io.FileNotFoundException;  
  4. import java.io.IOException;  
  5. import java.io.OutputStream;  
  6. import java.io.PrintWriter;  
  7. import java.util.Locale;  
  8.   
  9. import javax.servlet.ServletOutputStream;  
  10. import javax.servlet.ServletResponse;  
  11.   
  12. public class Response implements ServletResponse {  
  13.     /** 
  14.      * 定义一个默认缓存字节长度 
  15.      */  
  16.     private static final int BUFFER_SIZE=1024;  
  17.     private OutputStream outputStream;  
  18.     /** 
  19.      * 定义一个request对象,获取request中的uri 
  20.      */  
  21.     private Request request;  
  22.   
  23.     private PrintWriter printWriter;  
  24.   
  25.     public PrintWriter getPrintWriter() {  
  26.         return printWriter;  
  27.     }  
  28.   
  29.     public void setPrintWriter(PrintWriter printWriter) {  
  30.         this.printWriter = printWriter;  
  31.     }  
  32.   
  33.     public Response(OutputStream outputStream) {  
  34.         this.outputStream=outputStream;  
  35.     }  
  36.   
  37.     public void setRequest(Request request) {  
  38.         this.request=request;  
  39.     }  
  40.   
  41.     public void sendStaticResource() throws IOException{  
  42.         byte[] bytes=new byte[BUFFER_SIZE];  
  43.         FileInputStream fis=null;  
  44.         try {  
  45.             /** 
  46.              * 加载请求资源文件 
  47.              */  
  48.             File file=null;  
  49.   
  50.             file=new File(Constants.WEB_ROOT,request.getUri());  
  51.             System.out.println("请求资源绝对路径"+file.getAbsolutePath());  
  52.             if(file.exists()){  
  53.                 fis=new FileInputStream(file);  
  54.                 /** 
  55.                  * 读取file,每次读取长度为BUFFER_SIZE 
  56.                  */  
  57.                 int ch=fis.read(bytes, 0, BUFFER_SIZE);  
  58.                 while(ch!=-1){  
  59.                     this.outputStream.write(bytes, 0, ch);  
  60.                     ch=fis.read(bytes, 0, BUFFER_SIZE);  
  61.                 }  
  62.             }  
  63.         } catch (FileNotFoundException e) {  
  64.             String errorMessage="HTTP/1.1 404 File Not Found\r\n"+  
  65.                     "Context-Type:text/html\r\n"+  
  66.                     "Context-Length:23\r\n"+  
  67.                     "\r\n"+  
  68.                     "<h1>File Not Found</h1>";  
  69.             this.outputStream.write(errorMessage.getBytes());  
  70.             e.printStackTrace();  
  71.         }finally{  
  72.             if(fis!=null){  
  73.                 fis.close();  
  74.             }  
  75.         }  
  76.     }  
  77.   
  78.     @Override  
  79.     public void flushBuffer() throws IOException {  
  80.   
  81.     }  
  82.   
  83.     @Override  
  84.     public int getBufferSize() {  
  85.         return 0;  
  86.     }  
  87.   
  88.     @Override  
  89.     public String getCharacterEncoding() {  
  90.         return null;  
  91.     }  
  92.   
  93.     @Override  
  94.     public String getContentType() {  
  95.         return null;  
  96.     }  
  97.   
  98.     @Override  
  99.     public Locale getLocale() {  
  100.         return null;  
  101.     }  
  102.   
  103.     @Override  
  104.     public ServletOutputStream getOutputStream() throws IOException {  
  105.         return null;  
  106.     }  
  107.   
  108.     @Override  
  109.     public PrintWriter getWriter() throws IOException {  
  110.         this.printWriter = new PrintWriter(this.outputStream,true);  
  111.         return printWriter;  
  112.     }  
  113.   
  114.     @Override  
  115.     public boolean isCommitted() {  
  116.         return false;  
  117.     }  
  118.   
  119.     @Override  
  120.     public void reset() {  
  121.   
  122.     }  
  123.   
  124.     @Override  
  125.     public void resetBuffer() {  
  126.   
  127.     }  
  128.   
  129.     @Override  
  130.     public void setBufferSize(int arg0) {  
  131.   
  132.     }  
  133.   
  134.     @Override  
  135.     public void setCharacterEncoding(String arg0) {  
  136.   
  137.     }  
  138.   
  139.     @Override  
  140.     public void setContentLength(int arg0) {  
  141.   
  142.     }  
  143.   
  144.     @Override  
  145.     public void setContentType(String arg0) {  
  146.   
  147.     }  
  148.   
  149.     @Override  
  150.     public void setLocale(Locale arg0) {  
  151.   
  152.     }  
  153.   
  154. }  
================分割线================
[java]  view plain  copy
  1. import java.io.IOException;  
  2.   
  3. public class StaticResourceProcessor {  
  4.   
  5.     public void process(Request request, Response response) {  
  6.         try {  
  7.             response.sendStaticResource();  
  8.         } catch (IOException e) {  
  9.             e.printStackTrace();  
  10.         }  
  11.     }  
  12. }  
================分割线================
[java]  view plain  copy
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import java.net.MalformedURLException;  
  4. import java.net.URL;  
  5. import java.net.URLClassLoader;  
  6. import java.net.URLStreamHandler;  
  7.   
  8. import javax.servlet.Servlet;  
  9. import javax.servlet.ServletException;  
  10.   
  11. public class ServletProcessor {  
  12.   
  13.     public void process(Request request, Response response) {  
  14.         /** 
  15.          * 获取传入request的uri 
  16.          */  
  17.         String uri=request.getUri();  
  18.         /** 
  19.          * 截取uri中请求的servletName 
  20.          */  
  21.         String servletName=uri.substring(uri.lastIndexOf("/")+1);  
  22.         /** 
  23.          * 定义一个URLClassLoader,用以加载指定路径下的类。 
  24.          * ClassLoader只能加载classpath下的类,URLClassLoader可以加载任意路径下的类 
  25.          */  
  26.         URLClassLoader urlClassLoader=null;  
  27.         /** 
  28.          * 定义一个URL类数组(只存放一个数据),类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或 
  29.          * 目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。 
  30.          */  
  31.         URL[] urls=new URL[1];  
  32.         /** 
  33.          * 定义一个URLStreamHandler 
  34.          */  
  35.         URLStreamHandler urlStreamHandler=null;  
  36.         /** 
  37.          * 指定服务器WebRoot目录的路径 
  38.          */  
  39.         File classpath=new File(Constants.WEB_ROOT);  
  40.           
  41.         try {  
  42.   
  43.             String repository=(new URL("file",null,classpath.getCanonicalPath()+File.separator)).toString();  
  44.               
  45.             System.out.println("请求资源目录:"+repository);  
  46.               
  47.             urls[0]=new URL(null,repository,urlStreamHandler);  
  48.             urlClassLoader = new URLClassLoader(urls);  
  49.         } catch (MalformedURLException e) {  
  50.             e.printStackTrace();  
  51.         } catch (IOException e) {  
  52.             e.printStackTrace();  
  53.         }  
  54.           
  55.         Class myClass = null;  
  56.           
  57.         try {  
  58.             /** 
  59.              * 加载Http请求的servlet 
  60.              */  
  61.             myClass=urlClassLoader.loadClass(servletName);  
  62.         } catch (ClassNotFoundException e) {  
  63.             e.printStackTrace();  
  64.         }  
  65.           
  66.         Servlet servlet=null;  
  67.           
  68.         try {  
  69.             /** 
  70.              * servlet实例化 
  71.              */  
  72.             servlet=(Servlet) myClass.newInstance();  
  73.             /** 
  74.              * 调用servlet的service()方法 
  75.              */  
  76.             servlet.service(request, response);  
  77.         } catch (InstantiationException e) {  
  78.             e.printStackTrace();  
  79.         } catch (IllegalAccessException e) {  
  80.             e.printStackTrace();  
  81.         } catch (ServletException e) {  
  82.             // TODO Auto-generated catch block  
  83.             e.printStackTrace();  
  84.         } catch (IOException e) {  
  85.             // TODO Auto-generated catch block  
  86.             e.printStackTrace();  
  87.         }  
  88.           
  89.     }  
  90.   
  91. }  
================分割线================
[java]  view plain  copy
  1. import java.io.File;  
  2.   
  3. public class Constants {  
  4.     /** 
  5.      * 设置服务器根目录,里面存放各种资源 
  6.      * 注意:“webroot”后面如果有分隔符则表示“webroot”是一个目录,下面还有子文件,如果后面没有分隔符则表示“webroot”是一个具体的文件 
  7.      */  
  8.     public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot"+File.separator;  
  9. }  
================分割线================
[java]  view plain  copy
  1. import java.io.IOException;  
  2. import java.io.PrintWriter;  
  3.   
  4. import javax.servlet.Servlet;  
  5. import javax.servlet.ServletConfig;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.ServletRequest;  
  8. import javax.servlet.ServletResponse;  
  9.   
  10.   
  11. public class MyFirstServlet implements Servlet {  
  12.   
  13.     @Override  
  14.     public void destroy() {  
  15.         // TODO Auto-generated method stub  
  16.           
  17.     }  
  18.   
  19.     @Override  
  20.     public ServletConfig getServletConfig() {  
  21.         // TODO Auto-generated method stub  
  22.         return null;  
  23.     }  
  24.   
  25.     @Override  
  26.     public String getServletInfo() {  
  27.         // TODO Auto-generated method stub  
  28.         return null;  
  29.     }  
  30.   
  31.     @Override  
  32.     public void init(ServletConfig config) throws ServletException {  
  33.         // TODO Auto-generated method stub  
  34.           
  35.     }  
  36.   
  37.     @Override  
  38.     public void service(ServletRequest req, ServletResponse res)  
  39.             throws ServletException, IOException {  
  40.         PrintWriter printWriter=res.getWriter();  
  41.         System.out.println("servlet开始执行");  
  42.         printWriter.println("Hello,Servlet");  
  43.     }  
  44.   
  45. }  
在浏览器中输入http://127.0.0.1:8888/123.html,结果如下:

在浏览器中输入http://127.0.0.1:8888/servlet/MyFirstServlet,结果如下:


注意:编译后的MyFirstServlet.class文件必须放在WebRoot目录下。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
疫情居家办公系统管理系统按照操作主体分为管理员和用户。管理员的功能包括办公设备管理、部门信息管理、字典管理、公告信息管理、请假信息管理、签到信息管理、留言管理、外出报备管理、薪资管理、用户管理、公司资料管理、管理员管理。用户的功能等。该系统采用了MySQL数据库,Java语言,Spring Boot框架等技术进行编程实现。 疫情居家办公系统管理系统可以提高疫情居家办公系统信息管理问题的解决效率,优化疫情居家办公系统信息处理流程,保证疫情居家办公系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理疫情居家办公系统信息,包括外出报备管理,培训管理,签到管理,薪资管理等,可以管理公告。 外出报备管理界面,管理员在外出报备管理界面中可以对界面中显示,可以对外出报备信息的外出报备状态进行查看,可以添加新的外出报备信息等。签到管理界面,管理员在签到管理界面中查看签到种类信息,签到描述信息,新增签到信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值