Github : projectquestion
4. Basic Project
4. 3 . Cart & Product
Cart table : This table stores customer's cart. It includes fields for the unique identifier (`cnum`), product list (`cproductList`), customer information (`cccustomer`), and creation timestamp (`cdate`).
Product table : This table stores products to carts. It includes fields the unique identifier ('pcode'), cart's object (`pcart`), product name (`pname`), product specification (`pspec`), product price (`pprice`), customer's object ('pcustomer'), and creation timestamp ('pdate').
With this setup, each cart and its corresponding products are stored in separate tables, allowing for efficient management of carts and products.
Here's a detailed list of the topics
- 4.3.1 Basic Cart Project:
- 4.3.2 Project Configuration:
4.3.1 Basic Cart Project:
4.3.2 Project Configuration:
spring.application.name=cartexam
# Database Setting
spring.datasource.dbcp2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/cartexam
spring.datasource.username=root
spring.datasource.password=1111
# JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
create Database
Spring Secuity Setup
create Customer.java
package com.example.cartexam.customer;
import java.time.LocalDateTime;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
@Data
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer cid;
@Column(unique = true)
private String username; // for SpringSecurity Policy
private String password; // for SpringSecurity Policy
private boolean enabled; // for SpringSecurity Policy
private String role; // for SpringSecurity Policy
@Column(unique = true)
private String cemail;
private String cimage;
private LocalDateTime cdate;
}
create SecurityConfig.java Class
package com.example.cartexam.customer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
.requestMatchers(new AntPathRequestMatcher("/**")).permitAll())
.formLogin((formLogin) -> formLogin
.loginPage("/signin")
.defaultSuccessUrl("/")
)
.logout((logout) -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/signout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true))
;
return http.build();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
create CustomerRepository.java
package com.example.cartexam.customer;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CustomerRepository extends JpaRepository<Customer, Integer> {
Optional<Customer> findByusername(String username); // login check
}
CustomerService.java
package com.example.cartexam.customer;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class CustomerService implements UserDetailsService {
@Autowired
private CustomerRepository customerRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Customer> tcustomer = customerRepository.findByusername(username);
if (tcustomer.isEmpty()) {
throw new UsernameNotFoundException("You need to Sign up first...");
}
Customer customer = tcustomer.get();
List<GrantedAuthority> authorities = new ArrayList<>();
if ("ROLE_USER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
} else if ("ROLE_MANAGER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_MANAGER"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
return new User(customer.getUsername(), customer.getPassword(), authorities);
}
public void create(Customer customer) {
customer.setEnabled(true);
customer.setRole("ROLE_USER"); //ROLE_ADMIN, ROLE_MANAGER, ROLE_PAID...
customer.setCdate(LocalDateTime.now());
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
customer.setPassword(passwordEncoder.encode(customer.getPassword()));
customerRepository.save(customer);
}
}
CustomerController.java
package com.example.cartexam.customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class CustomerController {
@Autowired
private CustomerService customerService;
@GetMapping("/")
public String signup() {
return "signup";
}
@PostMapping("/signup")
public String signup(Customer customer) {
customerService.create(customer);
return "signup";
}
@GetMapping("/signin")
public String signin(){
return "signin";
}
}
Views
signup.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<span sec:authorize="isAnonymous()">Signin First...<a href="/signin">Sign in</a></span>
<span sec:authorize="isAuthenticated()">Welcome...<span th:text="${#authentication.name}"></span>
<span th:text="${#authentication.authorities}"></span>
<a href="/signout">Sign out</a>
</span>
<form action="/signup" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>ID : <input type="text" name="username">
<p>PW : <input type="password" name="password">
<p>Mail : <input type="text" name="cemail">
<p><input type="submit" value="Sign up">
</form>
</body>
</html>
signin.html
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="/signin" method="post">
<div th:if="${param.error}">
<div class="alert alert-danger">
Please, Check your ID or Password...
</div>
</div>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>ID : <input type="text" name="username">
<p>PW : <input type="password" name="password">
<p><input type="submit" value="Sign in">
</form>
</body>
</html>
4.3.3 Cart C,R,U,D:
Cart Table : This table is a cart for purchasing products . It can include the following fields:
- `cid`: The unique identifier for each cart, typically auto-generated as a number or UUID.
- `cnum`: In terms of meaning 'cid' and 'cnum' could be considered simiar, but 'cnum' is utilized as a unique code.
- `ccustomer`: A field storing information about the user, often set up as a foreign key relationship with another user table. For example, it can contain the user's OBJECT.
- 'cproduct': A object field list indicating which product is related to the cart. This relates to the `pcart` field in the Product table.
- `cdate`: A field storing the timestamp when the cart was created.
Cart.java
package com.example.cartexam.cart;
import java.time.LocalDateTime;
import java.util.List;
import com.example.cartexam.customer.Customer;
import com.example.cartexam.product.Product;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import lombok.Data;
@Data
@Entity
public class Cart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer cid;
@Column(length = 200)
private String cnum;
@OneToMany(mappedBy = "pcart", cascade = CascadeType.REMOVE)
private List<Product> cproduct;
@ManyToOne
private Customer ccustomer;
private LocalDateTime cdate;
}
CartRepository.java
package com.example.cartexam.cart;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CartRepository extends JpaRepository<Cart, Integer> {
}
CartService.java & CartServiceImpl.java
package com.example.cartexam.cart;
import java.security.Principal;
import java.util.List;
public interface CartService {
void create(Cart question, Principal principal);
List<Cart> readlist();
Cart readdetail(Integer cid);
void update(Cart cart);
void delete(Integer cid);
}
package com.example.cartexam.cart;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import com.example.cartexam.customer.Customer;
import com.example.cartexam.customer.CustomerRepository;
@Service
public class CartServiceImpl implements CartService {
@Autowired
private CartRepository cartRepository;
@Autowired
private CustomerRepository customerRepository;
@Override
public void create(Cart cart, Principal principal) {
cart.setCdate(LocalDateTime.now());
Optional<Customer> tc = customerRepository.findByusername(principal.getName());
cart.setCcustomer(tc.get());
cartRepository.save(cart);
}
@Override
public List<Cart> readlist() {
return cartRepository.findAll();
}
@Override
public Cart readdetail(Integer cid) {
Optional<Cart> tq = cartRepository.findById(cid);
return tq.get();
}
@Override
public void update(Cart cart) {
cartRepository.save(cart);
}
@Override
public void delete(Integer cid) {
Optional<Cart> tq = cartRepository.findById(cid);
cartRepository.delete(tq.get());
}
}
CartController.java
package com.example.cartexam.cart;
import java.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RequestMapping("/question")
@Controller
public class CartController {
@Autowired
private CartService cartService;
@GetMapping("/create")
public String create() {
return "cart/create";
}
@PostMapping("/create")
public String create(Cart cart, Principal principal) {
cartService.create(cart, principal);
return "redirect:/cart/readlist";
}
@GetMapping("/readlist")
public String readlist(Model model) {
model.addAttribute("carts", cartService.readlist());
return "cart/readlist";
}
@GetMapping("/readdetail/{cid}")
public String readdetail(@PathVariable("cid") Integer cid,
Model model) {
model.addAttribute("cart", cartService.readdetail(cid));
return "cart/readdetail";
}
}
create.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<span sec:authorize="isAnonymous()">Signin First...<a href="/signin">Sign in</a></span>
<span sec:authorize="isAuthenticated()">Welcome...<span th:text="${#authentication.name}"></span>
<span th:text="${#authentication.authorities}"></span>
<a href="/signout">Sign out</a>
</span>
<form action="/question/create" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>Title : <input type="text" name="qtitle">
<p>Content : <input type="password" name="qcontent">
<p><input type="submit" value="submit">
</form>
<p><a href="/question/readlist">Question List</a>
</body>
</html>
readlist.html
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<h2> Read List </h2>
<a href="/question/create">CREATE</a><br><br>
<th:block th:each="question: ${questions}">
[[${question.qid}]] /
<a th:href="@{|/question/readdetail/${question.qid}|}" th:text="${question.qtitle}"></a>
/ [[${question.qauthor.username}]] / [[${question.qdate}]]<br>
</th:block>
</body>
</html>
readdetail.html
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<h2> Read Detail </h2>
<a href="/question/readlist">List</a><br><br>
[[${question.qid}]] <br>
[[${question.qtitle}]]<br>
[[${question.qauthor.username}]] <br>
[[${question.qdate}]]<br>
</body>
</html>
ㅅㄷㄴㅅ
4.1.4 Answer with Question:
Answer Table : This table stores answers to each question on the question board. It can have the following fields:
- `aid`: The unique identifier for each answer, typically auto-generated as a number or UUID.
- `aquestion`: A object field indicating which question the answer is related to. This relates to the `qanswer` field in the Question table.
- `acontent`: A string field containing the content of the answer.
- `aauthor`: A field storing information about the user who posted the answer, often set up as a foreign key relationship with another user table.
- `adate`: A field storing the timestamp when the answer was posted.