首页 > 技术文章 > Servlet基础知识

DQGonoes 2021-12-21 17:41 原文

1.Servlet是什么?

(1)运行在服务器端的java程序

(2)作用:

++ 1.处理接收客户端的请求
++ 2.处理请求后调用java程序中的代码,并给客户端做出响应

++ 响应:HTML代码段、JSON 机制:IO输出流,将服务端的数据输出到客户端

(1)HTML: 输出的就是HTML代码段

(2) 使用json引入:阿里 fast-json

<!-- Fastjoson JSON处理工具 -->
<dependency>   
    <groupId>com.alibaba</groupId>    
    <artifactId>fastjson</artifactId>    
    <version>1.2.78</version>
</dependency>

告诉客户端我是什么数据/客户端发送给服务端的数据类型: Content-type (mime类型)

(3)实时运行的容器(随时监听客户端发送的请求,随时准备给客户端发送响应)

2.了解两个JAVA WEB(J2EE)开发中常用的组件

(1)Maven

作用:

++管理项目包

++构建项目,打包项目

++管理项目之间代码的依赖

安装方法:

1.官网下载软件,地址:http://maven.apache.org/download.cgi

2.解压

3.配置环境变量”MAVEN_HOME”为maven解压的根目录路径

4.环境变量”path”添加,%MAVEN_HOME%\bin

5.测试maven配置是否成功,cmd>mvn - v ,有版本输出则安装配置完成

结构解析:

++ conf: 配置文件路径

(1)settings.xml : maven构建目录配置文件

       ```xml

E:\GjbSVN\maven仓库
```

<!-- 配置阿里云仓库 -->
<mirror>
            <id>nexus-aliyun</id>
            <mirrorOf>*,!jeecg,!jeecg-snapshots,!getui-nexus</mirrorOf>
            <name>Nexus aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
        </mirror>

(2)Tomcat

是一个轻量的服务器端WEB程序容器

作用

++ 在服务器端运行一个服务用于接收所有客户端的请求转发给Java容器代码(Servlet)

++ 可以部署多个java程序在服务端运行,且提供端口号和项目名进行访问

++ 可以配置请求相关的内容,如:https(SSL证书加密的请求)

++ 请求网路相关的策略和Java代码解耦

安装方法:

1.官网下载https://tomcat.apache.org/download-80.cgi

2.解压

3.运行-》 运行:bin> startup程序(sh文件:linux执行 bat:windows执行)

4.访问:在浏览器导航窗体中输入: http://tomcat所在的服务器ip地址或域名: Tomcat的端口号 / 项目名

  1. 停止:运行:bin> shutdown程序(sh文件:linux执行 bat:windows执行)

    ++ 在打开的tomcat窗口 按 ctrl+C停止

结构解析:

++bin:Tomcat的执行文件目录(启动 startup、停止 shutdown)

++conf:Tomcat配置文件路径

(1)server.xml : 配置容器服务配置项(Tomcat端口、Https配置、项目路径配置...)

  **(2) web.xml  :   Tomcat启动项目配置文件(不要修改,启动的是Tomcat内置的项目)**

++ webapps : Tomcat要部署的项目文件夹

3.Servlet项目的构建(IDEA)

(1)使用idea构建项目

1.新建项目-》 Java Enterprise -》

++ name: 项目名

++ location: 项目文件位置

++ Project Template:项目模板(选择Web Application)

++ Application server:服务运行容器(TomEE)

++ bulid system : Maven

++ Group: 根包结构 (公司域名反写)

++ Artfiact: 打包的项目名称

点击OK

2.选择依赖

++ 只选择Servlet就可以

点击OK

(2)项目的结构

  1. src>main>java: java源代码目录

  2. src>main>resource :资源文件夹(配置文件)

  3. src>main>webapp: 包含项目的静态资源文件、web动态配置文件(Servlet运行配置)

    ++ WEB-INF》 web.xml : Servlet运行配置

    1. 和SRC目录同级的pom.xml : maven依赖配置文件

(3)IDEA 启动项目的方式

1.在idea下配置Tomcat的方式

注意:idea下选择服务容器选择 Tomcat Server

(1)右上角-》找到Tomcat窗体点击-》 Edit Configuration.. 打开窗体

(2)修改URL,点击Deployment-》Application context : 修改路径

2.启动点击Tomcat窗体右侧的运行按钮或者debug按钮

3.停止点击红色方块停止

2.IDEA中maven的配置方式

4.Servlet第一个Demo

(1)编写Servlet源文件

public class ServletDemo1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //设置mime类型为html
        resp.setContentType("text/html;charset=UTF-8");

        //准备返回给客户端的html代码段
        String str = "<span style='color:red;'>你好客户端,我是服务器!</span>";

        //从响应对象获取一个输出流
        PrintWriter writer = resp.getWriter();

        //输出客户端
        writer.write(str);

        //输出、关闭流
        writer.flush();
        writer.close();

    }
}

(2)配置Servlet

在webapp文件夹下得web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- 注册Servlet类到容器中 -->
    <servlet>
        <!-- 给Servlet取个名字 -->
        <servlet-name>ServletDemo1</servlet-name>
        <!-- 注册的servlet类的全包名路径位置 -->
        <servlet-class>com.huawei.javaservletdemo.ServletDemo1</servlet-class>
    </servlet>

    <!-- 配置请求URL路径与Servlet的映射关系 -->
    <servlet-mapping>
        <!-- 要给哪个名字的Servlet配置映射 -->
        <servlet-name>ServletDemo1</servlet-name>
        <!-- url路径与Servlet映射 -->
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>

(3)编译运行Tomcat

直接运行即可

(4)访问Servlet

如:在浏览器地址栏中输入:

http://localhost:8080/JavaServletDemo/login

其中:

++localhost : Tomcat运行的计算机IP地址

++ 8080 : Tomcat的端口号

++ /JavaServletDemo : 项目名称

++ /login : Servlet 的映射url-pattern

5.Servlet的生命周期方法

5.1 Servlet初始化-init()方法

定义在Servlet接口中,在GenericServlet类中重写了这个方法,提供了一个重载的init方法

public void init(ServletConfig config) throws ServletException

在HttpServlet类中就没有init方法了,我们需要重写

/**
     * Servlet初始化方法
     * @throws ServletException
     */
    @Override
    public void init() throws ServletException {
        System.out.println("Servlet初始化");
    }

作用:

当请求访问Servlet容器时,如果没有创建Servlet实例,就会调用init方法,如果有实例则不会调用(Servlet单例模式)

5.2 请求响应处理-service()方法

作用:处理请求和响应

注意:如果是继承了HttpServlet的Servlet实例,不要重写service方法,因为在HttpServlet类内部已经重写了该方法

HttpServlet中重写的方法:

public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException
    {
        HttpServletRequest  request;
        HttpServletResponse response;
        
        if (!(req instanceof HttpServletRequest &&
                res instanceof HttpServletResponse)) {
            throw new ServletException("non-HTTP request or response");
        }

        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;

        service(request, response);  //  调用了自定义的重载的service方法
    }

HttpServlet中重载的方法:

protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();  //获取请求的类型进行判断

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.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 {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

5.3 Servlet销毁-destroy() 方法

作用:

当Servlet容器停止或者Servlet容器觉得你的Servlet实例应该销毁就会被调用,自动化过程

@Override
    public void destroy() {
        System.out.println("销毁!");
    }

6.HTTP请求、响应

(1)请求组成

请求行/状态行
头信息
实体

请求行:
GET /sample.jsp HTTP/1.1

请求头:
Accept:image/gif,image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/4.0(compatible;MSIE5.01;Windows NT 5.0)
Accept-Encodin:gzip,deflate

参数:
username=chaidapeng&password=123456

(2)请求状态码

200 -》 请求成功

404 -》 请求资源不存在

403 -》请求方式不对

500 -》 后端代码异常

501 -》后端不支持RESTful接口

7.Servlet封装的请求和响应对象

1.请求对象ServletRequest常用方法

(1)getParameter(String parameterName)查询指定请求参数值

http://localhost:8080/JavaServletDemo/login?name=%E8%80%81%E6%9D%8E&age=18

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String name = req.getParameter("name");

        String age = req.getParameter("age");

        System.out.println("参数name="+name);

        System.out.println("参数age="+age);


    }

(2)getParameterMap() 获取请求参数的map集合

Map<String, String[]> parameterMap = req.getParameterMap();

        Set<String> strings = parameterMap.keySet();

        for(String key:strings){

            String[] strings1 = parameterMap.get(key);

            System.out.println("key:"+key+"    value:"+ Arrays.toString(strings1));

        }

(3)获取客户端请求的mime类型

String contentType = req.getContentType();

        System.out.println(contentType);

(4)获取客户端的输入流进行读取getInputStream

ServletInputStream inputStream = req.getInputStream();

            int available = inputStream.available();

            byte [] arr = new byte[available];
            System.out.println(available);
            inputStream.read(arr);

            System.out.println(new String(arr));

(5)获取客户端的ip、主机名、端口

//客户端IP地址
        String remoteAddr = req.getRemoteAddr();
        //返回客户端主机名
        String remoteHost = req.getRemoteHost();
        //客户端端口号
        int remotePort = req.getRemotePort();

        System.out.println(remoteAddr+" "+remoteHost+" "+remotePort);

(6)获取请求头中得参数

请求头参数如下:

请求头:
Accept:image/gif,image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/4.0(compatible;MSIE5.01;Windows NT 5.0)
Accept-Encodin:gzip,deflate

String host = req.getHeader("Host");

        System.out.println(host);

(7)在请求对象中添加或取得参数值(自定义)

//给请求对象添加参数
        req.setAttribute("keyName","123");
        //取得请求对象携带的参数
        Object keyName = req.getAttribute("keyName");

2.响应对象ServletResponse

(1)获取输出流,向客户端输出数据getOutputStream

ServletOutputStream outputStream = resp.getOutputStream();

        outputStream.print("123");
        outputStream.println("789");
        outputStream.print("456");
        outputStream.println("<h1>4444</h1>");//如果不设置contentType则按照字符串输出

        outputStream.flush();

        outputStream.close();

(2)返回可以向客户端发送字符数据的PrintWriter对象

同上,输出htmldemo 在单元4

(3)设置请求和响应的字符编码集

//设置请求、响应内容的字符集
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

(4)设置响应的mime类型

//设置请求、响应内容的字符集
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

比如:输出一个json字符串

 //设置请求、响应内容的字符集
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        PrintWriter writer = resp.getWriter();

        //设置响应的mime类型   json类型
        resp.setContentType("application/json;charset=UTF-8");

        User u1 = new User("高靖博",28);

        //json字符串转换为对象
        String u2 = "{name:'王丘',age:18}";

        User parse = JSONObject.parseObject(u2,User.class);

        System.out.println(parse.name+" "+parse.age);

        //java对象转为json字符串
        String s = JSON.toJSONString(u1);

        System.out.println(s);
		
		writer.print(s);

        writer.flush();

        writer.close();

8.ServletConfig 配置对象

作用:

++ 在Servlet实例的时候添加一些参数,然后通过servletConfig对象调用getInitParameter方法取得初始化参数

(1)配置初始化参数

在web.xml中对应的servlet标签下配置init-param标签

<!-- 注册Servlet类到容器中 -->
    <servlet>
        <!-- 给Servlet取个名字 -->
        <servlet-name>ServletDemo1</servlet-name>
        <!-- 注册的servlet类的全包名路径位置 -->
        <servlet-class>com.huawei.javaservletdemo.ServletDemo1</servlet-class>
        <!-- servletConfig初始化配置参数 -->
        <init-param>
            <param-name>userName</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>pwd</param-name>
            <param-value>123456</param-value>
        </init-param>
    </servlet>

(2)获取servletConfig对象,获取初始化参数值

方法一:重写init方法,参数写上ServletConfig对象参数

/**
     * 重写servlet中的init方法,且要带上参数(ServletConfig config)
     * 初始化方法
     * @param config  初始化时实例ServletConfig参数对象
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;

        System.out.println("初始化");

        //获取servlet初始化参数
        String userName = this.config.getInitParameter("userName");

        System.out.println("userName:"+userName);

    }

方法二:通过Servlet当前对象调用getServletConfig()方法获取对象

ServletConfig servletConfig = this.getServletConfig();

        System.out.println(servletConfig.getInitParameter("userName"));

(3)获取所有的初始化参数名称

//获取初始化参数名称的枚举对象
        Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();

        //迭代器遍历枚举值
        String s1 = initParameterNames.nextElement();

9.ServletContext 对象 Servlet上下文对象

获取方式主要使用两种:

//1.通过ServletConfig对象获取
ServletContext servletContext = servletConfig.getServletContext();

//2.通过当前Servlet对象调用getServletContext获取
ServletContext servletContext1 = this.getServletContext();

(1) 给上下文对象添加参数能够在多个Servlet实例之间共享

如:在Servlet1中给ServletContext对象设置参数

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ServletConfig servletConfig = this.getServletConfig();

        System.out.println(servletConfig.getInitParameter("userName"));

        //1.通过ServletConfig对象获取
        ServletContext servletContext = servletConfig.getServletContext();

        //2.通过当前Servlet对象调用getServletContext获取
        ServletContext servletContext1 = this.getServletContext();

        //设置参数
        servletContext.setAttribute("qqNumber","123456789");


    }

在Servlet2中获取设置的参数

System.out.println("Servlet2被调用");

        ServletContext servletContext = this.getServletContext();

        System.out.println("在Servlet2中获取:"+servletContext.getAttribute("qqNumber"));

10.Http请求响应

1.请求类型

(1)GET请求:

如:http://192.168.1.100:8080?name=高靖博&age=18

出现的情况:

++ 浏览器地址框请求是GET

++ 请求查询指定服务器资源是GET(获取css、js、页面、图片、视频..)

特点:

++ 请求参数是跟在请求url后面的

++ GET请求没有请求体

(2)POST请求

如:表单提交 <form method="post"> 当表单提交时就是POST请求

出现的情况:

++ 需要加密请求参数

++ 请求参数很多很长

特点:

++ 请求参数是在请求体重

++ 请求参数长度不限制

11.HttpServlet提供的请求(HttpServletRequest)和响应对象(HttpServletResponse)

httpservlet提供的请求和响应对象分别都继承了servlet的请求和响应对象

1.HttpServletRequest 请求对象

(1)获取客户端的Cookie

/**
         * Cookie客户端会话存储技术
         */
        //服务端获取Cookie的方法
        Cookie[] cookies = req.getCookies();
        if(cookies!=null){
            for(int i=0;i< cookies.length;i++){
                Cookie cookie = cookies[i];
                String name = cookie.getName();
                String value = cookie.getValue();
                System.out.println("name:"+name);
                System.out.println("value"+value);
            }
        }

(2)获取客户端请求的URI和URL

//获取客户端请求的URI
        String requestURI = req.getRequestURI();
//获取客户端请求的URL
        StringBuffer requestURL = req.getRequestURL();
        // /JavaServletDemo/login
        System.out.println("requestURI"+requestURI);
        // http://localhost:8080/JavaServletDemo/login
        System.out.println("requestURL"+requestURL);

(3) 请求的查询参数字符串

 //如请求: http://localhost:8080/JavaServletDemo/login?name=hhh&age=12
        String queryString = req.getQueryString();
        //name=hhh&age=12
        System.out.println(queryString);

(4) 获取请求的类型

String method = req.getMethod();
        // GET
        System.out.println(method);

2.HttpServletResponse 响应对象

(1) 给客户端添加一个Cookie

//服务器端可以创建一个cookie返回给客户端
        Cookie c = new Cookie("token","123456789");
        c.setMaxAge(9999);//设置Cookie过期时间,单位秒
        resp.addCookie(c);

(2) 获取响应头信息和设置响应头信息

//覆盖设置
resp.setHeader(“属性名”,"属性值");
//追加
resp.addHeader("属性名","属性值");
注意:只有响应对象可以取值和赋值,请求对象只能取得请求头的值,不能设置

推荐阅读