上一節《spring boot第一個web服務》中我們只是簡單的展示了spring mvc的功能,并沒有涉及到具體的CRUD的操作,也沒有涉及到資料持久化的方面,本節中我們將基于傳統的JDBC方式講解web應用中的CRUD操作,具體內容以用戶的注冊、登錄、詳情查詢、串列查詢為場景來展開(注:文章中的例子只為演示spring boot功能而設計,不能做為生產版本,針對生產版本還需做很多思考和優化作業),
1.表結構
/*==============================================================*/ /* Table: t_user 用戶表 */ /*==============================================================*/
create table t_user ( id bigint not null auto_increment comment 'id:主鍵', name varchar(20) not null comment '姓名', password varchar(20) not null comment '密碼', primary key (id) );
2.構建物體類
為了提高代碼的可讀性,我們這里用到了Lombok,它能自動生成getter、setter、toString()等常見方法,使用它時,需引入依賴
<!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
然后使用注解@Data來進行使用
用戶物體類User
package com.kinglead.demo.entity; ? import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; ? import java.io.Serializable; ? @Data //添加getter、setter方法 @NoArgsConstructor //無參建構式 @AllArgsConstructor //所以引數建構式 public class User implements Serializable { private static final long serialVersionUID = -21070736985722463L; /** * id:主鍵 */ private Long id; /** * 姓名 */ private String name; /** * 密碼 */ private String password; }
3.請求Request類
為了方便簡單的對表單進行校驗,我們引入Validation API依賴,使用相關注解宣告校驗規則,如@NotNull、@Size等,注解直接加到類的成員變數上即可,
<!--validation表單校驗--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
UserVo
package com.kinglead.demo.vo; ? import lombok.Data; ? import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import java.io.Serializable; ? @Data public class UserVo implements Serializable { private static final long serialVersionUID = -21070736985722463L; /** * 用戶名 */ @NotNull(message = "用戶名不能為空") @Size(max = 20, message = "用戶名長度不能大于20") private String userName; /** * 密碼 */ @NotNull(message = "密碼不能為空") @Size(max = 20, message = "密碼長度不能大于20") private String password; ? }
4.控制器Controller
用戶UserController
package com.kinglead.demo.controller; ? import com.kinglead.demo.entity.User; import com.kinglead.demo.service.UserService; import com.kinglead.demo.vo.UserVo; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; ? import javax.annotation.Resource; import javax.validation.Valid; import java.util.List; import java.util.Map; ? @Slf4j @Controller @RequestMapping("/user") public class UserController { ? /**注入UserService**/ @Resource private UserService userService; ? /** *注冊頁面 */ @GetMapping("/register") public ModelAndView register(ModelAndView modelAndView){ modelAndView.setViewName("register"); return modelAndView; } ? /** *注冊 */ @PostMapping("/register") public ModelAndView register(ModelAndView modelAndView, @Valid UserVo userVo, BindingResult bindingResult){ //校驗引數 if(bindingResult.hasErrors()){ modelAndView.addObject("error",bindingResult.getFieldError().getDefaultMessage()); modelAndView.setViewName("register"); return modelAndView; } //注冊 User user = new User(); user.setName(userVo.getUserName()); user.setPassword(userVo.getPassword()); userService.insert(user); //注冊成功回傳到登錄頁面 modelAndView.setViewName("login"); return modelAndView; } ? /** *登錄頁面 */ @GetMapping("/login") public ModelAndView login(ModelAndView modelAndView){ modelAndView.setViewName("login"); return modelAndView; } ? /** *登錄 */ @PostMapping("/login") public ModelAndView login(ModelAndView modelAndView,@Valid UserVo userVo, BindingResult bindingResult){ //效驗入參 if(bindingResult.hasErrors()){ modelAndView.addObject("error",bindingResult.getFieldError().getDefaultMessage()); modelAndView.setViewName("login"); return modelAndView; } //效驗用戶 User user = new User(); user.setName(userVo.getUserName()); user.setPassword(userVo.getPassword()); User rstUser = userService.queryByNameAndPassword(user); if(null == rstUser){ modelAndView.addObject("error","用戶名或密碼錯誤!"); modelAndView.setViewName("login"); } //展示首頁 modelAndView.addObject("userName",rstUser.getName()); modelAndView.setViewName("index"); return modelAndView; } ? /** * 查詢用戶串列 */ @GetMapping("/userList") public ModelAndView queryAll(ModelAndView modelAndView){ //查詢用戶串列 List<Map<String, Object>> userList = userService.queryAll(); //回傳 modelAndView.addObject("userList", userList); modelAndView.setViewName("userList"); return modelAndView; } ? }
5.服務介面Service及實作類
UserService
package com.kinglead.demo.service; ? import com.kinglead.demo.entity.User; ? import java.util.List; import java.util.Map; ? public interface UserService { ? /** * 新增用戶 */ User insert(User user); ? /** * 通過用戶名和密碼查詢用戶 */ User queryByNameAndPassword(User user); ? /** * 查詢用戶串列 */ List<Map<String, Object>> queryAll(); ? }
UserServiceImpl
package com.kinglead.demo.service.impl; ? import com.kinglead.demo.entity.User; import com.kinglead.demo.service.UserService; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; ? import javax.annotation.Resource; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; ? @Service public class UserServiceImpl implements UserService { ? @Resource private JdbcTemplate jdbcTemplate; ? /** * 新增用戶 */ @Override public User insert(User user) { jdbcTemplate.update("insert into t_user(name,password) values(?,?)", user.getName(), user.getPassword()); return user; } ? /** * 通過用戶名和密碼查詢用戶 */ @Override public User queryByNameAndPassword(User user) { return jdbcTemplate.queryForObject("select id, name, password from t_user where name = ? and password = ?", this::mapRowToUser, user.getName(), user.getPassword()); } ? /** * 查詢用戶串列 */ @Override public List<Map<String, Object>> queryAll() { return jdbcTemplate.queryForList("select id, name, password from t_user"); } ? private User mapRowToUser(ResultSet rs, int rowNum) throws SQLException { return new User(rs.getLong("id"), rs.getString("name"), rs.getString("password")); } }
6.用戶注冊功能詳解
從第4點UserController,我們可以看到用于注冊的請求有:展示注冊頁面@GetMapping("/register")和完成注冊@PostMapping("/register"),下面我們看看具體的html頁面、service實作和JDBC的操作,
register.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>注冊</title> </head> <body> <form th:action="@{/user/register}" method="post"> <div> <h2>帳號注冊</h2> </div> <div> <!--/*@thymesVar id="error" type=""*/--> <span id="basic-addon0"> </span> <span style="font-size: 12px;color: red" th:text="${error}" aria-describedby="basic-addon0"></span> <br /> </div> <div> <span id="basic-addon1">用戶名</span> <input id="user_name" name="name" type="text" placeholder="用戶名" aria-describedby="basic-addon1" /> ? </div> <br /> <div> <span id="basic-addon2">密 碼</span> <input id="password" name="password" type="password" placeholder="密 碼" aria-describedby="basic-addon2" /> </div> <br /> <div> <button type="submit" style="width:190px;">注 冊</button> </div> </form> </body> </html>
注冊頁面完成后,我們通過瀏覽器訪問:http://localhost:8080/user/register,URL地址映射到@GetMapping("/register")方法
/** *注冊頁面 */ @GetMapping("/register") public ModelAndView register(ModelAndView modelAndView){ modelAndView.setViewName("register"); return modelAndView; }
回傳register.html頁面,瀏覽器展示用戶注冊頁面

在注冊頁面填寫用戶名和密碼后,點擊“注冊”按鈕,

由于register.html中,from的method=“POST”,所以“注冊”按鈕會映射到@PostMapping("/register")方法
/** *注冊 */ @PostMapping("/register") public ModelAndView register(ModelAndView modelAndView, @Valid UserVo userVo, BindingResult bindingResult){ //校驗引數 if(bindingResult.hasErrors()){ modelAndView.addObject("error",bindingResult.getFieldError().getDefaultMessage()); modelAndView.setViewName("register"); return modelAndView; } //注冊 User user = new User(); user.setName(userVo.getUserName()); user.setPassword(userVo.getPassword()); userService.insert(user); //注冊成功回傳到登錄頁面 modelAndView.setViewName("login"); return modelAndView; }
通過@Valid注解打開了表單校驗,所以如果有引數不符合開始宣告的校驗規則,會引數錯誤Errors,如果有引數錯誤,會回傳注冊頁面,并顯示錯誤,如果沒有錯誤,將會呼叫UserService的insert方法
/** * 新增用戶 */ @Override public User insert(User user) { jdbcTemplate.update("insert into t_user(name,password) values(?,?)", user.getName(), user.getPassword()); return user; }
這里就用到了spring封裝的JdbcTemplate,要正常使用JDBC和訪問資料庫還需要做兩件事:
1、引入JDBC依賴和mysql連接驅動依賴(這里使用最常用的mysql資料庫)
<!--JDBC--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--mysql驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
2、配置資料庫連接
application.yml
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/spring_boot_topic
driver-class-name: com.mysql.cj.jdbc.Driver
通過jdbcTemplate的update方法即可插入資料,

7.用戶登錄功能詳解
從第4點UserController,我們可以看到用于注冊的請求有:展示登錄頁面@GetMapping("/login")和完成登錄@PostMapping("/login"),下面我們看看具體的html頁面、service實作和JDBC的操作,
login.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>登錄</title> <!--<link rel="stylesheet" type="text/css" href="https://www.cnblogs.com/css/common.css" />--> </head> <body> <div> <h2>用戶登錄</h2> </div> <form th:action="@{/user/login}" method="post"> <div> <!--/*@thymesVar id="error" type=""*/--> <span id="basic-addon0"> </span> <span style="font-size: 12px;color: red" th:text="${error}" aria-describedby="basic-addon0"></span> <br /> </div> <div> <span id="basic-addon1">用戶名</span> <input id="user_name" name="userName" type="text" placeholder="用戶名" aria-describedby="basic-addon1" th:field="*{userName}"/> </div> <br /> <div> <span id="basic-addon2">密 碼</span> <input id="password" name="password" type="password" placeholder="密 碼" aria-describedby="basic-addon2" th:field="*{password}"/> </div> <br /> <div> <button type="submit" style="width:95px;">登 錄</button> <a href="/user/register">注冊</a> </div> </form> </body> </html>
我們通過瀏覽器訪問:http://localhost:8080/user/login,進入到登錄頁面,URL地址映射到@GetMapping("/login")方法
/** *登錄頁面 */ @GetMapping("/login") public ModelAndView login(ModelAndView modelAndView){ modelAndView.setViewName("login"); return modelAndView; }
回傳login.html頁面,瀏覽器展示用戶登錄頁面

在登錄頁面填寫用戶名和密碼后,點擊“登錄”按鈕,

由于login.html中,from的method=“POST”,所以“注冊”按鈕會映射到@PostMapping("/login")方法
/**
*登錄
*/
@PostMapping("/login")
public ModelAndView login(ModelAndView modelAndView,@Valid UserVo userVo, BindingResult bindingResult){
//效驗入參
if(bindingResult.hasErrors()){
modelAndView.addObject("error",bindingResult.getFieldError().getDefaultMessage());
modelAndView.setViewName("login");
return modelAndView;
}
//效驗用戶
User user = new User();
user.setName(userVo.getUserName());
user.setPassword(userVo.getPassword());
User rstUser = userService.queryByNameAndPassword(user);
if(null == rstUser){
modelAndView.addObject("error","用戶名或密碼錯誤!");
modelAndView.setViewName("login");
}
//展示首頁
modelAndView.addObject("userName",rstUser.getName());
modelAndView.setViewName("redirect:/user/index");
return modelAndView;
}
通過@Valid注解打開了表單校驗,所以如果有引數不符合開始宣告的校驗規則,會引數錯誤Errors,如果有引數錯誤,會回傳登錄頁面,并顯示錯誤,如果沒有錯誤,將會呼叫UserService的queryByNameAndPassword方法
/** * 通過用戶名和密碼查詢用戶 */ @Override public User queryByNameAndPassword(User user) { return jdbcTemplate.queryForObject("select id, name, password from t_user where name = ? and password = ?", this::mapRowToUser, user.getName(), user.getPassword()); } ? private User mapRowToUser(ResultSet rs, int rowNum) throws SQLException { return new User(rs.getLong("id"), rs.getString("name"), rs.getString("password")); }
通過jdbcTemplate的queryForObject方法即可查詢到資料,然后重定向redirect到首頁index.html,
/** *首頁 */ @GetMapping("/index") public ModelAndView index(ModelAndView modelAndView, HttpServletRequest request){ modelAndView.addObject("userName",request.getParameter("userName")); modelAndView.setViewName("index"); return modelAndView; }
inde.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>登錄</title> <!--<link rel="stylesheet" type="text/css" href="https://www.cnblogs.com/css/common.css" />--> </head> <body> <div> <br /> <span>歡迎你</span> <span style="font-size: 12px;color: black" th:text="${userName}" aria-describedby="basic-addon0"></span> </div> </body> </html>
登錄成功界面

8.用戶串列查詢功能詳解
從第4點UserController,我們可以看到用于用戶串列查詢的請求有:@GetMapping("/userList"),下面我們看看具體的html頁面、service實作和JDBC的操作,
userList.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>用戶資訊</title> <!--<link rel="stylesheet" type="text/css" href="https://www.cnblogs.com/css/common.css" />--> <style type="text/css"> table { border: 1px solid black; text-align: center; border-collapse: collapse; } table thead th { border: 1px solid black; } table tbody td { border: 1px solid black; } </style> </head> <body> <div> <h2>用戶串列</h2> </div> <table cellpadding="0" cellspacing="0"> <thead> <th>序號</th> <th>編碼</th> <th>用戶名</th> </thead> <tbody> <tr th:each="entries,stat:${userList}" th:style="' color: rgb(17, 119, 0);">> <td th:text="${stat.count}"></td> <td th:text="${entries['id']}"></td> <td th:text="${entries['name']}"></td> <td th:text="${entries['sage']}"></td> </tr> </tbody> </table> </body> </html>
我們通過瀏覽器訪問:http://localhost:8080/user/userList,進入到登錄頁面,URL地址映射到@GetMapping("/userList")方法
/** * 查詢用戶串列 */ @GetMapping("/userList") public ModelAndView queryAll(ModelAndView modelAndView){ //查詢用戶串列 List<Map<String, Object>> userList = userService.queryAll(); //回傳 modelAndView.addObject("userList", userList); modelAndView.setViewName("userList"); return modelAndView; }
呼叫UserService的queryAll方法
/** * 查詢用戶串列 */ @Override public List<Map<String, Object>> queryAll() { return jdbcTemplate.queryForList("select id, name, password from t_user"); }
通過jdbcTemplate的queryForList方法即可查詢到資料,然后回傳到userList.html頁面上,

總結
Spring對JDBC的支持主要是使用JdbcTemplate,雖然JdbcTemplate將創建連接、創建陳述句、關閉連接、關閉結果集和sql例外處理等做了很好的封裝,但是還有待完善,下一節我們再聊聊更簡單的JPA,
原始碼地址:https://github.com/kinglead2012/myblog
create table t_user( id bigint not null auto_increment comment 'id:主鍵', name varchar(20) not null comment '姓名', password varchar(20) not null comment '密碼', primary key (id));
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/48263.html
標籤:Java
