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");
    }
}

  • 25
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值