JavaWeb項(xiàng)目實(shí)戰(zhàn)之表白墻和在線相冊(cè)
一. 案例: 表白墻 (使用模板引擎)
1. 首先創(chuàng)建 maven 項(xiàng)目
引入需要的依賴,創(chuàng)建必要的目錄



2. 創(chuàng)建好模板文件

<!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>
</head>
<body>
<form action="confession" method="post">
<div class="parent">
<div id="wall">表白墻</div>
<div id="remind">輸入后點(diǎn)擊提交,會(huì)將信息顯示在表格中</div>
<div class="one"><span class="two">誰(shuí):</span><input type="text" class="text" name="from"></div>
<div class="one"><span class="two">對(duì)誰(shuí):</span><input type="text" class="text" name="to"></div>
<div class="one"><span class="two">說(shuō)什么:</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>對(duì)<span th:text="${message.to}">zw</span>說(shuō): <span th:text="${message.message}">wzz</span>
</div>
</div>
</form>
<style>
/* 去除瀏覽器默認(rèn)樣式 */
* {
margin: 0;
padding: 0;
}
/* 設(shè)置總寬度 */
.parent {
width: 400px;
margin: 0 auto;
}
/* 設(shè)置表白墻樣式 */
#wall {
font-size: 30px;
font-weight: 700;
text-align: center;
margin: 5px;
}
/* 設(shè)置提示信息樣式 */
#remind{
font-size:13px;
text-align: center;
color:gray;
margin: 5px;
}
/* 設(shè)置彈性布局 */
.one {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
}
/* 設(shè)置文字內(nèi)容 */
.two {
width: 100px;
line-height: 40px;
}
/* 設(shè)置輸入框 */
.one .text{
width: 200px;
height: 20px;
padding-left: 3px;
}
/* 提交按鈕的設(shè)置 */
.one .press{
width: 304px;
height: 40px;
color:white;
background-color: orange;
border-radius: 5px;
border: none;
}
/* 設(shè)置鼠標(biāo)點(diǎn)擊的時(shí)候改變顏色 */
.one .press:active{
background-color: red;
}
/* 提交之后內(nèi)容的設(shè)置 */
.elem {
text-align: center;
margin: 15px;
}
</style>
</body>
</html>
3. 使用數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)據(jù).創(chuàng)建一個(gè)類用于數(shù)據(jù)庫(kù)連接
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://127.0.0.1:3306/confessionWall2?characterEncoding=utf-8&useSSL=true&serverTimezone=UTC";
private static final String USERNAME = "root";
private static final String PASSWORD = "0000";
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. 使用 監(jiān)視器 來(lái)初始化 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-8");
engine.setTemplateResolver(resolver);
context.setAttribute("engine",engine);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}5. 編寫 Servlet 代碼
首先創(chuàng)建一個(gè) 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-8");
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-8");
Confession confession = new Confession();
confession.from = req.getParameter("from");
confession.to = req.getParameter("to");
confession.message = req.getParameter("message");
save(confession);
resp.sendRedirect("confession");
③ 實(shí)現(xiàn) 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;
}
④ 實(shí)現(xiàn) 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(1,confession.from);
statement.setString(2, confession.to);
statement.setString(3,confession.message);
int ret = statement.executeUpdate();
if(ret == 1){
System.out.println("插入成功");
}else{
System.out.println("插入失敗");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
ConnectionDB.close(connection,statement,null);
}
}
6. 注意事項(xiàng)
注意模板引擎

注意 亂碼的情況,要添加utf-8



用數(shù)據(jù)庫(kù)的方法存數(shù)據(jù),要先創(chuàng)建好數(shù)據(jù)庫(kù)
create database confessionWall2;
use confessionWall2;
create table confession(
`from` varchar(1024),
`to` varchar(1024),
`message` varchar(1024)
);
還有一些必要的注解也要加上.


7. 部署之后 運(yùn)行截圖
瀏覽器輸入對(duì)應(yīng)的URL
在數(shù)據(jù)庫(kù)為空的時(shí)候界面如下


在輸入幾個(gè)數(shù)據(jù)之后 如下

此時(shí)的數(shù)據(jù)庫(kù)中表的內(nèi)容

重新部署再進(jìn)入U(xiǎn)RL發(fā)現(xiàn)數(shù)據(jù)還是存在.

二. 案例: 在線相冊(cè) (使用模板引擎)
1. 首先創(chuàng)建 maven 項(xiàng)目
引入必要的依賴,已經(jīng)必要的目錄


2. 創(chuàng)建好模板文件
image.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>相冊(cè)</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="sample1" />
<figcaption>
<div>
<h2 th:text="${image.name}">Deconovo</h2>
</div>
</figcaption>
<a th:href="${image.url}"></a>
</figure>
</div>
</body>
</html>
style.css
/* 引入文字樣式庫(kù) */
@import url(https://fonts.googleapis.com/css?family=Raleway:400,700);
*{
margin: 0 auto;
padding: 0 auto;
box-sizing: border-box;
}
html,body{
width: 100%;
height: calc(100% - 50px);
background-color: #212121;
}
.parent{
display: flex;
justify-content: center;
align-items: center;
flex-flow: wrap;
margin: 0;
height: 100%;
}
.nav{
background-color: rgba(255,255,255,0.3);
height: 50px;
width: 100%;
display: flex;
justify-content: left;
align-items: center;
}
/* sample 部分的整體樣式 */
.sample {
font-family: 'Raleway', Arial, sans-serif;
position: relative;
overflow: hidden;
margin: 10px;
min-width: 230px;
max-width: 315px;
width: 100%;
color: #ffffff;
text-align: center;
font-size: 16px;
background-color: #000000;
}
.sample *,
.sample *:before,
.sample *:after {
-webkit-box-sizing: border-box;
box-sizing: border-box;
/* 當(dāng)過(guò)了 0.55s 過(guò)渡效果 */
-webkit-transition: all 0.55s ease;
transition: all 0.55s ease;
}
/* 圖片部分的樣式 */
.sample img {
max-width: 100%;
backface-visibility: hidden;
vertical-align: top;
}
/* figcaption 用作文檔中插圖的圖像,帶有一個(gè)標(biāo)題 */
.sample figcaption {
position: absolute;
bottom: 25px;
right: 25px;
padding: 5px 10px 10px;
}
/* 繪制線條 */
.sample figcaption:before,
.sample figcaption:after {
height: 2px;
width: 400px;
position: absolute;
content: '';
background-color: #ffffff;
}
/* 上面一條線 */
.sample figcaption:before {
top: 0;
left: 0;
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
/* 下面一條線 */
.sample figcaption:after {
bottom: 0;
right: 0;
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
/* 繪制線條 */
.sample figcaption div:before,
.sample figcaption div:after {
width: 2px;
height: 300px;
position: absolute;
content: '';
background-color: #ffffff;
}
/* 左面一條線 */
.sample figcaption div:before {
top: 0;
left: 0;
-webkit-transform: translateY(100%);
transform: translateY(100%);
}
/* 右面一條線 */
.sample figcaption div:after {
bottom: 0;
right: 0;
-webkit-transform: translateY(-100%);
transform: translateY(-100%);
}
/* 文字部分 */
.sample h2,
.sample h4 {
margin: 0;
text-transform: uppercase;
}
.sample h2 {
font-weight: 400;
}
.sample h4 {
display: block;
font-weight: 700;
background-color: #ffffff;
padding: 5px 10px;
color: #000000;
}
.sample a {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
/* 當(dāng)鼠標(biāo)放到圖片時(shí)的效果, .hover 僅演示需要,可自行取消 */
.sample:hover img,
.sample.hover img {
zoom: 1;
filter: alpha(opacity=50);
-webkit-opacity: 0.5;
opacity: 0.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, 0);
transform: translate(0, 0);
}
.sample:hover figcaption:before,
.sample.hover figcaption:before,
.sample:hover figcaption:after,
.sample.hover figcaption:after {
/* 過(guò)渡延時(shí) 0.15s */
-webkit-transition-delay: 0.15s;
transition-delay: 0.15s;
}
/* 背景僅演示作用 */3. 這是通過(guò)訪問(wèn)文件夾里的圖片的
在webapp下創(chuàng)建一個(gè)文件夾 image,里面存放圖片.
通過(guò) getServletContext().getRealPath("/image") 來(lái)獲取絕對(duì)路徑

4. 使用 監(jiān)視器 來(lái)初始化 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-8");
engine.setTemplateResolver(resolver);
context.setAttribute("engine",engine);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}5. 編寫加載頁(yè)面的 Servlet代碼
創(chuàng)建一個(gè) Image 類
class Image {
public String name;
public String url;
}創(chuàng)建一個(gè)類,重寫 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-8");
// 1. 掃描指定路徑 /webapp/image 路徑
List<Image> images = loadImage();
// 2. 構(gòu)造到模板頁(yè)面
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);
}
}
實(shí)現(xiàn) loadImage 方法
注意使用 getRealPath 方法
以及注意使用 file.listFiles()方法
private List<Image> loadImage() {
List<Image> images = new ArrayList<>();
// 首先得到 /webapp/image 的絕對(duì)路徑
ServletContext context = this.getServletContext();
// 這里是將 webapp下的目錄轉(zhuǎn)換成一個(gè)絕對(duì)路徑
String path = context.getRealPath("/image");
// 根據(jù)路徑 看里面有哪些圖片.
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 代碼
① 創(chuàng)建一個(gè)類,重寫 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;
// 這個(gè)注解在上傳文件的功能中是必要的
@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. 注意事項(xiàng)
主要是得到文件夾,找到路徑的步驟復(fù)雜點(diǎn).重點(diǎn)掌握這幾種方法的使用


前后端約定好的名稱要對(duì)應(yīng).


傳文件需要加上注解,否則會(huì)報(bào)500的錯(cuò)誤.@MultipartConfig
8. 部署之后 運(yùn)行截圖
文件中已經(jīng)存了兩個(gè)圖片,一運(yùn)行就可以看到這些圖片

點(diǎn)擊圖片還能放大

上傳圖片,上傳兩個(gè)圖片

總結(jié)
到此這篇關(guān)于JavaWeb項(xiàng)目實(shí)戰(zhàn)之表白墻和在線相冊(cè)的文章就介紹到這了,更多相關(guān)JavaWeb表白墻和在線相冊(cè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決Java中socket使用getInputStream()阻塞問(wèn)題
這篇文章主要介紹了解決Java中socket使用getInputStream()阻塞問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java的Struts2框架配合Ext JS處理JSON數(shù)據(jù)的使用示例
這篇文章主要介紹了Java的Struts2框架配合Ext JS處理JSON數(shù)據(jù)的使用示例,包括將Ext JS中的JSON數(shù)據(jù)解析為列表的方法,需要的朋友可以參考下2016-03-03
Springboot整合Java?DL4J實(shí)現(xiàn)交通標(biāo)志識(shí)別系統(tǒng)全過(guò)程
在自動(dòng)駕駛系統(tǒng)中,交通標(biāo)志識(shí)別是實(shí)現(xiàn)車輛智能化的關(guān)鍵技術(shù)之一,本文介紹了利用SpringBoot和JavaDeeplearning4j構(gòu)建交通標(biāo)志識(shí)別系統(tǒng)的方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-10-10
springboot項(xiàng)目中常用的工具類和api詳解
在Spring Boot項(xiàng)目中,開發(fā)者通常會(huì)依賴一些工具類和API來(lái)簡(jiǎn)化開發(fā)、提高效率,以下是一些常用的工具類及其典型應(yīng)用場(chǎng)景,涵蓋 Spring 原生工具、第三方庫(kù)(如Hutool、Guava) 和 Java 自帶工具,本文給大家介紹springboot項(xiàng)目中常用的工具類和api,感興趣的朋友一起看看吧2025-04-04
SpringBoot+RabbitMQ+Redis實(shí)現(xiàn)商品秒殺的示例代碼
本文主要介紹了SpringBoot+RabbitMQ+Redis實(shí)現(xiàn)商品秒殺,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Java 8 Stream filter流式過(guò)濾器詳解
本文介紹了Java 8的Stream API中的filter方法,展示了如何使用lambda表達(dá)式根據(jù)條件過(guò)濾流式數(shù)據(jù),通過(guò)實(shí)際代碼示例,展示了filter方法的高效性以及如何結(jié)合findAny和orElse方法處理更復(fù)雜的情況,適合Java新手和追求代碼優(yōu)雅的開發(fā)者閱讀,感興趣的朋友一起看看吧2025-02-02
Spring框架JavaMailSender發(fā)送郵件工具類詳解
這篇文章主要為大家詳細(xì)介紹了Spring框架JavaMailSender發(fā)送郵件工具類,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04

