美文网首页
一、JavaWeb学习笔记之 Servlet (一)

一、JavaWeb学习笔记之 Servlet (一)

作者: Martin_Depp | 来源:发表于2018-04-27 13:29 被阅读0次

    [TOC]

    Servlet

    用户在浏览器中输入一个网址并回车,浏览器会向服务器发送一个HTTP请求,服务器端接收并且处理改请求,然后向浏览器发送响应,浏览器接收响应,在将服务器端响应的内容显示出来,这种请求-响应模式就是典型的Web应用程序访问过程。在JavaWeb应用程序中,处理请求和响应的过程就是由Servlet程序来完成的。

    1. Servlet 概述

    JavaWeb应用程序中所有的请求-响应都是由Servlet来完成的。Servlet没有main方法,当用户访问服务器时,服务器通过调用Servlet的某些方法来完成整个的处理过程。

    1.1 Servlet 工作流程

    浏览器提交的请求是遵循HTTP协议的,提交的请求通过服务器(Tomcat)接收解析,并且封装成为HttpServletRequest类型的reqeust对象,所有的HTTP头数据都可以通过request的相应方法查询到。

    服务器(Tomcat)同时把输出流封装为HttpServletResponse类型的response对象,通过设置response属性,就可以控制输出的内容。服务器(Tomcat)把request和response作为参数,调用Servlet的相应方法,如doGet或者doPost方法。

    1.2 Servlet 接口

    Servlet 实现了javax.servlet.Servlet接口的类,Servlet接口规定了特定的方法来处理特定的请求,我们只需要实现Servlet的相关方法,用户访问Web应用程序的时候,服务器(Tomcat)会自动调用这些方法来完成业务处理。Servlet业务处理主要方法有一下两种:

    1. Get方法:表示查询信息,URL中可以附带少量的参数信息,但是URL的总长度不能超过255个字符,并且参数会显示在浏览器的地址栏中。
    2. Post方法:表示提交信息,一般用于调教大数据信息或者文件,提交的内容不受长度限制,并且不会显示在浏览器地址栏。

    1.3 实现 Servlet

    package com.servlet.demo;
    
    import java.io.IOException;
    
    import javax.servlet.Servlet;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class ServletDemo implements Servlet {
    
        private ServletConfig config;
    
        public void destroy() {
            System.out.println("执行destory()方法...");
        }
    
        public ServletConfig getServletConfig() {
            return this.config;
        }
    
        public String getServletInfo() {
            return this.config.getServletName();
        }
    
        public void init(ServletConfig config) throws ServletException {
            System.out.println("执行init()方法...");
            this.config = config;
        }
    
        public void service(ServletRequest request, ServletResponse response) 
                throws ServletException, IOException {
            System.out.println("执行Service()方法...");
        }
    }
    

    1.4 配置 Servlet

    在JavaWeb应用程序中,Web容器还必须知道浏览器怎么访问这个Servlet。所以我们要配置Servlet的类文件与访问方式。这个配置在Web应用程序的描述文件web.xml文件中。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
        id="WebApp_ID" version="3.1">
        <display-name>servlet</display-name>
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
        </welcome-file-list>
        
        <!-- 配置Servlet -->
        <servlet>
            <servlet-name>ServletDemo</servlet-name>
            <servlet-class>com.servlet.demo.ServletDemo</servlet-class>
             <!-- 将servlet随Tomcat启动时自动实例化 -->
            <load-on-startup>0</load-on-startup>
        </servlet>
        <!-- 映射Servlet -->
        <servlet-mapping>
            <servlet-name>ServletDemo</servlet-name>
            <url-pattern>/demo</url-pattern>
        </servlet-mapping>
    </web-app>
    

    1.4.1 配置 servlet 标签

    <servlet></servlet>分别为Servlet配置的开始与结束标签。中间部分为Servlet的配置信息,其中 <servlet-name><servlet-class> 属性是必须配置的。

    1. <servlet-name>:配置servlet名称,可以为任意字符串,但是保证该名称在web.xml文件中唯一,该名称供<servlet-mapping><filter>等使用;
    2. <servlet-class>:Servlet类所在包及类名;
    1. 在容器启动时实例化 Servlet

    <load-on-startup>:配置Servlet的加载模式,可选0和1,如果配置1,服务器会在启动时自动加载该Servlet;

    2. 设置Servlet初始化参数

    <init-param>:可以在servlet中配置初始化参数,包括一个参数名称和参数值,servlet可以通过其ServletConfig对象的getInitParam(String paramName)方法来获取初始化参数值;

    • <param-name>:配置初始化参数名称;
    • <param-value>:配置初始化参数值;

    1.4.2 配置 servlet-mapping标签

    1. <servlet-name>:配置指明采用该访问方式Servlet的名称,与<servlet>标签中的<servlet-name>须一致;
    2. <url-pattern>:配置该servlet的访问方式,该标签前面加上Web应用程序的路径,再加上服务器域名端口号信息就是访问该servlet的网址。
    image

    1.5 Servlet生命周期和生命周期方法

    Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

    • Servlet 通过调用 init () 方法进行初始化;
    • Servlet 调用 service() 方法来处理客户端的请求;
    • Servlet 通过调用 destroy() 方法终止(结束);

    以上的init()service()destory() 三个方法属于Servlet的生命周期方法。

    1. init():被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。
    2. service(): 执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端的请求,并把格式化的响应写回给客户端。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。
    3. destory():只会被调用一次,在 Servlet 生命周期结束时被调用。

    2. 通过继承 HttpServlet 编写 Servlet

    直接实现Servlet接口来编写Servlet不方便,需要实现的方法太多。javax.servlet.http.HttpServlet类实现了Servlet接口所有方法,通过继承HttpServlet编写Servlet,一般只需要覆盖doGet()和doPost()方法即可。

    package com.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.UnsupportedEncodingException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class FirstServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            this.log("执行 doGet 方法...");
            this.execute(request, response);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            this.log("执行 doPost 方法...");
            this.execute(request, response);
        }
        
        public long getLastModified(HttpServletRequest request) {
            this.log("执行 getLastModified 方法...");
            return -1;
        }
    
        private void execute(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            response.setCharacterEncoding("utf-8");
            request.setCharacterEncoding("utf-8");
            //获取访问该 Servlet 的 URI
            String requestURI = request.getRequestURI();
            // 获取访问 Servlet 的方式
            String method = request.getMethod();
            
            String param = request.getParameter("param");
            
            response.setContentType("text/html");
            
            PrintWriter out = response.getWriter();
            
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>First Servlet</title>");
            out.println("</head>");
            out.println("<body>");
            
            out.println("以<span color='red'> " + method +"</span> 方式访问该页面,取得的 param 参数为:" + param+"。");
            out.println("<br/>");
            
            out.println("<form action='"+ requestURI +"' method='get'>");
            out.println("<input type='text' name='param' value='param string'/>");
            out.println("<input type='submit' value='以 GET 方式查询页面'/>");
            out.println("</form>");
            
            out.println("<form action='"+ requestURI +"' method='post'>");
            out.println("<input type='text' name='param' value='param string'/>");
            out.println("<input type='submit' value='以 Post 方式提交到页面'/>");
            out.println("</form>");
            
            out.println("<script type='text/javascript'>");
            out.println("document.wirte('本页最后更新时间为 :' + document.lastModified);");
            out.println("</script>");
            
            out.println("</body>");
            out.println("</html>");
            
            out.flush();
            out.close();
        }
    
    }
    

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    id="WebApp_ID" version="3.1">
    <display-name>servlet</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    <!-- 配置FirstServlet -->
    <servlet>
        <servlet-name>FirstServlet</servlet-name>
        <servlet-class>com.servlet.FirstServlet</servlet-class>
    </servlet>
    <!-- 映射FirstServlet -->
    <servlet-mapping>
        <servlet-name>FirstServlet</servlet-name>
        <url-pattern>/first</url-pattern>
    </servlet-mapping>
    </web-app>
    

    3. 请求和响应

    客户端浏览器发送给一个请求,服务器接收并处理请求,最后向客户端浏览器发送响应,结束一次Web访问过程。

    3.1 获取 request 的变量

    客户端浏览器发出的请求被封装成为HttpServletRequest类型对象,所有的信息包括请求地址、请求参数、提交的数据、上传的文件,客户端的IP地址,甚至是客户操作系统都包含在HttpServletRequest类型的对象中。

    package com.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class RequestServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html");
            
            PrintWriter out = response.getWriter();
            
            // 获取 user-agent 请求头        
            String userAgent = request.getHeader("user-agent");
            
            String os = getOS(userAgent);
            String navigator = getNavigator(userAgent);
            
            out.println("你使用的操作系统是: "+ os +" 系统");
            out.println("<br/>");
            out.println("你使用的浏览器是: "+ navigator +" 浏览器");
            
            out.flush();
            out.close();
            
            
        }
        private static String getOS(String userAgent) {
            if (userAgent.indexOf("Ubuntu") > 0) {
                return "Ubuntu";
            }
            return "未知";
        }
        
        private static String getNavigator(String userAgent) {
            if (userAgent.indexOf("Firefox") > 0) {
                return "Mozllia Firefox";
            }
            return "未知";
        }
    }
    

    RequestServlet配置:

    <servlet>
        <servlet-name>RequestServlet</servlet-name>
        <servlet-class>com.servlet.request.RequestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestServlet</servlet-name>
        <url-pattern>/request</url-pattern>
    </servlet-mapping>
    

    3.2 使用 response 生成图片验证码

    package com.servlet.response;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.sun.image.codec.jpeg.JPEGCodec;
    import com.sun.image.codec.jpeg.JPEGImageEncoder;
    
    public class IdentityServlet extends HttpServlet {
    
        public static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
    
        // 获取随机数
        public static Random random = new Random();
    
        // 随机获取6位验证码
        public StringBuffer getIdentityCode() {
    
            // 创建缓存字符串
            StringBuffer buffer = new StringBuffer();
    
            for (int i = 0; i < 6; i++) {
                buffer.append(CHARS[random.nextInt(CHARS.length)]);
            }
    
            return buffer;
        }
    
        public static Color getRandomColor() {
            return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));
        }
    
        public static Color getReverseColor(Color c) {
            return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue());
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            response.setContentType("image/jpeg");
    
            String identityCode = getIdentityCode().toString();
            request.getSession(true).setAttribute("identityCode", identityCode);
            // 设置验证码图片的高度和宽度
            int width = 100;
            int height = 30;
    
            Color backColor = getRandomColor();
            Color frontColor = getReverseColor(backColor);
    
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    
            Graphics2D g = bi.createGraphics();
            g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));
    
            g.setColor(backColor);
            g.fillRect(0, 0, width, height);
    
            g.setColor(frontColor);
            g.drawString(identityCode, 18, 20);
    
            for (int i = 0; i < random.nextInt(100); i++) {
                g.drawRect(random.nextInt(width), random.nextInt(height), 1, 1);
            }
    
            ServletOutputStream out = response.getOutputStream();
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
    
            encoder.encode(bi);
            out.flush();
    
        }
    
    }
    
    

    IdentityServlet配置信息:

    <servlet>
        <servlet-name>identity</servlet-name>
        <servlet-class>com.servlet.response.IdentityServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>identity</servlet-name>
        <url-pattern>/identity</url-pattern>
    </servlet-mapping>
    

    4. 读取 web.xml 参数

    在JavaWeb开发中,源码上微小的变动就需要重新编译class文件,然后重新部署,会带来大量的工作。现在,可以将一些常亮信息存放于配置文件中。当程序需求发生变化,只需修改配置文件即可。web.xml提供了设置初始化参数的功能,可以将这些信息配置在web.xml文件中。

    4.1 初始化参数(init-param)

    web.xml配置servlet时,<servlet> 标签可以包含多个 <init-param> 来配置多个初始化参数。servlet中提供了如下的方法来操作来获取初始化参数的名称和值:

    1. String getInitParameter(String parameterName) : 获取指定初始化参数的值;
    2. Enumeration<String> getInitParameterNames() : 获取所有初始化参数名称;

    web.xml配置信息如下:

    <!-- 配置InitParamServlet -->
    <servlet>
        <servlet-name>InitParamServlet</servlet-name>
        <servlet-class>com.servlet.initParam.InitParamServlet</servlet-class>
        <!-- 配置初始化参数 -->
        <init-param>
            <param-name>admin</param-name>
            <param-value>martin0319</param-value>
        </init-param>
        <init-param>
            <param-name>adminPassword</param-name>
            <param-value>319517</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>InitParamServlet</servlet-name>
        <url-pattern>/param</url-pattern>
    </servlet-mapping>
    

    InitParamServlet

    package com.servlet.initParam;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Enumeration;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class InitParamServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
    
            response.setCharacterEncoding("utf-8");
            request.setCharacterEncoding("utf-8");
    
            response.setContentType("text/html");
    
            PrintWriter out = response.getWriter();
    
            String requestURI = request.getRequestURI();
    
            out.println("<!DOCTYPE HTML>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Test Init-Param</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<form action='" + requestURI + "' method='post'>");
            out.println("账号:<input type='text' name='loginName' />"
                    + "<br />"
                    + "密码:<input type='password' name='loginPassword' />"
                    + "<br />"
                    + "<input type='submit' value='Log In Now' />");
            out.println("</form>");
            out.println("</body>");
            out.println("</html>");
    
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
            
            response.setCharacterEncoding("utf-8");
            request.setCharacterEncoding("utf-8");
    
            response.setContentType("text/html");
    
            PrintWriter out = response.getWriter();
            
            //  获取由表达提交的数据      
            String username = request.getParameter("loginName");
            String password = request.getParameter("loginPassword");
            
            /*
             * 获取web.xml中配置参数
             *  1、获取ServletConfig对象
             *  2、获取所有初始化参数名称
             *  3、通过初始化参数名称获取初始化参数值
             */
            ServletConfig config = this.getServletConfig();
            
            String initName = config.getInitParameter("admin");
            String initPassword = config.getInitParameter("adminPassword");
            
            if (username.equalsIgnoreCase(initName) && password.equalsIgnoreCase(initPassword)) {
                out.println("欢迎登陆...");
            } else {
                out.println("用户名或密码错误...");
            }
    
        }
    
    }
    

    4.2 上下文参数(context-param)

    由于 init-param 是配置在<servlet>标签中的,只能由这个servlet类调用,不能被其他的servlet调用,不是全局参数。如果需要配置全局参数,需要用到上下文参数(文档参数),上下文参数使用<context-param>标签配置。

    上下文参数可以使用ServletConfig对象来获取。Servlet中通过getServletConfig().getServletContext()方法来获取一个ServletContext对象。

    1. String getInitParameter(String parameterName): 获取指定上下文参数的值;
    2. Enumeration<String> getInitParameterNames() : 获取所有上下文参数名称;

    ContextParamServlet配置信息:

    <context-param>
        <param-name>upload folder</param-name>
        <param-value>attachment</param-value>
    </context-param>
    <context-param>
        <param-name>allowed file type</param-name>
        <param-value>.jpg, .gif, .bmp</param-value>
    </context-param>
    <!-- 配置 ContextParamServlet -->
    <servlet>
        <servlet-name>ContextParamServlet</servlet-name>
        <servlet-class>com.contextParam.ContextParamServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ContextParamServlet</servlet-name>
        <url-pattern>/context</url-pattern>
    </servlet-mapping>
    

    ContextParamServlet类:

    package com.contextParam;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ContextParamServlet extends HttpServlet {
        
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            response.setCharacterEncoding("utf-8");
            request.setCharacterEncoding("utf-8");
            
            response.setContentType("text/html");
            
            PrintWriter out = response.getWriter();
            //  获取ServletContext对象
            ServletContext context = this.getServletConfig().getServletContext();
            //  获取上下文参数
            String uploadFolder = context.getInitParameter("upload folder");
            String allowFileType = context.getInitParameter("allowed file type");
            //  获取实际磁盘路径
            String realPath = context.getRealPath(uploadFolder);
            
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>读取上下文参数</title>");
            out.println("</head>");
            out.println("<body>");
            
            out.println("<table>");
            out.println("<tr>");
            out.println("<td>上传文件夹:</td>");
            out.println("<td>" + uploadFolder + "</td>");
            out.println("</tr>");
            
            out.println("<tr>");
            out.println("<td>实际磁盘路径:</td>");
            out.println("<td>" + realPath + "</td>");
            out.println("</tr>");
            
            out.println("<tr>");
            out.println("<td>允许上传类型:</td>");
            out.println("<td>" + allowFileType + "</td>");
            out.println("</tr>");
            out.println("</table>");
            
            out.println("</body>");
            out.println("</html>");
            
            out.flush();
            out.close();
            
        }
    
    }
    

    相关文章

      网友评论

          本文标题:一、JavaWeb学习笔记之 Servlet (一)

          本文链接:https://www.haomeiwen.com/subject/tlmblftx.html