朗读者项目

本文详细记录了一个朗读者项目的开发过程,包括需求分析、实施可行性、技术难点解决、ER图设计、数据库创建及代码开发。项目旨在实现用户注册登录、上传音频章节、播放音频等功能,通过学习前端录制上传技术,克服了技术挑战。

前言:对于之前系统地学习java之路,现在面临找工作,发现对项目的询问比较多,之前只是把自己的项目挂在了github上,还是总结一下比较好。

一、需求分析
第一眼就看上了这个项目,觉得一个可以实现用户注册登录,上传音频章节信息图书资料的项目对我而言十分合适,其中有JDBC编程实现的注册登录上传书籍等静态文本内容数据库交互操作。又有上传音频播放这种比较新鲜我没有学习过的点。拿来做项目真是极好的。

进入正题:做朗读者网的需求重点是实现小说上传和音频的上传,用户的注册和登录。
之后可以增加其他的拓展性需求,比如加个视频,美化下界面,实现用户管理,个人中心什么的。

二、实施可行性
从需求分析也能得出,目前我的水平只有开发学生信息管理系统登录注册功能时MVC那一套后端的开发,这次的开发,我的技术难点在于从头开发,相当于前端那一套得研究一下,录制音频的方法也得好好学习一下子。
可以解决:用户注册登录,添加书籍章节。
技术难点:录制音频,上传音频,播放音频。前端页面的开发。

三、技术难点解决
结合菜鸟编程和csdn上的教程找到一个视频的录制上传。
record.html文件
`

开始录制

预览

停止

录制中

下载
`

以及JavaScript


// document 是在浏览器中运行时一直存在的一个变量,表示的意思是代表文档树
// html Document Object Model Tree    DOM 树
// document 粗糙的可以理解成这棵树的根

// getElementById 从树上,根据 id,找到对应的结点(标签)
let preview = document.getElementById("preview"); 
let recording = document.getElementById("recording");
let startButton = document.getElementById("startButton");
let stopButton = document.getElementById("stopButton");
let downloadButton = document.getElementById("downloadButton");

function wait(delayInMS) {
    // setTimeout(执行什么方法,多少毫秒之后)
    // 类似 Java 中的定时器(Timer)
    // 设定一个闹钟一样的效果
    return new Promise(resolve => setTimeout(resolve, delayInMS));
}

function startRecording(stream, lengthInMS) {
    console.log("开始录制");

    let recorder = new MediaRecorder(stream);   // 定义一个媒体录制对象
    let data = [];

    // 当(on) 数据(data)可用(available) 时,执行该方法
    recorder.ondataavailable = function (event) {
        console.log("数据可用");
        // event.data 录制下来的视频和音频数据,存入 data 数组
        data.push(event.data);  // 线性表的尾插
    };

    // 开始录制
    recorder.start();

    // resolve 成功的时候应该执行的方法,对应 then 传入的方法
    // reject 失败的时候应该执行的方法,对应 catch 传入的方法
    let stopped = new Promise(function (resolve, reject) {
        recorder.onstop = resolve;
        recorder.onerror = function(event) { 
            reject(event.name);
        }
    });

    // 持续 lengthInMS 时间后,执行 then 中的方法
    let recorded = wait(lengthInMS).then(
        function() {
            // 20 秒之后
            // 判断 recorder 是否还在录制,如果还在录制 == "recording",则,停止录制
            if (recorder.state == "recording") {
                console.log("停止录制");
                recorder.stop();
            }
        }
    );

    return Promise.all([
        stopped,
        recorded
    ])
    .then(() => data);
}

function startCapturing() {
    console.log("点击采集");
    
    // 会触发,申请权限的操作
    let promise = navigator.mediaDevices.getUserMedia({
        video: true,        // 申请摄像头权限
        audio: true         // 申请麦克风权限
    });

    // 如果用户同意了,就执行 then 中的方法,如果失败(用户不同意 or 其他失败)会执行 catch 中的方法
    let promise2 = promise.then(function(stream) {
        console.log("同意授权");
        // 用户同意了
        // stream 变量就代表录制的视频和音频了
        preview.srcObject = stream;

        // 处理兼容性的,类似 if (!preview.captureStream) { preview.captureStream = preview.mozCaptureStream; }
        preview.captureStream = preview.captureStream || preview.mozCaptureStream;

        // 接着执行的是,当 preview 开始(on) 播放(palying) 时,执行 then 的方法
        // resolve 形参对应的实参就是 xxxx 函数
        return new Promise(function(resolve) {
            preview.onplaying = resolve;
        });
    });

    function xxxx() {
        return startRecording(preview.captureStream(), 5000); //
    }
    
    promise2.then(xxxx) // 调用 function(resolve) { ... } 这个函数
    .then(function (data) {
        console.log("使用录制下来的数据");
        console.log(data);

        let recordedBlob = new Blob(data, { type: "video/webm" });
        recording.src = URL.createObjectURL(recordedBlob);
    })
    .catch(e => {
        console.log(e);
    });
}

function stopRecording() {
    console.log("点击了结束录制");
}

// startButton.addEventListener("click", startRecording);   <-- 和下面的写法,目前可以认为是一样的效果
startButton.onclick = startCapturing;        
// 进行事件绑定,发生了 startButton 的点击(click)事件后,
// 请执行 startRecording
// 这种形态就是俗称的回调函数(callback)
// 当 startButton 上有了 click 事件时,startButton.onclick();


stopButton.onclick = stopRecording;
// 在 stopButton 发生了(on) 点击(click)事件后,执行 stopRecording 函数

在这里插入图片描述
弄出来效果是这样的。到时候只保留音频录制功能就好了。

四:ER图,数据库设计

一个用户可以上传多部小说(1:n)
一个小说可以有多个章节(1:n)
一个章节对应一个音频(1:1)

ER图大概就是:

用户 —> 小说 —>章节 —> 音频
在这里插入图片描述

然后设置表的属性:
Users:uid,username,password
Books:bid,uid,tittle
Sections:sid,bid,name
Audios:aid,sid,uuid,type,content

uuid是逻辑主键,好处是如果audios和别的表合并那aid可能就失效了,但是uuid是独立的主键,永远可用正确。这里就用用。

五、执行建库建表代码和xml文件

create database Audio charset utf8mb4;
use Audio;
create table users (
 uid int primary key auto_increment comment '用户id',
 username varchar(64) not null unique comment '用户名',
 password char(64) not null comment '经过sha-256计算后的用户密码'
);
create table books (
 bid int primary key auto_increment comment '小说id',
 uid int not null comment '上传用户id',
 title varchar(100) not null comment '小说名称'
);
create table sections (
 sid int primary key auto_increment comment '章节id',
 bid int not null comment '属于哪本小说的id',
 name varchar(100) comment '章节名称'
);
create table audios (
 aid int primary key auto_increment comment '音频id',
 sid int not null unique comment '属于哪个章节的id',
 uuid char(36) not null comment 'uuid音频的唯一标识',
 type varchar(20) not null comment '音频类型audio/wmv audio/mp3',
 content longblob default null comment '音频内容'
);

xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 项目基本信息 -->
    <groupId>zjw</groupId>
    <artifactId>AudioFiction</artifactId>
    <version>1.0-SNAPSHOT</version>


    <!-- war 包形式打包,IDEA会根据这个选项,自动创建 artifacts 选项-->
    <packaging>war</packaging>

    <!-- 项目的字符集 + 字符集选项配置 -->
    <properties>
        <encoding>utf-8</encoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>


    <!-- 添加需要的第三方依赖jar包 -->
    <dependencies>

    <!-- 提供 Servlet 提供的标准接口 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <!-- 这个 jar 包只在开发 + 编译阶段使用,运行阶段不需要 -->
            <scope>provided</scope>
        </dependency>

        <!-- 添加 MySQL Driver 的依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!-- 添加处理 json 数据的依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
    </dependencies>

</project>

六、方法,url,功能
在这里插入图片描述
主要逻辑:tomcat调用servlet,servlet接入逻辑层,service,service调用DAO,DAO对数据库进行交互。

在这里插入图片描述
框架就搭好了。

然后开始开发Model:
六、代码开发

Model层:

package com.wanghaidong.model;

import java.io.InputStream;

public class Audio {
    public String contentType;
    public InputStream inputStream;

    public Audio(String type, InputStream content) {
        this.contentType = type;
        this.inputStream = content;
    }
}

package com.wanghaidong.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class Book {
    public int bid;
    public User user;
    public String title;
    public List<Section> sections;

    public Book() {
        this.sections = new ArrayList<>();
    }

    public Book(int bid, User user, String title) {
        this.bid = bid;
        this.user = user;
        this.title = title;
        this.sections = new ArrayList<>();
    }

    @Override
    public String toString() {
        return "Book{" +
                "bid=" + bid +
                ", user=" + user +
                ", title='" + title + '\'' +
                ", sections=" + sections +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Book)) return false;
        Book book = (Book) o;
        return bid == book.bid &&
                Objects.equals(user, book.user) &&
                Objects.equals(title, book.title) &&
                Objects.equals(sections, book.sections);
    }

    @Override
    public int hashCode() {

        return Objects.hash(bid, user, title, sections);
    }
}

package com.wanghaidong.model;

public class Section {
    public int sid;
    public String name;
    // 如果关联声音,uuid 就是保存声音的 uuid
    // 否则,uuid == null
    public String uuid;

    public Section() {
    }

    public Section(int sid, String uuid, String name) {
        this.sid = sid;
        this.uuid = uuid;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Section{" +
                "uuid='" + uuid + '\'' +
                "name='" + name + '\'' +
                '}';
    }
}

package com.wanghaidong.model;

import java.util.Objects;

/**
 * 一般来说,model 这类对象,都需要覆写
 * 1. toString
 * 2. equals
 * 3. hashCode
 */
public class User {
    public int uid;
    public String username;

    public User() {
    }

    public User(int uid, String username) {
        this.uid = uid;
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;     // 两个引用是不是指向同一个对象
        if (!(o instanceof User)) return false; // 两个对象的类型是否一致
        User user = (User) o;                   // 判断重要属性是否一样
        return uid == user.uid &&
                Objects.equals(username, user.username);
    }

    @Override
    public int hashCode() {

        return Objects.hash(uid, username);
    }
}

DAO层:

package com.wanghaidong.dao;

import com.wanghaidong.model.User;
import com.wanghaidong.util.DB;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.*;

public class UserDao {
    public User insert(String username, String plainPassword) throws SQLException {
        String password = encrypt(plainPassword);

        String sql = "insert into users (username, password) values (?, ?)";

        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
                s.setString(1, username);
                s.setString(2, password);

                s.executeUpdate();

                try (ResultSet r = s.getGeneratedKeys()) {
                    if (!r.next()) {
                        return null;
                    }

                    return new User(r.getInt(1), username);
                }
            }
        }
    }

    public User select(String username, String plainPassword) throws SQLException {
        String password = encrypt(plainPassword);

        String sql = "select uid from users where username = ? and password = ?";

        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql)) {
                s.setString(1, username);
                s.setString(2, password);

                try (ResultSet r = s.executeQuery()) {
                    if (!r.next()) {
                        return null;
                    }

                    return new User(r.getInt(1), username);
                }
            }
        }
    }

    // 这个做法实际上也不适合生产环境真正使用
    // 但至少比明文的情况要安全一点
    private String encrypt(String plain) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] bytes = plain.getBytes();
            byte[] digest = messageDigest.digest(bytes);
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String a = "123";
        UserDao userDao = new UserDao();
        String encrypt = userDao.encrypt(a);
        System.out.println(encrypt);
    }
}

package com.wanghaidong.dao;

import com.wanghaidong.model.Section;
import com.wanghaidong.util.DB;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class SectionDao {
    public void insert(int bid, String name) throws SQLException {
        String sql = "insert into sections (bid, name) values (?, ?)";

        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql)) {
                s.setInt(1, bid);
                s.setString(2, name);

                s.executeUpdate();
            }
        }
    }

    public List<Section> selectByBid(int bid) throws SQLException {
        // 必须用左联查询,自己思考为什么!
        String sql = "select sections.sid, uuid, name " +
                "from sections left join audios on sections.sid = audios.sid " +
                "where bid = ? order by sections.sid";
        List<Section> sections = new ArrayList<>();
        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql)) {
                s.setInt(1, bid);

                try (ResultSet r = s.executeQuery()) {
                    while (r.next()) {
                        Section section = new Section(
                                r.getInt("sid"),
                                r.getString("uuid"),
                                r.getString("name")
                        );
                        sections.add(section);
                    }
                }
            }
        }

        return sections;
    }
}
package com.wanghaidong.dao;

import com.wanghaidong.model.Book;
import com.wanghaidong.model.User;
import com.wanghaidong.util.DB;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class BookDao {
    public Book insert(User user, String title) throws SQLException {
        String sql = "insert into books (uid, title) values (?, ?)";

        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
                s.setInt(1, user.uid);
                s.setString(2, title);

                s.executeUpdate();

                try (ResultSet r = s.getGeneratedKeys()) {
                    if (!r.next()) {
                        return null;
                    }

                    return new Book(r.getInt(1), user, title);
                }
            }
        }
    }

    public List<Book> selectAll() throws SQLException {
        // 联表查询
        String sql = "select bid, title, users.uid, users.username " +
                "from books, users " +
                "where books.uid = users.uid " +
                "order by bid desc";

        List<Book> books = new ArrayList<>();
        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql)) {
                try (ResultSet r = s.executeQuery()) {
                    while (r.next()) {
                        User user = new User(r.getInt("uid"), r.getString("username"));
                        Book book = new Book(r.getInt("bid"), user, r.getString("title"));

                        books.add(book);
                    }
                }
            }
        }
        return books;
    }

    public Book selectByBid(int bid) throws SQLException {
        String sql = "select bid, title, users.uid, users.username " +
                "from books, users " +
                "where books.uid = users.uid and bid = ?";

        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql)) {
                s.setInt(1, bid);

                try (ResultSet r = s.executeQuery()) {
                    if (!r.next()) {
                        return null;
                    }

                    User user = new User(r.getInt("uid"), r.getString("username"));
                    return new Book(r.getInt("bid"), user, r.getString("title"));
                }
            }
        }
    }
}

package com.wanghaidong.dao;

import com.wanghaidong.model.Audio;
import com.wanghaidong.util.DB;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class AudioDao {
    public void insert(int sid, String uuid, String contentType, InputStream inputStream) throws SQLException {
        String sql = "insert into audios (sid, uuid, type, content) values (?, ?, ?, ?)";

        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql)) {
                s.setInt(1, sid);
                s.setString(2, uuid);
                s.setString(3, contentType);
                s.setBlob(4, inputStream);

                s.executeUpdate();
            }
        }
    }

    public Audio select(String uuid) throws SQLException {
        String sql = "select type, content from audios where uuid = ?";

        try (Connection c = DB.getConnection()) {
            try (PreparedStatement s = c.prepareStatement(sql)) {
                s.setString(1, uuid);

                try (ResultSet r = s.executeQuery()) {
                    if (!r.next()) {
                        return null;
                    }

                    return new Audio(r.getString("type"), r.getBinaryStream("content"));
                }
            }
        }
    }
}

Service层:

package com.wanghaidong.service;

import com.wanghaidong.dao.AudioDao;
import com.wanghaidong.model.Audio;

import javax.servlet.http.Part;
import java.io.IOException;
import java.sql.SQLException;
import java.util.UUID;

public class AudioService {
    private AudioDao audioDao;

    public AudioService() {
        audioDao = new AudioDao();
    }

    public String save(int sid, Part audio) throws IOException, SQLException {
        String uuid = UUID.randomUUID().toString();

        audioDao.insert(sid, uuid, audio.getContentType(), audio.getInputStream());

        return uuid;
    }

    public Audio get(String uuid) throws SQLException {
        return audioDao.select(uuid);
    }
}

Servlet层

package com.wanghaidong.service;

import com.wanghaidong.dao.BookDao;
import com.wanghaidong.dao.SectionDao;
import com.wanghaidong.model.Book;
import com.wanghaidong.model.User;

import java.sql.SQLException;
import java.util.List;

public class BookService {
    private BookDao bookDao;
    private SectionDao sectionDao;

    public BookService() {
        bookDao = new BookDao();
        sectionDao = new SectionDao();
    }

    public List<Book> list() throws SQLException {
        return bookDao.selectAll();
    }

    public Book post(String title, User user) throws SQLException {
        return bookDao.insert(user, title);
    }

    public Book get(int bid) throws SQLException {
        Book book = bookDao.selectByBid(bid);
        if (book == null) {
            return null;
        }
        book.sections = sectionDao.selectByBid(bid);

        return book;
    }

    public void addSection(int bid, String name) throws SQLException {
        sectionDao.insert(bid, name);
    }
}

package com.wanghaidong.service;

import com.wanghaidong.dao.UserDao;
import com.wanghaidong.model.User;

import java.sql.SQLException;

public class UserService {
    private UserDao userDao;

    public UserService() {
        userDao = new UserDao();
    }

    public User register(String username, String password) throws SQLException {
        return userDao.insert(username, password);
    }

    public User login(String username, String password) throws SQLException {
        return userDao.select(username, password);
    }
}

package com.wanghaidong.servlet;

import com.wanghaidong.model.Audio;
import com.wanghaidong.service.AudioService;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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.SQLException;

@WebServlet("/audio/get")
public class AudioGetServlet extends HttpServlet {
    private AudioService audioService;

    @Override
    public void init() throws ServletException {
        audioService = new AudioService();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String uuid = req.getParameter("uuid");

        Audio audio = null;
        try {
            audio = audioService.get(uuid);
            if (audio == null) {
                resp.sendError(404, "没有这段声音");
                return;
            }
        } catch (SQLException e) {
            throw new ServletException(e);
        }

        resp.setContentType(audio.contentType);
        ServletOutputStream outputStream = resp.getOutputStream();
        byte[] buf = new byte[1024];
        int len;

        while ((len = audio.inputStream.read(buf)) != -1) {
            outputStream.write(buf, 0, len);
        }
        audio.inputStream.close();
    }
}

package com.wanghaidong.servlet;

import com.wanghaidong.service.AudioService;

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;
import java.io.PrintWriter;
import java.sql.SQLException;

@MultipartConfig
@WebServlet("/upload/audio")
public class AudioUploadServlet extends HttpServlet {
    private AudioService audioService;

    @Override
    public void init() throws ServletException {
        audioService = new AudioService();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        int sid = Integer.parseInt(req.getParameter("sid"));

        Part audio = req.getPart("audio");


        // 保存声音,得到声音的 uuid,同时关联 sid
        resp.setContentType("utf-8");
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        try {
            String uuid = audioService.save(sid, audio);
            writer.printf("{\"uuid\": \"%s\"}%n", uuid);
        } catch (SQLException e) {
            e.printStackTrace();
            resp.setStatus(500);
            writer.printf("{\"reason\": \"%s\"}%n", e.getMessage());
        }
    }
}

package com.wanghaidong.servlet;

import com.wanghaidong.model.Book;
import com.wanghaidong.model.User;
import com.wanghaidong.service.BookService;

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;
import java.sql.SQLException;

@WebServlet("/post-book")
public class BookPostServlet extends HttpServlet {
    private BookService bookService;

    @Override
    public void init() throws ServletException {
        bookService = new BookService();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String title = req.getParameter("title");

        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");
        if (user == null) {
            resp.sendRedirect("/login.html");
            return;
        }

        try {
            Book book = bookService.post(title, user);
            if (book != null) {
                resp.sendRedirect("/book.jsp?bid=" + book.bid);
            } else {
                resp.sendRedirect("/add-book.jsp");
            }
        } catch (SQLException e) {
            throw new ServletException(e);
        }
    }
}

package com.wanghaidong.servlet;

import com.wanghaidong.service.BookService;

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.SQLException;

@WebServlet("/post-section")
public class SectionPostServlet extends HttpServlet {
    private BookService bookService;

    @Override
    public void init() throws ServletException {
        bookService = new BookService();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        int bid = Integer.parseInt(req.getParameter("bid"));
        String name = req.getParameter("name");

        try {
            bookService.addSection(bid, name);
        } catch (SQLException e) {
            throw new ServletException(e);
        }

        resp.sendRedirect("/book.jsp?bid=" + bid);
    }
}

package com.wanghaidong.servlet;

import com.wanghaidong.model.User;
import com.wanghaidong.service.UserService;

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;
import java.sql.SQLException;

@WebServlet("/login")
public class UserLoginServlet extends HttpServlet {
    private UserService userService;

    @Override
    public void init() throws ServletException {
        userService = new UserService();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");

        try {
            User user = userService.login(username, password);
            if (user == null) {

                resp.sendRedirect("/login.html");
                return;
            }


            HttpSession session = req.getSession();
            session.setAttribute("user", user);

            // 跳转回首页
            resp.sendRedirect("/");
        } catch (SQLException e) {
            throw new ServletException(e);
        }
    }
}

package com.wanghaidong.servlet;

import com.wanghaidong.model.User;
import com.wanghaidong.service.UserService;

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;
import java.sql.SQLException;

@WebServlet("/register")
public class UserRegisterServlet extends HttpServlet {
    private UserService userService;

    @Override
    public void init() throws ServletException {
        // Servlet 生命周期的内容
        userService = new UserService();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 每次都带上 utf-8 的设置,字符集不会出问题
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");


        try {
            User user = userService.register(username, password);
            if (user == null) {

                resp.sendRedirect("/register.html");
                return;
            }


            HttpSession session = req.getSession();
            session.setAttribute("user", user);

            // 跳转回首页
            resp.sendRedirect("/");
        } catch (SQLException e) {
            throw new ServletException(e);
        }
    }
}

前端代码:

<!DOCTYPE html>
<html lang="zh-hans">
<head>
    <meta charset="UTF-8">
    <title>AudioFiction | 用户注册</title>
</head>
<body>
    <form method="post" action="register">
        <div>
            <label for="username">
                用户名:
                <input type="text" id="username" name="username" />
            </label>
        </div>
        <div>
            <label for="password">
                密码:
                <input type="password" id="password" name="password" />
            </label>
        </div>
        <div>
            <button type="submit">注册</button>
        </div>
    </form>
</body>
</html>

<!DOCTYPE html>
<html lang="zh-hans">
<head>
    <meta charset="UTF-8">
    <title>AudioFiction | 用户登陆</title>
</head>
<body>
    <form method="post" action="login">
        <div>
            <label for="username">
                用户名:
                <input type="text" id="username" name="username" />
            </label>
        </div>
        <div>
            <label for="password">
                密码:
                <input type="password" id="password" name="password" />
            </label>
        </div>
        <div>
            <button type="submit">登陆</button>
        </div>
    </form>
</body>
</html>

最后设计一个测试用例,接下来可以测试一下子
https://blog.youkuaiyun.com/weixin_44861663/article/details/108521624

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值