Servlet实现常用功能及其他方法

getParameter

获取body或url中指定的key/value值

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

getQueryString

获取请求的所有查询参数key,values1

String queryString=req.getQueryString();

from表单提交

前端通过from表单提交用户名和密码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="Demo4" method="post">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="submit" name="提交">
    </form>
</body>
</html>

后端通过req.getParameter获取用户名和密码

package Demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/Demo4")
public class Demo4 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        String username=req.getParameter("username");
        String password=req.getParameter("password");

        if(username.equals("user")&&password.equals("123")){
            resp.getWriter().write("登录成功!");
        }
        else{
            resp.getWriter().write("用户名或者密码错误!");
        }
    }
}

构造json格式

body中的json格式

使用jackson库解析json格式

版本随便一个都可以

拷贝复制

记得刷新

读取从客户端传来的json数据

class Student{
    public int classId;
    public int studentId;
}
//        使用jackSon库处理JSON格式
        ObjectMapper objectMapper=new ObjectMapper();
//        从请求获取body并且解析
//        使用readValue来把json字符串转成java对象
//        第一个对象是String或者InputStream
//        第二个参数是转换的结果对应的java类对象
        //把JSON字符串转成java对象
        Student s=objectMapper.readValue(req.getInputStream(),Student.class);
        resp.getWriter().write("classId="+s.classId+" studentId="+s.studentId);

服务器把json写入到客户端

        //传json时,要用这个类型
        resp.setContentType("application/json;charset=utf8");
        //要拿到写数据库操作的类
        BlogDao blogDao=new BlogDao();
        
        String jsonString=objectMapper.writeValueAsString(blogs);
        //响应
        resp.getWriter().write(jsonString);

客户端如何解析json格式?

后端设置了application/json格式,并且返回json格式,那么ajax会自动把body中的json格式转换成js对象

function getBlogs(){
            //构造ajax
            $.ajax({
                type:'get',
                url:'blog',
                success: function(body){
                    let container=document.querySelector('.container-right');
                    //后端返回的是json数据
                    //如果Content-Type是application/json,jquery ajax会把body转成js对象
                    for(let blog of body){
                        //构造最外层的div
                        let blogDiv=document.createElement('div');
                        blogDiv.className='blog';

                        //创建博客标题
                        let titleDiv=document.createElement('div');
                        titleDiv.className='title';
                        //把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
                        titleDiv.innerHTML=blog.title;
                        //把titleDiv添加在blogDiv内
                        blogDiv.appendChild(titleDiv);

页面自动刷新

设置头部信息Refresh属性 values为秒

package Demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/Demo5")
public class Demo5 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        resp.setHeader("Refresh","1");
        resp.getWriter().write("设置页面1秒后自动刷新");
    }
}

跳转页面

        //跳转页面
        resp.setStatus(302);//设置状态码 302
        resp.setHeader("Location","Demo1.html");

N秒后自动跳转页面

        //2秒后,跳转页面
        resp.getWriter().write("2秒后我将跳转页面");
        resp.setHeader("refresh", "2;Demo1.html");

自动下载

response.setHeader("content-disposition", "attachment;filename=3.jpg");

对话墙

基本逻辑

前端构造post方法,把数据构造成json格式,发送给后端,后端解析json格式,存储到数据库。

当页面刷新时,前端构造get方法,把数据构造成json格式,发送给后端,后端从数据库读取数据,再构造成json格式,发送给前端。

ajax会自动把body中的json格式解析成js对象,之后前端把数据显示到页面上。

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对话墙</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        .container {
            width: 800px;
            margin: 10px auto;
        }

        .container h2 {
            text-align: center;
            margin: 30px 0px;
        }

        .row {
            height: 50px;
            display: flex;
            justify-content: center;
            margin-top: 5px;
            line-height: 50px;
        }

        .row span {
            height: 50px;
            width: 100px;
            line-height: 50px;
        }

        .row input {
            height: 50px;
            width: 300px;
            line-height: 50px;
        }

        .row button {
            width: 400px;
            height: 50px;
            color: white;
            background-color: orange;
            border: none;
            border-radius: 10px;
        }

        .row button:active {
            background-color: grey;
        }
    </style>
</head>
<body>
    <!-- 这是一个顶层容器, 放其他元素 -->
    <div class="container">
        <h2>表白墙</h2>
        <div class="row">
            <span>谁</span>
            <input type="text" id="from">
        </div>

        <div class="row">
            <span>对谁</span>
            <input type="text" id="to">
        </div>

        <div class="row">
            <span>说什么</span>
            <input type="text" id="message">
        </div>

        <div class="row">
            <button>提交</button>
        </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script>
        let container = document.querySelector('.container');
        let fromInput = document.querySelector('#from');
        let toInput = document.querySelector('#to');
        let messageInput = document.querySelector('#message');
        let button = document.querySelector('button');
        button.onclick = function() {
            // 1. 把用户输入的内容获取到. 
            let from = fromInput.value;
            let to = toInput.value;
            let message = messageInput.value;
            if (from == '' || to == '' || message == '') {
                return;
            }
            // 2. 构造一个 div, 把这个 div 插入到 .container 的末尾
            let newDiv = document.createElement('div');
            newDiv.className = 'row';
            newDiv.innerHTML = from + " 对 " + to + " 说: " + message;
            // 3. 把 div 挂在 container 里面
            container.appendChild(newDiv);
            // 4. 把之前的输入框内容进行清空
            fromInput.value = '';
            toInput.value = '';
            messageInput.value = '';

            // 5. [新的步骤] 需要把刚才输入框里取到的数据, 构造成 POST 请求, 交给后端服务器!

            // JSON格式
            let messageJson={
                //kv值 k是我们现在定义的,v是在上面我们自己定义的
                from:from,
                to:to,
                message:message
            }
            $.ajax({
                type:"post",
                url:"message",
                contentType:'application/json;charset=utf8',
                // ajax构造请求发送JSON
                data:JSON.stringify(messageJson),
                //当服务器返回数据时,执行
                success:function (){
                    alert("提交成功!");
                },
                error:function (){
                    alert("提交失败");
                }
            })
        }

        //这个函数再页面加载时候调用,通过这个函数从服务器获取当前的消息列表
        //摈弃显示到页面上
        function load(){
            $.ajax({
                type: 'get',
                url: 'message',
                contentType:'application/json;charset=utf8',
                //当服务器返回数据时,才会执行
                success: function(body){
                    //服务器传来的时JSON格式,但ajax根据Content-Type为
                    //application/json,ajax会帮我们自动类型转换成js数组

                    let container=document.querySelector('.container');
                    //服务器传来的数据都在body里
                    //遍历body
                    for(let message of body){
                        let newDiv=document.createElement('div');
                        newDiv.className='row';
                        newDiv.innerHTML=message.from +" 对 "+message.to+ " 说 "+message.message;
                        //把newDiv加在container的里面
                        container.appendChild(newDiv);
                    }
                }
            })
        }

        //函数页面写在这代表页面加载/刷新时执行load函数
        load();

    </script>
</body>
</html>

后端页面

package org.example;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

//对应前端的格式
//名字和全都key时一致的
class Message{
    public String from;
    public String to;
    public String message;

    @Override
    public String toString() {
        return "org.example.Message{" +
                "from='" + from + '\'' +
                ", to='" + to + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    //因为get、post都会用到这个对象,所以共享出来
    private ObjectMapper objectMapper=new ObjectMapper();
    //private List<org.example.Message> messageList=new ArrayList<>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //报文格式
        resp.setContentType("application/json;charset=utf8");

        List<Message> messageList=load();
        //把messageList对象转成JSON格式
        String respString=objectMapper.writeValueAsString(messageList);
        resp.getWriter().write(respString);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");

        //第一个参数从拿哪读,转成什么类型
        Message message=objectMapper.readValue(req.getInputStream(),Message.class);
        save(message);
        System.out.println("message"+message);
        //把这些数据存储起来
        //messageList.add(message);
        //System.out.println("messaage="+message);

        //返回保存成功响应
        resp.getWriter().write("{\"ok\":1}");
    }
    // 把当前的消息存到数据库中
    private void save(Message message) {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            // 1. 和数据库建立连接
            connection = DBUtil.getConnection();
            // 2. 构造 SQL 语句
            String sql = "insert into message values(?, ?, ?)";
            //写入sql
            statement = connection.prepareStatement(sql);
            //填入问号
            statement.setString(1, message.from);
            statement.setString(2, message.to);
            statement.setString(3, message.message);
            // 3. 执行 SQL 语句
            int ret = statement.executeUpdate();
            if (ret != 1) {
                System.out.println("插入失败!");
            } else {
                System.out.println("插入成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 4. 关闭连接.
            DBUtil.close(connection, statement, null);
        }
    }

    // 从数据库查询到记录
    private List<Message> load() {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Message> messageList = new ArrayList<>();
        try {
            // 1. 建立连接
            connection = DBUtil.getConnection();
            // 2. 构造 SQL
            String sql = "select * from message";
            //写入sql
            statement = connection.prepareStatement(sql);
            // 3. 执行 SQL
            resultSet = statement.executeQuery();
            // 4. 遍历结果集
            while (resultSet.next()) {
                Message message = new Message();
                message.from = resultSet.getString("from");
                message.to = resultSet.getString("to");
                message.message = resultSet.getString("message");
                messageList.add(message);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 5. 释放资源
            DBUtil.close(connection, statement, resultSet);
        }
        return messageList;
    }
}

建立连接

完成与数据库建立连接

package org.example;

import com.mysql.cj.jdbc.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// 期望通过这个类来完成数据库建立连接的过程.
// 建立连接需要使用 DataSource . 并且一个程序有一个 DataSource 实例即可. 此处就使用单例模式来实现.
public class DBUtil {
    private static DataSource dataSource = null;

    private static DataSource getDataSource() {
        if (dataSource == null) {
            dataSource = new MysqlDataSource();
            ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/MessageWall?characterEncoding=utf8&useSSL=false");
            ((MysqlDataSource)dataSource).setUser("root");
            ((MysqlDataSource)dataSource).setPassword("monan1946");
        }
        return dataSource;
    }

    public static Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    }

    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {
        // 此处还是推荐大家写成分开的 try catch.
        // 保证及时一个地方 close 异常了, 不会影响到其他的 close 的执行.
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

抓包过程

当页面提交数据时,触发post请求,会把数据提交到服务器,服务器会把数据存储起来。

当刷新页面时,会触发get请求,服务器会把数据回传给页面,页面会把数据继续显示到页面上,所以数据会依据存在

为什么刷新页面时会自动触发get请求呢?

在HTTP协议中,GET请求是用来获取服务器上的资源的。当你在浏览器中输入一个URL并按下回车键或者点击刷新按钮时,浏览器会向服务器发送一个GET请求,请求服务器返回该URL对应的资源。

客户端发起的请求,会自动触发服务器的对应的do方法

服务器返回响应,就会触发客户端的代码,也就是success的回调函数

模拟用户登录

基本逻辑

前端传递用户名和密码

当用户名与密码正确时,后端创建session(cookie),把用户名写进去,并且创建计数器。之后在另一个页面,获取session中的用户名,再把计数器也取出,计数器++,并且两个打印,计数器更新后,再把更新后的计数器写入session

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页</title>
</head>
<body>
    <!-- action是路径 method是方法 -->
    <form action="login" method="post">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="submit" name="提交">
    </form>
</body>
</html>

后端

loginServlet

package login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/login")
//处理登录请求
public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        String username=req.getParameter("username");
        String password=req.getParameter("password");

        //数据为空时
        if(username==null || username.equals("")|| password==null || password.equals("")){
            //返回到登录页面
            //resp.sendRedirect("login.html");
            resp.getWriter().write("用户名或密码错误,请重新登录!");
            return;
        }
        if(username.equals("user")&&password.equals("123")){
            //创建一个session会话 把用户信息填写到session中
            //如果会话存在直接获取,根据cookie中的sessionid来查
            //如果不存在就创建新的
            //第一次登录时,cookie没有sessionid,就会创建新的会话对象
            //同时这个getsession还会生成一个sessionid,把这个sessionid作为Set-Cookie中的字段返回
            //给浏览器保存
            //一个sessionid对应一个session
            HttpSession sessio=req.getSession(true);
            sessio.setAttribute("username","user");
            //设置计数器 用来表示用户访问页面次数
            Integer visitCount= (Integer) sessio.getAttribute("visitCount");
            //如果visitCount为空时,就设置0
            if(visitCount==null){
                //第二个参数是Object 所以会自动装箱成Integer
                sessio.setAttribute("visitCount",0);
            }else
            {
                //如果已经存在,就不设置为0
            }
            resp.sendRedirect("index");
        }
        else{
            resp.getWriter().write("用户名或密码错误,请重新登录!");
            return;
        }
    }
}

indexServlet

package login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/index")
public class indexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        //false不创建会话,有则有,没有则要求用户重新登录
        HttpSession session=req.getSession(false);
        //用户未登录,跳转登录界面,重新登录
        //当浏览器直接访问这个页面时 并没有先进入login.html页面 就会出现session==null的情况
        if(session==null){
            resp.sendRedirect("login.html");
            return;
        }
        //这里就是登录成功
        //获取会话中的数据

        //因为getAttribute返回的是Object 所以要强转

        //获取session中传来的username
        String username= (String) session.getAttribute("username");
        //session第二个参数是Object,虽然写的是0,但是会自动装箱成Integer,取的时候也是Integer
        //获取session中传来的计数器
        Integer visitCount= (Integer) session.getAttribute("visitCount");

        visitCount=visitCount+1;

        //加数后,再写回去
        session.setAttribute("visitCount",visitCount);

        resp.getWriter().write("当前用户: "+username+"访问次数:"+visitCount);
    }
}

第一次请求

首次登录,都会触发get方法

第二次请求 

输入用户名密码登录

响应

JSESSIONID就是key(servlet自动生成的key名字) 后面是一传很长的十六进制数字,就是value

value就是服务器生成的sessionid

可以看到已经保存在浏览器内了

HttpSession sessio=req.getSession(true);

就是这个代码,实现创建会话,生成sessionid并且把sessionid通过Set-Cookie返回给浏览器

因为上面重定向了,所以浏览器get了index的页面

这是报文里就有了cookie

响应

这时就会读取请求中的cookie中的username,并且显示出来

上传文件

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- enctype="multipart/form-data"指定了表单数据的编码方式,这样文件上传操作才能正确地执行。 -->
    <form action="upload" method="post" enctype="multipart/form-data">
        <input type="file" name="MyFile">
        <input type="submit" value="上传">
    </form>
</body>
</html>

后端

package upload;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;

@MultipartConfig//servlet上传文件时默认关闭的,写上这个注解,打开
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
//        name要对应前端的name
        //获取文件
        Part part=req.getPart("MyFile");

//        文件真实名字
        resp.getWriter().write(part.getSubmittedFileName()+"<br>");

        //文件大小
        System.out.println(part.getSize()+"<br>");

        //文件类型
        resp.getWriter().write(part.getContentType()+"<br>");

        //将文件写入磁盘
        part.write("D:/4k阿狸.jpg");

        resp.getWriter().write("upload ok");
    }
}

相关推荐

  1. MyBatis实战指南(三):注解使用方法

    2024-04-15 06:46:02       50 阅读
  2. 恒虚警处理其他功能的Matlab实现

    2024-04-15 06:46:02       61 阅读
  3. Viewpage+TabLayout+Fragment功能实现

    2024-04-15 06:46:02       35 阅读
  4. File类方法

    2024-04-15 06:46:02       37 阅读
  5. 实用功能:Git命令

    2024-04-15 06:46:02       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-15 06:46:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-15 06:46:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-15 06:46:02       82 阅读
  4. Python语言-面向对象

    2024-04-15 06:46:02       91 阅读

热门阅读

  1. Kali安全

    2024-04-15 06:46:02       35 阅读
  2. 数据库常用语句复建链接记录 枚举类型转换语义

    2024-04-15 06:46:02       39 阅读
  3. 2024.4.17 Python爬虫复习day05 可视化

    2024-04-15 06:46:02       43 阅读
  4. ARM的TrustZone技术

    2024-04-15 06:46:02       148 阅读
  5. 人工智能常见的分类算法

    2024-04-15 06:46:02       38 阅读
  6. Go语言异常处理方式

    2024-04-15 06:46:02       42 阅读
  7. ASP.NET基于BS方式的即时通讯软件的设计与实现

    2024-04-15 06:46:02       35 阅读
  8. [leetcode 链表] 反转链表 vs 链表相交

    2024-04-15 06:46:02       37 阅读
  9. Docker搭建Emby

    2024-04-15 06:46:02       127 阅读
  10. .Net 里面WhenAll的解释和用法

    2024-04-15 06:46:02       38 阅读
  11. 智能指针三剑客:shared_ptr

    2024-04-15 06:46:02       34 阅读
  12. 【LeetCode刷题记录】189. 轮转数组

    2024-04-15 06:46:02       43 阅读