Servlet实践操作

Servlet运行原理

  1. Tomcat 的代码内置了 main 方法,当我们启动 Tomcat 的时候,就是从 Tomcat 的 main 方法开始执行的

  2. 被 @WebServlet 注解修饰的类会在 Tomcat 启动的时候就被获取并集中管理

  3. Tomcat 通过反射这样的语法机制来创建被 @WebServlet 注解修饰的类的实例

  4. 这些实例被创建完之后,就会调用其中的 init 方法进行初始化

  5. 这些实例被销毁之前,就会调用其中的 destory 方法进行收尾工作

  6. Tomcat 内部也是通过 Socket API 进行网络通信

  7. Tomcat 为了能够同时处理多个 HTTP 请求,采取了多线程的方式实现,因此 Servlet 是运行在多线程环境下的

 Post请求测试

浏览器直接发送的是get请求,这里使用Postman进行接口测试

@WebServlet("/testDoPost")
public class TestDoPostServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("testPost success!");
    }
}

 Response重定向到其他页面

public class RedirectServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("https://blog.csdn.net/weixin_44610169");
    }
}

post请求体body中携带信息获取

@WebServlet("/postParameter")
public class PostParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        resp.getWriter().write("username = " + username + " password = " + password);
    }
}

body内容格式为JSON数据获取

JSON格式的数据需要解析,Java内置库没有对JSON的解析,所以这里导入第三方数据库jackson,使用jackson解析读取请求中body内的数据.

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.17.1</version>
        </dependency>

 

//定义一个JavaBean类
class UserInfo{
    public String username;
    public String password;
}
//读取请求中所有body
    public String readBody(HttpServletRequest req) throws IOException {
        //获取请求体长度
        int contentLength = req.getContentLength();
        //获取请求体内容
        byte[] bytes = new byte[contentLength];
        //读取请求体内容
        ServletInputStream inputStream = req.getInputStream();
        //将请求体内容读取到bytes中
        inputStream.read(bytes);
        //将bytes转换为字符串返回
        return new String(bytes, StandardCharsets.UTF_8);
    }
@WebServlet("/jsonParameter")
public class JsonParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        //读取请求体内容
        String body = readBody(req);
        //将请求体内容转换为JavaBean对象
        UserInfo userInfo = new ObjectMapper().readValue(body, UserInfo.class);
        //输出解析结果
        resp.getWriter().write("username: " + userInfo.username);
        resp.getWriter().write("password: " + userInfo.password);
    }
}

 Cookie

  • Cookie 是什么?

Cookie 是浏览器提供的在客户端存储数据的一种机制(由于浏览器禁止了网页中的代码直接访问本地磁盘的文件,因此想要在网页中实现持久化存储,就可以通过 Cookie 这样的机制)

  • Cookie 里面存什么?

Cookie 存储的数据都是程序员自定义的,存储的数据是一个字符串,是键值对结构的,键值对之间使用 ; 分割,键和值之间使用 = 分割

  • Cookie 从哪里来?

服务器返回响应的时候,可以把要在客户端保存的数据以 Set-Cookie 这个 header 的方式返回给浏览器

  • Cookie 到哪里去?

客户端下次访问服务器的时候,就会把之前保存好的 Cookie 再发送给服务器

  • Cookie 的典型应用场景:

可以使用 Cookie 来保存用户的登录信息。比如我们登录过某个网站后,下次登录时就不需要重新输入用户和密码了

  • Cookie 的缺陷:

每次请求都要把该域名下所有的 Cookie 通过 HTTP 请求传给服务器,因此 Cookie 的存储容量是有限的。

Session

在计算机中,尤其是在网络应用中,Session 称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中。注意会话状态仅在支持 Cookie 的浏览器中保留。

session的本质

  • 会话的本质就是一个哈希表,其中存储了一些键值对结构,key 叫做 sessionId,是一个不随机的、不重复的、唯一的字符串,value 就是要保存的身份信息,通过 HttpSession 对象来保存。key 和 value 都是 Servlet 自动创建的。

  • 每个用户登录都会生成一个会话,服务器会以哈希表的方式将这些会话管理起来

  • 一个会话的详细数据通过一个 HttpSession 对象来存储,并且 HttpSession 对象中存储的数据也是键值对结构,key 和 value 都是程序员自定义的

  • 当用户成功登录之后,服务器在 Session 中会生成一个新的记录,并把 sessionId 返回给客户端(例如 HTTP 响应中可以通过 Set-Cookie 字段返回,其中 Cookie 的 key 为 “JSESSION”,value 为服务器生成的 sessionId 的具体的值)

  • 然后客户端只需要保存这个 sessionId ,当后续再给服务器发送请求时,请求中就会带上 sessionId(例如 HTTP 请求中会带上 Cookie 字段用于传递 Session)

  • 服务器收到请求后,就会根据请求中的 sessionId 在 Session 中查询对应用户的身份信息,在进行后续操作

 Servlet实现登录测试

前端页面login.html使用form表单发送数据,servlet接收后进行操作

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <form action="/servlet_test/login1" method="post">
        <input type="text" placeholder="用户名" name="username"/>
        <input type="password" placeholder="密码" name="password"/>
        <input type="submit" value="登录">
    </form>

</body>
</html>
@WebServlet("/login1")
public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        if (username == null || username.isEmpty() || password == null || password.isEmpty()){
            resp.getWriter().write("<h3>用户名或密码不能为空</h3>");
            return;
        }
        if (!username.equals("root") && !password.equals("root")){
            resp.getWriter().write("<h3>用户名或密码错误</h3>");
            return;
        }
        if (username.equals("root") && password.equals("root")){
            // 登录成功后创建session
            HttpSession session = req.getSession(true);
            session.setAttribute("visitCount", 0);
            // 登录成功后跳转页面
            resp.sendRedirect("index");
        }

    }
}
@WebServlet("/index")
public class LoginSuccessServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        HttpSession session = req.getSession(false);
        if(session == null){
            // 如果为空重定向到登录页面
            resp.sendRedirect(req.getContextPath() + "/login.html");
            return;
        }
        // 登录成功后获取session中的数据
        Integer visitCount = (Integer) session.getAttribute("visitCount");
        visitCount += 1;
        session.setAttribute("visitCount", visitCount);
        resp.getWriter().write("登录成功,欢迎回来!您已经登录" + visitCount + "次!");
    }
}

文件上传

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
<!--通过 form 表单构造上传文件,要加上一个 enctype 字段,
    它表示 body 中的数据格式,它的默认值为:x-www-form-urlencoded,
    这里要修改成:multipart/form-data,它是上传文件或者图片的数据格式-->
  <form action="/servlet_test/uploadFile" method="post" enctype="multipart/form-data">>
    <input type="file" name="file1">
    <input type="submit" value="上传">
  </form>
</body>
</html>
@MultipartConfig
@WebServlet("/uploadFile")
public class uploadFileServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        Part file1 = req.getPart("file1");
        String fileName = file1.getSubmittedFileName();
        String contentType = file1.getContentType();
        long size = file1.getSize();
        System.out.println("文件名:" + fileName + ",文件类型:" + contentType + ",文件大小:" + size + "字节");
        file1.write("C:\\Users\\86152\\Desktop\\" + fileName);

        resp.getWriter().write("文件上传成功");
    }
}
传文件操作还需要给 Servlet 加上一个 @MultipartConfig 注解,否则服务器代码无法使用 getPart() 方法

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OtnIOs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值