Servlet技术

本文介绍了Servlet的基本概念和使用,包括依赖配置、Servlet接口实现、HttpServlet的使用,以及请求和响应的处理。通过示例展示了如何处理GET和POST请求,如何配置Servlet路径,以及请求转发和重定向的操作。同时,还讨论了处理中文乱码的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

servlet时访问动态资源的技术,由web服务器创建并调用。

快速入门

1.servlet依赖

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <!--编译和测试有效,运行环境无效。因为打包发布到的tomcat中也有servlet的jar包,运行会jar包冲突-->
            <scope>provided</scope>
        </dependency>

2.创建Servlet接口的是实现类

在main的java目录中创建类实现Servlet接口,并使用@WebServlet("/servletStart")注解配置该servlet的访问路径

package com.kdy.web;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

@WebServlet("servletStart")
//@WebServlet(urlPatterns = "/servletStart",loadOnStartup = 0)
/*loadOnStartup不加默认第一次访问该servlet执行时创建servlet对象并初始化
  loadOnStartup=负整数时同上
  loadOnStartup为0或正整数时,web服务器启动时创建servlet对象,数字越小,优先级越高
 */
public class ServletStart implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("servlet init hello!");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet service hello!");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

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

3、启动Tomcat

run maven->tomcat7 run或idea集成tomcat部署后启动

访问http://localhost:8080/MavenWeb3_war/servletStart即可

init()方法仅在创建servlet对象时调用一次,service()方法每次访问该servlet时调用。

destroy()方法:idea下方terminal中dir找到该模块名,cd 目标模块名进入目录后,mvn tomcat7:run可在终端运行,Ctrl+C模拟web服务器正常关闭,会调用一次destory()方法

HttpServlet

Servlet->GenericServlet(抽象实现类)->HttpServlet(对Http协议封装的实现类)

原理

根据不同的请求方式调用不同的doXxx()方法,类似下面我们自己写的MyHttpServlet,继承Servlet后在service()方法中进行根据请求方法分别处理。之后这个MyServlet就可拿来用了。

    @Override
    public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
        System.out.println("servlet service hello!");
        HttpServletRequest request = (HttpServletRequest)req;
        String method = request.getMethod();
        if("GET".equals(method)){
            //get方式的逻辑处理

            doGet(req,resp);
        }else if ("POST".equals(method)){
            //post方式的逻辑处理

            doPost(req,resp);
        }
    }
    private void doGet(ServletRequest req, ServletResponse resp) {
    }
    private void doPost(ServletRequest req, ServletResponse resp) {
    }

HttpServlet使用步骤

继承HttpServlet,重写doGet和doPost

@javax.servlet.annotation.WebServlet("/httpServlet")
public class WebServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do get ...");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do post ...");
    }
}

启动tomcat,浏览器访问该servlet路径,默认get方法走doGet方法。

写一个html表单:

<form action="/MavenWeb3/httpServlet" method="post">
    <!--action:由于和servlet在同一项目中,就直接项目根路径和servlet路径-->
    用户名:<input name="username" type="text"/>
    <input name="submit" type="submit" value="提交">
</form>

重新启动tomcat后,先访问http://localhost:8080/MavenWeb3/html/a.html表单页面,提交后以post请求方式访问http://localhost:8080/MavenWeb3/httpServlet,走doPost()方法。

Servlet访问路径urlPattern

匹配多个
@WebServlet(urlPatterns = {"/servletStart","/servletStart2"})
1.精确匹配
@WebServlet(urlPatterns = "/servlet/servletStart")
2.目录匹配
@WebServlet(urlPatterns = "/servlet/*")
3.扩展名匹配
@WebServlet(urlPatterns = "*.jsp")
4.任意匹配

"/"(其他urlPattern都对不上才会走这个)和"/*"(匹配任意)。不推荐使用。

XML文件方式配置Servlet路径和资源

不使用@WebServlet("")注解了,使用web.xml进行配置,在<web-app>里加上以下代码:

    <servlet>
        <servlet-name>webServlet</servlet-name>
        <servlet-class>com.kdy.web.WebServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>webServlet</servlet-name>
        <url-pattern>/httpServlet</url-pattern>
    </servlet-mapping>

Request与Response

Requst

RequestFacade(tomcat的实现类)->HttpServletRequest(http封装的请求接口)->ServletRequest

请求行、请求头

请求行:GET URI?参数  HTTP版本

请求头:A:B

@javax.servlet.annotation.WebServlet("/httpServlet")
public class WebServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = request.getSession();  //request也能getSession
        System.out.println("do get ...");
        String method = req.getMethod();//GET
        String contextPath = req.getContextPath();//虚拟目录(项目访问路径)  /MavenWeb3
        String requestURL = req.getRequestURL().toString();//统一资源定位符  http://localhost:8080/MavenWeb3/httpServlet
        String requestURI = req.getRequestURI();//统一资源标识符  /MavenWeb3/httpServlet
        String queryString = req.getQueryString();//请求参数  name=%E5%BC%A0%E4%B8%89&pwd=zhangsan
        //获取请求头
        String header1 = req.getHeader("Cookie");
        String header2 = req.getHeader("User-Agent");
        System.out.println(method+"\n"+contextPath+"\n"+requestURL+"\n"+requestURI+"\n"+queryString
        +"\n"+header1+"\n"+header2);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do post ...");
    }
}
请求体

使用html的form表单发送post请求

<form action="/MavenWeb3/httpServlet" method="post">
    <!--action:由于和servlet在同一项目中,就直接项目根路径和servlet路径-->
    用户名:<input name="username" type="text"/> <br/>
    密码:<input name="password" type="text"/>
    <input name="submit" type="submit" value="提交">
</form>

servlet中doPost()方法去接收:

@javax.servlet.annotation.WebServlet("/httpServlet")
public class WebServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do get ...");
        String method = req.getMethod();//GET
        String contextPath = req.getContextPath();//虚拟目录(项目访问路径)  /MavenWeb3
        String requestURL = req.getRequestURL().toString();//统一资源定位符  http://localhost:8080/MavenWeb3/httpServlet
        String requestURI = req.getRequestURI();//统一资源标识符  /MavenWeb3/httpServlet
        String queryString = req.getQueryString();//请求参数  name=%E5%BC%A0%E4%B8%89&pwd=zhangsan
        //获取请求头
        String header1 = req.getHeader("Cookie");
        String header2 = req.getHeader("User-Agent");
        System.out.println(method+"\n"+contextPath+"\n"+requestURL+"\n"+requestURI+"\n"+queryString
        +"\n"+header1+"\n"+header2);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        BufferedReader br = req.getReader();
        String line = br.readLine();
        System.out.println(line);//username=%E5%BC%A0%E4%B8%89&password=zhangsan&submit=%E6%8F%90%E4%BA%A4
    }
}

通用方式获取请求参数

由于GET请求参数获取为req.getQueryString();POST请求参数获取方式为req.getReader().readLine(),可以根据req.getMethod()进行判断GET还是POST。

Request提供了以下三种方法

Map<String ,String[]> getParameterMap():获取所有参数的Map集合

String [] getParammeterValues(String name):根据名称获取参数值(数组)

String getParameter(String name):根据名称获取参数值(单个值)

 post请求的表单
<form action="/MavenWeb3/httpServlet" method="post">
    <!--action:由于和servlet在同一项目中,就直接项目根路径和servlet路径-->
    用户名:<input name="name" type="text"/> <br/>
    密码:<input name="pwd" type="text"/>
    <input name="submit" type="submit" value="提交">
</form>
 servlet演示
@javax.servlet.annotation.WebServlet("/httpServlet")
public class WebServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do get ...");
        System.out.println("req.getParameterMap()---------------------------------");
        Map<String, String[]> map = req.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = map.entrySet();
        for (String key:map.keySet()) {
            System.out.print(key+":");
            for (String value:map.get(key)) {
                System.out.print(value+" ");
            }
            System.out.println();
        }
        System.out.println("req.getParameterValues()-----------------------------");
        String[] names = req.getParameterValues("name");
        String[] pwds = req.getParameterValues("pwd");
        for (String name:names) {
            System.out.println(name);
        }
        for (String pwd:pwds){
            System.out.println(pwd);
        }
        System.out.println("//req.getParameter()------------------------------------");
        String name= req.getParameter("name");//如果有多个叫name的参数,仅获取第一个
        String pwd = req.getParameter("pwd");//如果有多个叫pwd的参数,仅获取第一个
        System.out.println(name);
        System.out.println(pwd);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do post...");
        doGet(req,resp);
    }
}

 解决中文乱码问题

在idea中通过集成tomcat或tomcat插件方式启动上述项目就会出现中文乱码问题。可通过以下方式解决: 

POST请求参数中文乱码:设置req.setCharacterEncoding("UTF-8");

Tomcat7的GET请求参数中文乱码:name  = new String(name.getBytes(StandardCharacters.ISO_8859_1),StandardCharsets.UTF_8);

@javax.servlet.annotation.WebServlet("/httpServlet")
public class WebServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");//POST请求的参数的中文乱码解决方式
        //Tomcat7的GET请求参数的中文乱码解决方式为 name  = new String(name.getBytes(StandardCharacters.ISO_8859_1),StandardCharsets.UTF_8);

        System.out.println("do get ...");
        System.out.println("req.getParameterMap()---------------------------------");
        Map<String, String[]> map = req.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = map.entrySet();
        for (String key:map.keySet()) {
            System.out.print(key+":");
            for (String value:map.get(key)) {
                System.out.print(new String(value.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8)+" ");
            }
            System.out.println();
        }
        System.out.println("req.getParameterValues()-----------------------------");
        String[] names = req.getParameterValues("name");
        String[] pwds = req.getParameterValues("pwd");
        for (String name:names) {
            System.out.println(new String(name.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8));
        }
        for (String pwd:pwds){
            System.out.println(new String(pwd.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8));
        }
        System.out.println("//req.getParameter()------------------------------------");
        String name= req.getParameter("name");//如果有多个叫name的参数,仅获取第一个
        String pwd = req.getParameter("pwd");//如果有多个叫pwd的参数,仅获取第一个
        System.out.println(new String(name.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8));
        System.out.println(new String(pwd.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do post...");
        doGet(req,resp);
    }
}

注:如果上述servlet演示代码的项目maven clearn后maven package,将target中生成的该模块的文件或war放在tomcat的webapp目录下,重命名MavenWeb31,且conf/loggings.properties设置java.util.logging.ConsoleHandler.encoding = GBK,通过bin/startup.bat启动, 以http://localhost:8080/MavenWeb31/httpServlet?name=张三pwd=zhangsan&name=王五&pwd=wangwu访问,在tomcat的窗口日志展示中没有中文乱码。

Response

ResponseFacade(tomcat定义的实现类)->HttpServletResponse(http封装的请求对象)->ServlertResponse

响应行:协议版本 状态码 状态描述   void setStatus(int sc)设置响应状态码

响应头:key:value    void setHeader():设置响应头键值对

响应体:<html><head><body>  PrintWriter getWriter()获取字符输出流 ServletOutputStream getOutputStream()获取字节输出流

@WebServlet("/servletA")
public class ServletA extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //resp.setHeader("content-type","text/html");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.write("中文响应内容输出到页面上");
        writer.write("<h1>AAA</h1>");
    }

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

 注:tomcat7即使设置了上述utf-8依然会出现浏览器端的响应中文乱码问题。

@WebServlet("/servletA")
public class ServletA extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        FileInputStream fis = new FileInputStream("D://a.jpg");
        ServletOutputStream os = resp.getOutputStream();
        /*byte[] buff = new byte[1024];
        int len = 0;
        while ((len = fis.read(buff))!=-1){
            os.write(buff,0,len);
        }*/
        /* 上面代码替换为IOUtils.copy(fis,os);
        需添加依赖,使用import org.apache.commons.io.IOUtils;中的IOUtils.copy();
        * <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        */
        IOUtils.copy(fis,os);
        fis.close();
    }

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

 请求转发与重定向

请求转发forward

 服务器内部资源共享方式,通过request对象进行转发间的资源共享,同一个web服务器内部servlet转发,浏览器地址栏不发生变化。

request.setAttribute(String name ,Object o);       requestgetAttribute(String name);

request.removeAttribute(String name);

request.getRequestDispatcher("/servletB").forward(request,response);

创建两个servlet类演示如下:

@WebServlet("/servletA")
public class ServletA extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servletA...");
        req.setAttribute("attribute","attributeObjectString");
        req.getRequestDispatcher("/servletB").forward(req,resp);//服务器内部资源调用,不需要加虚拟目录
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
@WebServlet("/servletB")
public class servletB extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servletB...");
        Object attribute = req.getAttribute("attribute");
        System.out.println(attribute);
    }

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

启动tomcat后,访问:http://localhost:8080/MavenWeb3/servletA

结果,先访问了servletA又请求转发到servletB,且浏览器地址栏没有发生变化。

重定向redirect

可重定向到任意位置资源(web服务器内外部均可),不能用request共享数据,浏览器地址栏发生变化。

@WebServlet("/servletA")
public class ServletA extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servletA...");
        resp.setStatus(302);
        resp.setHeader("Location","/MavenWeb3/servletB");//uri:contextPath+servlet路径
        //resp.sendRedirect(req.getContextPath()+"/servletB");
        resp.sendRedirect("/MavenWeb3/servletB");//将资源发给浏览器,让浏览器去再次访问该路径,要加虚拟目录
        //同一服务内部资源可用uri,访问其他服务资源可用url
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
@WebServlet("/servletB")
public class servletB extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servletB...");
    }

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

启动tomcat,访问http://localhost:8080/MavenWeb3/servletA浏览器地址栏会跳到http://localhost:8080/MavenWeb3/servletBhttp://localhost:8080/MavenWeb3/servletA会跳到

路径问题

 服务端使用,不需要加虚拟目录contextPath,如请求转发。

浏览器端使用,需要加虚拟目录,如重定向发给浏览器由浏览器再发请求,再如超链接、form表单action路径都需加虚拟目录。

虚拟目录context:idea集成tomcat部署项目时的application context,或pom.xml中引入tomcat7插件配置的configuration里的path(不加默认为项目名)。可通过req.getContextPath()动态获取。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值