JavaWeb项目实战之表白墙和在线相册

Java
263
0
0
2023-09-10
目录
  • 一. 案例: 表白墙 (使用模板引擎)
  • 1. 首先创建 maven 项目
  • 2. 创建好模板文件
  • 3. 使用数据库存储数据.创建一个类用于数据库连接
  • 4. 使用 监视器 来初始化 Thymeleaf
  • 5. 编写 Servlet 代码
  • 6. 注意事项
  • 7. 部署之后 运行截图
  • 二. 案例: 在线相册 (使用模板引擎)
  • 1. 首先创建 maven 项目
  • 2. 创建好模板文件
  • 3. 这是通过访问文件夹里的图片的
  • 4. 使用 监视器 来初始化 Thymeleaf
  • 5. 编写加载页面的 Servlet代码
  • 6. 编写提交图片的 Servlet 代码
  • 7. 注意事项
  • 8. 部署之后 运行截图
  • 总结 

一. 案例: 表白墙 (使用模板引擎)

1. 首先创建 maven 项目

引入需要的依赖,创建必要的目录

2. 创建好模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=.0">
    <title>表白墙</title>
</head>
<body>
    <form action="confession" method="post">
        <div class="parent">
            <div id="wall">表白墙</div>
            <div id="remind">输入后点击提交,会将信息显示在表格中</div>
            <div class="one"><span class="two">谁:</span><input type="text" class="text" name="from"></div>
            <div class="one"><span class="two">对谁:</span><input type="text" class="text" name="to"></div>
            <div class="one"><span class="two">说什么:</span><input type="text" class="text" name="message"></div>
            <div class="one"><input type="submit" value="提 交" class="press"></div>
            <div class="elem" th:each="message : ${messages}">
                <span th:text="${message.from}">wz</span><span th:text="${message.to}">zw</span>说: <span th:text="${message.message}">wzz</span>
            </div>
        </div>
    </form>
    
    <style>
        /* 去除浏览器默认样式 */
        * {
            margin:;
            padding:;
        }
        /* 设置总宽度 */
        .parent {
            width:px;
            margin: auto;
        }
        /* 设置表白墙样式 */
        #wall {
            font-size:px;
            font-weight:;
            text-align: center;
            margin:px;
        }
        /* 设置提示信息样式 */
        #remind{
            font-size:px;
            text-align: center;
            color:gray;
            margin:px;
        }
        /* 设置弹性布局 */
        .one {
            display: flex;
            justify-content: center;
            align-items: center;
            height:px;
        }
        /* 设置文字内容 */
        .two {
            width:px;
            line-height:px;
        }
        /* 设置输入框 */
        .one .text{
            width:px;
            height:px;
            padding-left:px;
        }
        /* 提交按钮的设置 */
        .one .press{
            width:px;
            height:px;
            color:white;
            background-color: orange;
            border-radius:px;
            border: none;
        } 
        /* 设置鼠标点击的时候改变颜色 */
        .one .press:active{
            background-color: red;
        }
        /* 提交之后内容的设置 */
        .elem {
            text-align: center;
            margin:px;
        }
    </style>
</body>
</html>

3. 使用数据库存储数据.创建一个类用于数据库连接

ConnectionDB 类

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;

public class ConnectionDB {
    private static final String URL = "jdbc:mysql://.0.0.1:3306/confessionWall2?characterEncoding=utf-8&useSSL=true&serverTimezone=UTC";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "";

    private static volatile DataSource dataSource = null;

    public static DataSource getDataSource() {
        if(dataSource == null){
            synchronized (ConnectionDB.class){
                if(dataSource == null) {
                    dataSource = new MysqlDataSource();
                    ((MysqlDataSource) dataSource).setURL(URL);
                    ((MysqlDataSource) dataSource).setUser(USERNAME);
                    ((MysqlDataSource) dataSource).setPassword(PASSWORD);

                }
            }
        }
        return dataSource;

    }

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

    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
        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();
            }
        }
    }
}

4. 使用 监视器 来初始化 Thymeleaf

ThymeleafConfig 类

注意加上注解

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ThymeleafConfig implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext 初始化完毕!");
        ServletContext context = servletContextEvent.getServletContext();
        TemplateEngine engine = new TemplateEngine();
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(context);
        resolver.setPrefix("/WEB-INF/template/");
        resolver.setSuffix(".html");
        resolver.setCharacterEncoding("utf-");
        engine.setTemplateResolver(resolver);
        context.setAttribute("engine",engine);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

5. 编写 Servlet 代码

首先创建一个 Confession 类

class Confession{
    public String from;
    public String to;
    public String message;
}

① 重写 doGet 方法

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setContentType("text/html;charset=utf-");
    List<Confession> list = load();
      TemplateEngine engine = (TemplateEngine) getServletContext().getAttribute("engine");
    WebContext webContext = new WebContext(req,resp,getServletContext());
    webContext.setVariable("messages",list);
    engine.process("confessionwall",webContext, resp.getWriter());
}

② 重写 doPost 方法

resp.setContentType("text/html;charset=utf-");
Confession confession = new Confession();
confession.from = req.getParameter("from");
confession.to = req.getParameter("to");
confession.message = req.getParameter("message");
  save(confession);
resp.sendRedirect("confession");

③ 实现 load 方法

private List<Confession> load() {
    List<Confession> list = new ArrayList<>();
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    try {
        connection = ConnectionDB.getConnection();
        String sql = "select * from confession";
        statement = connection.prepareStatement(sql);
        resultSet = statement.executeQuery();
        while(resultSet.next()){
            Confession confession = new Confession();
            confession.from =resultSet.getString("from");
            confession.to = resultSet.getString("to");
            confession.message = resultSet.getString("message");
            list.add(confession);
        }
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    } finally {
        ConnectionDB.close(connection,statement,resultSet);
    }
    return list;
}

④ 实现 save 方法

private void save(Confession confession) {
    Connection connection = null;
    PreparedStatement statement = null;
    try{
        connection = ConnectionDB.getConnection();
        String sql = "insert into confession values (?,?,?)";
        statement = connection.prepareStatement(sql);
        statement.setString(,confession.from);
        statement.setString(, confession.to);
        statement.setString(,confession.message);
        int ret = statement.executeUpdate();
        if(ret ==){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失败");
        }
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    } finally {
        ConnectionDB.close(connection,statement,null);
    }
}

6. 注意事项

注意模板引擎

注意 乱码的情况,要添加utf-8

用数据库的方法存数据,要先创建好数据库

create database confessionWall;

use confessionWall;

create table confession(
    `from` varchar(),
    `to` varchar(),
    `message` varchar()
);

还有一些必要的注解也要加上.

7. 部署之后 运行截图

浏览器输入对应的URL

在数据库为空的时候界面如下

在输入几个数据之后 如下

此时的数据库中表的内容

重新部署再进入URL发现数据还是存在.

二. 案例: 在线相册 (使用模板引擎)

1. 首先创建 maven 项目

引入必要的依赖,已经必要的目录

2. 创建好模板文件

image.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-">
    <title>相册</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <div class="nav">
        <form action="upload" method="POST" enctype="multipart/form-data" >
            <input type="file" name="myImage">
            <input type="submit" value="上传图片">
        </form>
    </div>
    <div class="parent">
            <!-- 第一组图片 -->
        <figure class="sample" th:each="image : ${images}"> 
            <img th:src="${image.url}" alt="sample" />
            <figcaption>
                <div>
                    <h th:text="${image.name}">Deconovo</h2>
                </div>
            </figcaption>
            <a th:href="${image.url}"></a>
        </figure>
    </div>
    
</body>
</html>

style.css

/* 引入文字样式库 */
@import url(https://fonts.googleapis.com/css?family=Raleway:,700);
*{
    margin: auto;
    padding: auto;
    box-sizing: border-box;
}
html,body{
    width:%;
    height: calc(% - 50px);
    background-color: #;
}
.parent{
    display: flex;
    justify-content: center;
    align-items: center;
    flex-flow: wrap;
    margin:;
    height:%;
}
.nav{
    background-color: rgba(,255,255,0.3);
    height:px;
    width:%;
    display: flex;
    justify-content: left;
    align-items: center;
}
/* sample 部分的整体样式 */
.sample {
    font-family: 'Raleway', Arial, sans-serif;
    position: relative;
    overflow: hidden;
    margin:px;
    min-width:px;
    max-width:px;
    width:%;
    color: #ffffff;
    text-align: center;
    font-size:px;
    background-color: #;
}
.sample *,
.sample *:before,
.sample *:after {
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    /* 当过了.55s 过渡效果 */
    -webkit-transition: all.55s ease;
    transition: all.55s ease;
}
/* 图片部分的样式 */
.sample img {
    max-width:%;
    backface-visibility: hidden;
    vertical-align: top;
}
/* figcaption 用作文档中插图的图像,带有一个标题 */
.sample figcaption {
    position: absolute;
    bottom:px;
    right:px;
    padding:px 10px 10px;
}
/* 绘制线条 */
.sample figcaption:before,
.sample figcaption:after {
    height:px;
    width:px;
    position: absolute;
    content: '';
    background-color: #ffffff;
}
/* 上面一条线 */
.sample figcaption:before {
    top:;
    left:;
    -webkit-transform: translateX(%);
    transform: translateX(%);
}
/* 下面一条线 */
.sample figcaption:after {
    bottom:;
    right:;
    -webkit-transform: translateX(-%);
    transform: translateX(-%);
}
/* 绘制线条 */
.sample figcaption div:before,
.sample figcaption div:after {
    width:px;
    height:px;
    position: absolute;
    content: '';
    background-color: #ffffff;
}
/* 左面一条线 */
.sample figcaption div:before {
    top:;
    left:;
    -webkit-transform: translateY(%);
    transform: translateY(%);
}
/* 右面一条线 */
.sample figcaption div:after {
    bottom:;
    right:;
    -webkit-transform: translateY(-%);
    transform: translateY(-%);
}
/* 文字部分 */
.sample h,
.sample h {
    margin:;
    text-transform: uppercase;
}
.sample h {
    font-weight:;
}
.sample h {
    display: block;
    font-weight:;
    background-color: #ffffff;
    padding:px 10px;
    color: #;
}
.sample a {
    position: absolute;
    top:;
    bottom:;
    left:;
    right:;
}
/* 当鼠标放到图片时的效果, .hover 仅演示需要,可自行取消 */
.sample:hover img,
.sample.hover img {
    zoom:;
    filter: alpha(opacity=);
    -webkit-opacity:.5;
    opacity:.5;
}
.sample:hover figcaption:before,
.sample.hover figcaption:before,
.sample:hover figcaption:after,
.sample.hover figcaption:after,
.sample:hover figcaption div:before,
.sample.hover figcaption div:before,
.sample:hover figcaption div:after,
.sample.hover figcaption div:after {
    -webkit-transform: translate(, 0);
    transform: translate(, 0);
}
.sample:hover figcaption:before,
.sample.hover figcaption:before,
.sample:hover figcaption:after,
.sample.hover figcaption:after {
    /* 过渡延时.15s */
    -webkit-transition-delay:.15s;
    transition-delay:.15s;
}
/* 背景仅演示作用 */

3. 这是通过访问文件夹里的图片的

在webapp下创建一个文件夹 image,里面存放图片.

通过 getServletContext().getRealPath("/image") 来获取绝对路径

4. 使用 监视器 来初始化 Thymeleaf

这里的代码不变

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ThymeleafConfig implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext 初始化完毕");
        ServletContext context = servletContextEvent.getServletContext();
        TemplateEngine engine = new TemplateEngine();
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(context);
        resolver.setPrefix("/WEB-INF/template/");
        resolver.setSuffix(".html");
        resolver.setCharacterEncoding("utf-");
        engine.setTemplateResolver(resolver);

        context.setAttribute("engine",engine);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

5. 编写加载页面的 Servlet代码

创建一个 Image 类

class Image {
    public String name;
    public String url;
}

创建一个类,重写 doGet 方法

@WebServlet("/Image")
public class OnlineImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-");
        //. 扫描指定路径 /webapp/image 路径
        List<Image> images = loadImage();
        //. 构造到模板页面
        TemplateEngine engine = (TemplateEngine) getServletContext().getAttribute("engine");
        WebContext webContext = new WebContext(req,resp,getServletContext());
        webContext.setVariable("images",images);
        String html = engine.process("image",webContext);
        resp.getWriter().write(html);
    }
}

实现 loadImage 方法

注意使用 getRealPath 方法

以及注意使用 file.listFiles()方法

private List<Image> loadImage() {
    List<Image> images = new ArrayList<>();
    // 首先得到 /webapp/image 的绝对路径
    ServletContext context = this.getServletContext();
    // 这里是将 webapp下的目录转换成一个绝对路径
    String path = context.getRealPath("/image");
    // 根据路径 看里面有哪些图片.
    File file = new File(path);
    File[] files = file.listFiles();
    for(File f:files){
        Image image = new Image();
        image.name = f.getName();
        image.url = "image/"+f.getName();
        images.add(image);
    }
    return images;
}

6. 编写提交图片的 Servlet 代码

① 创建一个类,重写 doPost 方法

注意一定要加上注解@MultipartConfig

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
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String path = getServletContext().getRealPath("/image");
        Part part = req.getPart("myImage");
        part.write(path + "/" + part.getSubmittedFileName());
        resp.sendRedirect("Image");
    }
}

7. 注意事项

主要是得到文件夹,找到路径的步骤复杂点.重点掌握这几种方法的使用

前后端约定好的名称要对应.

传文件需要加上注解,否则会报500的错误.@MultipartConfig

8. 部署之后 运行截图

文件中已经存了两个图片,一运行就可以看到这些图片

点击图片还能放大

上传图片,上传两个图片