# SpringBoot 3/26 上課內容
###### tags: `SpringBoot`
[老師雲端](https://onedrive.live.com/?authkey=%21AOSC5VqK5wFJeuk&id=AF483E7E8FEC387B%218460&cid=AF483E7E8FEC387B)

# 58 Spring Boot 動態網站開發實務

# 59 Spring Boot 動態網站開發實務

[Spring Data JPA](https://docs.spring.io/spring-data/jpa/docs/2.4.6/reference/html/#repositories.namespace-reference)
## Spring Boot 動態網站開發實務

# 60 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 61 Spring Boot 動態網站開發實務

# 62 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 63 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 64 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 65 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

* 要寫在最上面 .authorizeRequests()
* .authenticated()要驗證
# 66 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 67 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 68 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 69 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 70 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

* 加密後的密碼(2000)
# 71 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 72 Spring Boot 動態網站開發實務

* UserNotFoundException = 自訂Exception
## Spring Boot 動態網站開發實務

# 73 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 74 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 75 Spring Boot 動態網站開發實務

# 76 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 77 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 78 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 79 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

* 新增 查詢
# 80 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# 81 Spring Boot 動態網站開發實務


# 82 Spring Boot 動態網站開發實務

* 呼叫

## Spring Boot 動態網站開發實務

# 83 Spring Boot 動態網站開發實務

## Spring Boot 動態網站開發實務

# (重要) 88 Spring Boot 動態網站開發實務

# <font color="green">------------實作部份------------</font>
#### sql table
```clike=
USE LeonPower
create table Users(
id int not null primary key identity(1,1),
name nvarchar(50) not null
);
insert into Users(name) Values('mary');
insert into Users(name) Values('john');
insert into Users(name) Values('judy');
insert into Users(name) Values('louis');
insert into Users(name) Values('karen');
select*from Users
```
#### Users.java
```clike=
package tw.leonchen.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.stereotype.Component;
@Entity
@Table(name = "users")
@Component
public class Users {
@Id @Column(name = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "NAME")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```
#### UsersRepository.java (interface)
```clike=
package tw.leonchen.model;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface UsersRepository extends JpaRepository<Users, Integer> {
@Query(value = "from Users Where name like concat('%', ?1, '%')",nativeQuery = false)
public List<Users> findUsers(String name);
public List<Users> findByNameLike(String name);
@Query(value = "Select * From Users",nativeQuery = true)
public List<Users> findAll();
}
```
#### UsersService.java
```clike=
package tw.leonchen.model;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@Transactional
public class UsersService {
@Autowired
private UsersRepository usersRepository;
public List<Users> findUsers(String name){
return usersRepository.findUsers(name);
}
public List<Users> findUsersLike(String name){
return usersRepository.findByNameLike(name);
}
public List<Users> findAll(){
return usersRepository.findAll();
}
}
```
#### UsersController.java
```clike=
package tw.leonchen.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import tw.leonchen.model.Users;
import tw.leonchen.model.UsersRepository;
import tw.leonchen.model.UsersService;
@RestController
public class UsersController {
@Autowired
private UsersRepository usersRepository;
@Autowired
private UsersService uService;
@GetMapping("/findusersbyname,controller")
public List<Users> processFindUsersByName(){
return usersRepository.findUsers("ma");
}
@GetMapping("/findusersbynamelike.controller")
public List<Users> processFindUsersByNameLike(@RequestParam(name = "name")String name){
return usersRepository.findByNameLike("%" + name + "%");
}
@GetMapping("/findallusers.controller")
public List<Users> processFindAllUsers(){
return uService.findAll();
}
}
```
#### Postman

#### pom.xml

```clike=
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
```
#### WebSecurityConfig.java

```clike=
package tw.leonchen.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
//import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import tw.leonchen.model.AuthUserDetailsService;
@EnableWebSecurity //忽略管控
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
//路徑都要驗證 可多個路徑 payment底下都要驗證
.antMatchers(HttpMethod.GET,"/users/**","/payment/**").authenticated()
.antMatchers(HttpMethod.GET).permitAll()
.antMatchers(HttpMethod.POST,"/users/**","/payment/**").authenticated()
.antMatchers(HttpMethod.POST).permitAll()
//除了上面 任何請求都要驗證
.anyRequest().authenticated()
.and()
.rememberMe().tokenValiditySeconds(86400).key("remember-me")
.and()
//不要管我
.csrf().disable()
.formLogin().loginPage("/login/page")
.defaultSuccessUrl("/login/welcome");
}
}
```
#### application.properties
```clike=
#spring security default username and password
spring.security.user.name=user
spring.security.user.password=test123
```
#### login.jsp
```clike=
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form action="/login/page" method="post">
<table>
<tr>
<td>UserName:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="remember-me">RememberMe
</td>
</tr>
<tr>
<td colspan="2">
<button type="submit" value="login">Login</button>
</td>
</tr>
</table>
</form>
</body>
</html>
```
#### welcome.jsp
```clike=
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Welcome</title>
</head>
<body>
Welcome
</body>
</html>
```
#### WebAppConfig.java


```clike=
package tw.leonchen.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login/page").setViewName("login");
registry.addViewController("/login/welcome").setViewName("welcome");
registry.addViewController("/logout/page").setViewName("logout");
registry.addViewController("/logout").setViewName("logoutResult");
}
}
```
#### logout.jsp
```clike=
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Logout</title>
</head>
<body>
<form action="/logout" method="post">
<table>
<tr>
<td>Logout</td>
<td><button type="submit" value="logout">Logout</button></td>
</tr>
</table>
</form>
</body>
</html>
```
#### logoutResult.jsp
```clike=
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>LogoutResult</title>
</head>
<body>
You've already logout<br/>
</body>
</html>
```
#### sql table UserProfiles
```clike=
create table UserProfiles(
id int not null primary key identity(1000,1),
name nvarchar(50)not null,
emailAddress nvarchar(50) not null,
password nvarchar(2000)not null
)
加密後的密碼(2000)
編碼 不能解碼
nvarchar最多4000字
varchar最多8000字
select * from UserProfiles
```
#### UserProfiles.java
```clike=
package tw.leonchen.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.stereotype.Component;
@Entity
@Table(name = "userprofiles")
@Component
public class UserProfiles {
@Id @Column(name = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "NAME")
private String name;
@Column(name = "EMAILADDRESS")
private String emailAddress;
@Column(name = "PASSWORD")
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
```
#### UserProfilesRepository.java(interface)
```clike=
package tw.leonchen.model;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserProfilesRepository extends JpaRepository<UserProfiles, String> {
public Optional<UserProfiles> findByName(String name);
}
```
#### UserNotFoundException.java


```clike=
package tw.leonchen.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public UserNotFoundException() {
}
public UserNotFoundException(String message) {
super(message);
}
}
```
#### UserProfilesService.java
```clike=
package tw.leonchen.model;
import java.util.Optional;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tw.leonchen.exception.UserNotFoundException;
@Service
@Transactional
public class UserProfilesService {
@Autowired
private UserProfilesRepository userProfilesRepository;
public UserProfiles getByName(String name) {
Optional<UserProfiles> uRep = userProfilesRepository.findByName(name);
//重要
if(uRep.isEmpty()) {
throw new UserNotFoundException("Can't find User");
}
return uRep.get();
}
public UserProfiles createUserProfiles(UserProfiles userProfiles) {
return userProfilesRepository.save(userProfiles);
}
}
```
#### UserProfilesController.java
```clike=
package tw.leonchen.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import tw.leonchen.model.UserProfiles;
import tw.leonchen.model.UserProfilesService;
@RestController
public class UserProfilesController {
@Autowired
private UserProfilesService userProfilesService;
@PostMapping("/userProfilesCreate.controller")
public UserProfiles processCreateUser(@RequestBody UserProfiles uProfiles) {
String bcEncode1 = new BCryptPasswordEncoder().encode(uProfiles.getPassword());
uProfiles.setPassword(bcEncode1);
return userProfilesService.createUserProfiles(uProfiles);
}
}
```
#### AuthUserDetailsService.java
```clike=
package tw.leonchen.model;
import java.util.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class AuthUserDetailsService implements UserDetailsService {
@Autowired
private UserProfilesService userProfilesService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserProfiles uProfiles = userProfilesService.getByName(username);
return new User(uProfiles.getName(), uProfiles.getPassword(), Collections.emptyList());
}
}
```
#### sql table Product

* 查詢200筆會有以下的圖

```clike=
create table Product(
id int not null primary key identity(10000,1),
pname nvarchar(50)not null,
price int not null,
pdate date not null,
note nvarchar(200)not null
);
select * from Product
insert into Product(pname,price,pdate,note) values('NB',25000,'2021-03-26','Good to use');
insert into Product(pname,price,pdate,note) values('MobilePhone',18000,'2021-03-27','contact');
insert into Product(pname,price,pdate,note) values('Banana',10,'2021-03-26','yummy');
insert into Product(pname,price,pdate,note) values('Drink',80,'2021-04-16','sweet');
insert into Product(pname,price,pdate,note) values('Apple',50,'2021-05-08','Health');
insert into Product(pname,price,pdate,note) values('客家資策會',1,'2020-01-01','bad');
```
#### Product.Java
```clike=
package tw.leonchen.product.model;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonFormat;
@Entity @Table(name = "product")
public class Product {
@Id @Column(name = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "PNAME")
private String pname;
@Column(name = "PRICE")
private int price;
@Column(name = "QUANTITY")
private int quantity;
@Column(name = "PDATE")
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private Date pdate;
@Column(name = "NOTE")
private String note;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Date getPdate() {
return pdate;
}
public void setPdate(Date pdate) {
this.pdate = pdate;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
```
#### ProductRepository.java(interface)
```clike=
package tw.leonchen.product.model;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProductRepository extends JpaRepository<Product, Integer> {
}
```
#### ProductService.java
```clike=
package tw.leonchen.product.model;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public Product findById(Integer id) {
Optional<Product> pRep = productRepository.findById(id);
if(pRep.isPresent()) {
return pRep.get();
}
return null;
}
public List<Product> findAll(){
return productRepository.findAll();
}
public Page<Product> findAllByPage(Pageable pageable){
return productRepository.findAll(pageable);
}
}
```
#### ProductController.java
```clike=
package tw.leonchen.product.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import tw.leonchen.product.model.Product;
import tw.leonchen.product.model.ProductService;
@Controller
@RequestMapping(path = "/product")
@SessionAttributes(names = { "totalPages", "totalElements" })
public class ProductController {
@Autowired
private ProductService pService;
//顯示分頁
@GetMapping("/productqueryMainPage.controller")
public String processQueryMainPage() {
return "product/productQueryAll";
}
//直接顯示全部
@PostMapping("/queryallproduct.controller")
@ResponseBody
public List<Product> queryAllProduct() {
return pService.findAll();
}
//分頁
@PostMapping("/queryallproductByPage.controller/{pageNo}")
@ResponseBody
public List<Product> queryAllProductByPage(@PathVariable(name = "pageNo") int pageNo, Model m) {
int pageSize = 2;
Pageable pageable = PageRequest.of(pageNo-1, pageSize);
Page<Product> page = pService.findAllByPage(pageable);
int totalPages = page.getTotalPages();
long totalElements = page.getTotalElements();
m.addAttribute("totalPages", totalPages);
m.addAttribute("totalElements", totalElements);
return page.getContent();
}
}
```
#### productQuery.jsp
```clike=
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Product Query</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript">
var indexPage = 1;
$(document).ready(function(){
load(indexPage);
});
function change(page){
indexPage = page;
load(indexPage);
}
function load(indexPage){
$.ajax({
type:'post',
url:'/product/queryallproductByPage.controller/' + indexPage,
dataType:'JSON',
contentType:'application/json',
success: function(data) {
var json = JSON.stringify(data, null, 4);
console.log("SUCCESS : ", json);
var parsedObjinArray = JSON.parse(json);
$('#showproduct').empty(""); //清空table內的資料
if(json=null){
$('table').prepend("<tr><td colspan='2'>暫無資料</td></tr>");
}else{
var table = $('#showproduct');
table.append("<tr id='ptitle'><th>ID</th><th>Product Name</th><th>ProductPrice</th><th>Date</th><th>Note</th></tr>");
$.each(parsedObjinArray,function(i,n){
var tr = "<tr align='center'>" + "<td>" + n.id + "</td>" +
"<td>" + n.pname + "</td>" + "<td>" + n.price + "</td>" +
"<td>" + n.pdate + "</td>" + "<td>" + n.note + "</td>" +
"</tr>";
table.append(tr);
});
}
},
error: function() {
console.log("error");
}
});
}
</script>
<style type="text/css">
table {
margin: auto;
width: 70%
}
#ptitle {
background-color: orange;
}
#productListTitle {
margin: auto;
font-size: 25px;
font-weight: bold;
text-align: center;
}
</style>
</head>
<body>
<div id="productListTitle">ProductQuery</div>
<table id="showproduct" border="1">
</table>
<table id="showpage">
<tr>
<td>Total Pages:${totalPages} Total Records:${totalElements}</td>
<td colspan="3" align="right">Previous <c:forEach var="i"
begin="1" end="${totalPages}" step="1">
<button id="myPage" value="${i}" onclick="change(${i})">${i}</button>
</c:forEach>Next
</td>
</tr>
</table>
</body>
</html>
```