menu ChaYedan
Tomcat相关
240 浏览 | 2020-04-19 | 阅读时间: 约 8 分钟 | 分类: Java | 标签: Java
请注意,本文编写于 893 天前,最后修改于 779 天前,其中某些信息可能已经过时。

善用页面搜索,h6标题不能生成目录

Tomcat

Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用

户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。

支持Servlet和JSP 规范,且最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。

安装

到官网下载即可

Tomcat目录结构


bin:脚本目录

启动脚本:startup.bat

停止脚本:shutdown.bat

conf:配置文件目录 (config /configuration)

核心配置文件:server.xml

用户权限配置文件:tomcat-users.xml

所有web项目默认配置文件:web.xml

lib:依赖库,tomcat和web项目中需要使用的jar包

logs:日志文件.

localhost_access_log..txttomcat记录用户访问信息,星表示时间。

例如:localhost_access_log.2018-07-07.txt

temp:临时文件目录,文件夹内内容可以任意删除。

webapps:默认情况下发布WEB项目所存放的目录。

work:tomcat处理JSP的工作目录。

配置和发布

创建模块

部署模块

进入设置

进入Deployment
在Application context那里配置路由

点右边的小铅笔,进入发布配置

改变输出目录到tomacat的webapps下面。最好自己在后面加个路径,因为以后可能是多个模块,每个模块单独放一个文件夹

另外需要注意的是,导包后,打开project structure->problem->fix修复,lib与web项目关联
如果不关联,可能只能在当前开发时可用,但是项目发布是失败

Servlet类

Servlet 运行在服务端的Java小程序,是sun公司提供一套规范,用来处理客户端请求、响应给浏览器的动态资源

Servlet是JavaWeb三大组件之一(Servlet、Filter、Listener),且最重要。

编写步骤

继承Servlet接口

  1. 定义类, 实现 Servlet接口
  2. 重写 service方法 , 当浏览器访问此类, 会自动执行 service 方法。
  3. 编写 web.xml 配置文件 . 在文件配置我们 HelloServlet 的信息

配置方式

xml:

servlet 类信息 <Servlet>

servlet 路径信息 <Servlet-mapping>

<!-- 表示 Servlet 类 -->
            <servlet>
                <!-- 表示 servlet类的名字 , 格式任意起名 ,建议见名知意  -->
                <servlet-name>hello</servlet-name>
                <!-- 表示 servlet类的  路径 , 全类名 -->
                <servlet-class>hm01_hello.HelloServlet</servlet-class>
            </servlet>
            <!-- 表示 Servlet 类 配置的路径 , 用于浏览器访问-->
            <servlet-mapping>
                <!-- 表示 servlet类的名字 , 与前面Servlet标签中 name 一致  -->
                <servlet-name>hello</servlet-name>
                <!-- 表示 servlet类 在浏览器中虚拟路径 -->
                <url-pattern>/h</url-pattern>
            </servlet-mapping>

注解:

Servlet3.0新增了一些注解,用来简化的javaweb代码开发

//name = "HelloServlet":servlet名称,相当于web.xml中的<servlet-name>
//urlPatterns = "/hello":servlet的访问路径,相当于<url-pattern>
@WebServlet(name = "HelloServlet",urlPatterns = "/hello")

可以直接写urlPatterns

相关方法
servletRequest

这个对象在service的参数列表中

所有的提交的数据,都以键值对保存在里面。用key可以拿到里面的数据,返回的是字符串形式

servletRequest.getParameter("key")

servletResponse

回写数据 , 打印回在浏览器上 。

servletResponse.getWriter().print();

print()不定,可以调用其他方法

继承HttpServlet接口

doGet()方法用于处理get请求。

doPost()方法用于处理post请求。

HttpServletRequest相关方法
获取值的方法

getParameter(String s):返回一个字符串,值是键为s的值

getParameterValues(String s):返回一个字符串数组

getParameterMap():保存所有提交参数。表单中的name的值为key, value 为String[]的值

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

        // 遍历数组
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();


        // 通过键值对 获取key 和value
        for (Map.Entry<String, String[]> entry : entries) {

            String key = entry.getKey();
            String[] value = entry.getValue();

            System.out.println(key +" -- " + Arrays.toString(value));
常见请求头

获取请求行中信息的相关方法


调用方法后的结果

获取请求头信息的相关方法

示例代码

public class Req3Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         // 解析请求头
        String host = request.getHeader("host");
        System.out.println(host);

        // 获取所有的头的键   --  返回枚举类型 .
        Enumeration<String> names = request.getHeaderNames();

        //  枚举类型的遍历   - 枚举 就相当于你学的迭代器 .

        while (names.hasMoreElements()) {    // hasMoreElements  -->  hasNext
            String s = names.nextElement();  // nextElement      -->  next
            System.out.println(s);

            // 获取 值
            String value = request.getHeader(s);
            System.out.println(s +" -- " + value);
        }
    }
}
获取请求参数

在实际开发中,经常需要获取用户提交的表单数据,例如,用户名、密码、电子邮件等,为了方便获取表单中的请求参数,在HttpServletRequest接口中,定义了一系列获取请求参数的方法

表中,列出了HttpServletRequest获取请求参数的一系列方法。其中,getParameter()方法用于获取某个指定的参数,而getParameterValues()方法用于获取多个同名的参数。

getParameterMap()方法配合BeanUtils使用,将发送的数据用对象保存
Request对象保存数据

Request对象不仅可以获取一系列数据,还可以通过属性传递数据。在ServletRequest接口中,定义了一系列操作
属性的方法,具体如下:
> 只有属于同一个请求中的数据才可以通过ServletRequest对象传递数据

RequestDispatcher对象(重要)

RequestDispatcher接口

当一个Web资源收到客户端的请求后,如果希望服务器通知另外一个资源去处理请求,这时,除了使sendRedirect()方法实现请求重定向外,还可以通过RequestDispatcher接口的实例对象来实现。在ServletRequest接口中定义了一个获取RequestDispatcher对象的方法

获取到RequestDispatcher对象后,最重要的工作就是通知其它Web资源处理当前的Servlet请求,为此,在RequestDispatcher接口中,定义了两个相关方法

列举的两个方法中,forward()方法可以实现请求转发,include()方法可以实现请求包含(就是将当前页面和被包含页面的输出结果,合并一起响应给浏览器)

跟重定向不一样的是,重定向是游览器多次请求。最后的地址栏会变。但请求转发游览器只向服务器请求一次,请求在服务器内多次转发,最后的地址栏地址不会变。

请求转发可以携带数据,重定向只能用Servlet来传递数据

示例代码

AServlet

@WebServlet(urlPatterns = "/a")
public class AServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    /*
      请求 转发:
      getRequestDispatcher : 获取转发器 , 参数地址 , 不需要添加 项目的名称 , 直接填写 资源路径即可.

     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //  使用 request 保存 数据  .
        request.setAttribute("name" , "tom");


        // 转发 到  BServlet  中

        // 1. 获取转发器
        // 这里是同一个项目中(模块?),所以不用加项目名
        RequestDispatcher rd = request.getRequestDispatcher("/b");

        // 2. 发送 (走你)
        rd.forward(request ,response);


    }
}

BServlet

@WebServlet(urlPatterns = "/b")
public class BServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("BServlet.doGet");

        // 获取request 对象 保存数据
        Object name = request.getAttribute("name");

        // 回写到页面
        response.getWriter().println(name);

    }
}
中文乱码问题

Tomcat 8 以后get方式自动处理了,post方式没有解决。

由于HTML设置了浏览器在传递请求参数时,采用的编码方式是UTF-8,但在解码时采用的是默认的ISO8859-1,因此会导致乱码的出现。

解决:
HttpServletRequest接口中,提供了一个setCharacterEncoding()方法,该方法用于设置request对象的解码方式

HttpServletResponse也有类似的方法response.setContentType("text/html;charset=utf-8");

@WebServlet(urlPatterns = "/ch")
public class ChinaServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    /*
      获取请求中的中文数据.

     GET 方式请求: 自动处理 tomcat8特性.
     POST 方式 :  依然乱码 . 通过
     setCharacterEncoding 设置编码

     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取 参数前 ,设置请求对象中编码
        request.setCharacterEncoding("utf-8");
        // 设置 回写的编码
        response.setContentType("text/html;charset=utf-8");

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

        System.out.println(name);

        response.getWriter().println(name);
    }
}

HttpServletResponse

在Servlet API中,定义了一个HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息,由于HTTP响应消息分为状态行、响应消息头、消息体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码、响应消息头、响应消息体的方法。

发送状态码相关的方法

当Servlet向客户端回送响应消息时,需要在响应消息中设置状态码。

setStatus(int status):该方法用于设置HTTP响应消息的状态码,并生成响应状态行。由于响应状态行中的状态描述信息直接与状态码相关,而HTTP版本由服务器确定,因此,只要通过setStatus(int status)方法设置了状态码,即可实现状态行的发送。需要注意的是,正常情况下,Web服务器会默认产生一个状态码为200的状态行。

/*
     响应行 :  状态码: 200
              版本:HTTP/1.1

     响应头 :
                Content-Length    :12
                Date    :Sat, 25 May 2019 02:48:14 GMT

      响应体:  正文内容
               hello resp
=============================================================================

   setStatus(int i) : 可以用来设置状态码 , 通常 tomcat 去设置 ,我们几乎不会调用.
                      此状态码只是描述作用 , 无法真实反映代码实际状态.



     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 设置 响应行  --  状态码
        response.setStatus(500);  // 表示200  成功 , 500 表示 出现异常 .



        // 回写内容
        response.getWriter().print("hello resp");

    }
发送响应消息头相关的方法

当Servlet向客户端发送响应消息时,由于HTTP协议的响应头字段有很多种,为此,在HttpServletResponse接口中,定义了一系列设置HTTP响应头字段的方法。

  • addHeader(key, value) :添加头信息键值对, 键可以重复.
  • setHeader(key,value) : 设置头信息键值对, 键唯一的. 键重复时, 后面值覆盖前面的值.
/*

      添加头信息 : addHeader(key, value) , 添加头信息键值对,  键可以重复.


      设置头信息: setHeader(key,value) , 设置头信息键值对, 键唯一的. 键重复时, 后面值覆盖前面的值.

      =========================

      了解 : setIntHeader  setDateHeader ,几乎不会调用 ,因为 字符串类型可以替代.
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

            // 添加 头信息
//        response.addHeader("name" , "tom");
//        response.addHeader("name" , "tom");
//        response.addHeader("name" , "tom");


        // 设置头信息
        response.setHeader("name" , "tom");
        response.setHeader("name" , "tom");
        response.setHeader("name" , "tom");
        response.setHeader("name" , "tommy");
        response.setHeader("Date" , new Date().toString());
    }

其他方法:

响应头信息

应答头说明
Allow服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。
Date当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
Location表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。
Refresh表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。 注意Refresh的意义是"N秒之后刷新本页面或访问指定页面",而不是"每隔N秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。 注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。
Server服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。
Set-Cookie设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。
WWW-Authenticate客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。 注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。

中文乱码问题:因为没有设置解析为utf-8

在响应之前,调用setContentType("text/html;charset=utf-8"); 设置解析方式解决

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

     // 测试 自动跳转 :
     // 格式 : "时间(秒); URL=地址"
     response.setHeader("Refresh","5; URL=https://www.baidu.com");

     // 处理响应 中文  , 回写之前设置utf8编码
     response.setContentType("text/html;charset=utf-8");

     response.getWriter().println("5 秒 自动跳转到 baidu.co");
 }
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,快来留言吧!