
👉 Mybatis 게시판 복사
👉 삭제, 다시 설치하는게 낫다(열면 자동 설치)
package com.MyBatisBorder;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
public interface BorderService {
public List<BorderDTO> list();
public BorderDTO view(String id);
public int write(BorderDTO bbsDto);
public int delete(String id);
public int allCount();
}
package com.MyBatisBorder;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface IBorderDAO {
public List<BorderDTO> listDao();
public BorderDTO viewDao(String id);
public int writeDao(BorderDTO bbsDto);
public int deleteDao(String id);
public int allCount();
}
package com.MyBatisBorder;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public class BorderServiceImpl implements BorderService{
@Autowired
IBorderDAO dao;
@Override
public List<BorderDTO> list(){
return dao.listDao();
};
@Override
public BorderDTO view(String id){
return dao.viewDao(id);
};
@Override
public int write(BorderDTO bbsDto){
return dao.writeDao(bbsDto);
};
@Override
public int delete(String id){
return dao.deleteDao(id);
};
@Override
public int allCount(){
return dao.allCount();
};
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.MyBatisBorder.IBorderDAO">
<select id="listDao" resultType="com.MyBatisBorder.BorderDTO">
select * from simple_bbs order by id desc
</select>
<select id="viewDao" resultType="com.MyBatisBorder.BorderDTO">
select * from simple_bbs where id = #{id}
</select>
<insert id="writeDao">
insert into simple_bbs(writer, title, content) values(#{writer}, #{title}, #{content})
</insert>
<delete id="deleteDao">
delete from simple_bbs where id = #{id}
</delete>
<select id="allCount" resultType="_int">
select count(*) from simple_bbs
</select>
</mapper>
package com.MyBatisBorder;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class BorderController {
//@Autowired // 자식인 객체
//IBorderDAO dao;
@Autowired
BorderService borderService;
@RequestMapping("/")
// Service vs DAO
public String root(){
return "redirect:list";
}
@RequestMapping("/list")
public String userListPage(Model model){
model.addAttribute("list", borderService.list());
int nTotalCount = borderService.allCount();
System.out.println("Count : " + nTotalCount);
return "list";
}
@RequestMapping("/view")
public String view(@RequestParam("id") String id, Model model){
model.addAttribute("dto", borderService.view(id));
return "view";
}
@RequestMapping("/writeForm")
public String writeForm(){
return "writeForm"; // 화면만 나온다
}
@RequestMapping(value = "/write", method = RequestMethod.POST) // POST 방식으로 보낸다
public String write(Model model, BorderDTO bbsDto){ //HttpRequest 필요없이 BBSDto에 담으면 된다
borderService.write(bbsDto);
return "redirect:list";
}
/* @RequestMapping("/write")
public String write(Model model, HttpServletRequest request){
dao.writeDao(request.getParameter("writer"),
request.getParameter("title"),
request.getParameter("content"));
return "redirect:list";
}*/
@RequestMapping("/delete")
public String delete(@RequestParam("id") String id){
int nResult = borderService.delete(id);
System.out.println("Delete : " + nResult);
return "redirect:list";
}
}




@Service는 에러 발생시 앞의 명령문을 아예 실행하지 않고 트랜잭션을 이용하여 롤백을 하기위한 주석 같은 것이다. 서비스는 컨트롤러와 같은 형태의 인터페이스를 컨트롤러에서 사용하여 트랜잭션 하는 것이고 DB에 접근 할 땐 원래의 컨트롤러로 접근하는 것이다.
Spring DAO란?, DTO란?, VO란?, DTO vs VO, DTO vs Domain, DAO vs Repository
create table tran1(
id varchar(20),
amount int);
create table tran2(
id varchar(20),
amount int);
create table tran3(
id varchar(20),
amount int);
insert into tran1 value('1', 100);
insert into tran2 value('1', 100);
insert into tran3 value('1', 100);
commit;
delete from tran1;
delete from tran2;
delete from tran3;
commit;
select * from tran1;
select * from tran2;
select * from tran3;

👉 실행은 잘 됐지만 말하고 싶은건 commit 하는 순간 delete 명령을 실행 👉 충돌 👉 트랜잭션을 통한 롤백을 하고 싶은 것이다.

👉 이제 설정 알아서 하자. 전에 거 복붙

package com.TransactionX.DTO;
import lombok.Data;
@Data
public class Transaction1Dto {
private String consumerId;
private int amount;
}
package com.TransactionX.DAO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface Transaction1Dao {
public void pay(String consumerId, int amount);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.TransactionX.DAO.Transaction1Dao">
<insert id="pay">
insert into tran1(id, amount)
values(#{param1}, #{param2})
</insert>
</mapper>
package com.TransactionX.SERVICE;
public interface IBuyTicketService {
public int buy(String consumerId, int amount, String error);
}
package com.TransactionX.SERVICE;
import com.TransactionX.DAO.Transaction1Dao;
import com.TransactionX.DAO.Transaction2Dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BuyTicketService implements IBuyTicketService {
@Autowired
Transaction1Dao transaction1Dao; // 인터페이스 Dao1
@Autowired
Transaction2Dao transaction2Dao; // 인터페이스 Dao2
@Override
public int buy(String consumerId, int amount, String error) {
try {
transaction1Dao.pay(consumerId, amount);
// 1번 의도적 에러 발생
if (error.equals("1")) {
int n = 10 / 0; // 0 에러
}
transaction2Dao.pay(consumerId, amount);
return 1;
/*
if(nResult == 1){
return "buy_ticket_end";
}
else {
return "buy_ticket_error";
}
*/
} catch (Exception e) {
return 0;
}
}
}
package com.TransactionX;
import com.TransactionX.SERVICE.IBuyTicketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@Autowired
IBuyTicketService iBuyTicketService;
@RequestMapping("/")
public @ResponseBody String root(){
return "Transaction X (1)";
}
@RequestMapping("/buy_ticket")
public String buy_ticket(){
return "buy_ticket";
}
@RequestMapping("/buy_ticket_card")
public String buy_ticket_card(@RequestParam("consumerId") String consumerId,
@RequestParam("amount") String amount,
@RequestParam("error") String error,
Model model)
{
int nResult = iBuyTicketService.buy(consumerId, Integer.parseInt(amount), error);
model.addAttribute("consumerId", consumerId);
model.addAttribute("amount", amount);
if(nResult == 1){
return "buy_ticket_end";
}
else {
return "buy_ticket_error";
}
}
}
<%@ 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 lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>카드 결제</p>
<form action="buy_ticket_card">
고객 아이디 : <input type="text" name="consumerId"> <br />
티켓 구매수 : <input type="text" name="amount"> <br />
에러 발생 여부 : <input type="text" name="error" value="0"> <br />
<input type="submit" value="구매"> <br />
</form>
<hr>
에러 발생 여부에 1을 입력하면 에러가 발생합니다.
</body>
</html>
<%@ 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 lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
<title>Document</title>
</head>
<body>
buy_ticket_end.jsp 입니다. <br />
${consumerId } <br />
${amount } <br />
</body>
</html>
<%@ 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 lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
<title>Document</title>
</head>
<body>
buy_ticket_error.jsp 입니다. <br />
<h1>에러가 발생했습니다.</h1> <br />
${consumerId } <br />
${amount } <br />
</body>
</html>









👉 0을 입력 했을 때 error가 발생하지 않으므로 1과 2 둘다 정상적으로 입력되지만, 1을 입력 했을 때 error 가 발생하기 전에 1에 입력이 되고 error가 발생하기 때문에 2는 실행이 되지 않는다
복붙

package com.TransactionX.SERVICE;
import com.TransactionX.DAO.Transaction1Dao;
import com.TransactionX.DAO.Transaction2Dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
@Service
public class BuyTicketService implements IBuyTicketService {
@Autowired
Transaction1Dao transaction1Dao; // 인터페이스 Dao1
@Autowired
Transaction2Dao transaction2Dao; // 인터페이스 Dao2
@Autowired
PlatformTransactionManager transactionManager; // 👉 추가
@Autowired
TransactionDefinition definition; // 👉 추가
@Override
public int buy(String consumerId, int amount, String error) {
TransactionStatus status = transactionManager.getTransaction(definition); // 👉 추가
try{
transaction1Dao.pay(consumerId, amount);
// 1번 의도적 에러 발생
if(error.equals("1")) {
int n = 10 / 0; // 0 에러
}
transaction2Dao.pay(consumerId, amount);
transactionManager.commit(status); // 👉 추가
return 1;
/*
if(nResult == 1){
return "buy_ticket_end";
}
else {
return "buy_ticket_error";
}
*/
}catch (Exception e){
System.out.println("롤백"); // 👉 추가
transactionManager.rollback(status); // 👉 추가
return 0;
}
}
}









👉 롤백

👉 0을 입력 했을 때 error가 발생하지 않으므로 commit으로 1과 2 둘다 정상적으로 입력되지만, 1을 입력 했을 때 error 가 발생하기 전에 1에 입력이 되고 error가 발생 후 transactionManager.rollback 에 의해 2는 실행하지 않고 롤백이 되어 데이터가 아예 입력 되지 않는다.
복붙, 알아서 하자

package com.TransactionX.SERVICE;
import com.TransactionX.DAO.Transaction1Dao;
import com.TransactionX.DAO.Transaction2Dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Service
public class BuyTicketService implements IBuyTicketService {
@Autowired
Transaction1Dao transaction1Dao; // 인터페이스 Dao1
@Autowired
Transaction2Dao transaction2Dao; // 인터페이스 Dao2
/*@Autowired
PlatformTransactionManager transactionManager;
@Autowired
TransactionDefinition definition;*/
@Autowired
TransactionTemplate transactionTemplate; // 👉 추가
@Override
public int buy(String consumerId, int amount, String error) {
//TransactionStatus status = transactionManager.getTransaction(definition); // 👉 추가
try{
// 처음 보는 형태, 메소드 안에 메소드?? 👉 메소드가 아니고 재정의이다
// 추상화 클래스(생성자 객체) {추상화 객체 재정의}, 객체를 만들면서 정의한다. 자바스크립트(Node.js)에서 많이 보이는 표현
// 즉, 추상화 클래스도 단발성이지만 객체를 만들 수 있다
transactionTemplate.execute(new TransactionCallbackWithoutResult() { // 👉 추가
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) { // 👉 자동 으로 추가 됨
transaction1Dao.pay(consumerId, amount);
// 1번 의도적 에러 발생
if(error.equals("1")) {
int n = 10 / 0; // 0 에러
}
transaction2Dao.pay(consumerId, amount);
}
});
//transactionManager.commit(status);
return 1;
}catch (Exception e){
System.out.println("Template ROLLBACK"); // 👉 수정
//transactionManager.rollback(status);
return 0;
}
}
}









👉 트랜잭션 매니저와 같은 구조이다. 다만 매니저는 commit이 있지만 템플릿 구조엔 없다
트랜잭션이 중첩된 상황
트랜잭션: 오늘 일기 작성하기
(1)오늘 날씨 데이터를 가져와서
(2)일기를 DB에 저장하기
(1)과 (2)를 모두 수행해야 데이터베이스의 상태가 변화하므로,(1)+(2)를 하나의 트랜잭션이라고 본다.
(1)은 트랜잭션 ⭕, (2)는 트랜잭션 ❌ 👉 (1)에의해 트랜잭션에 묶이는 상황이라면 👉 (1)과 (2)를 묶은 트랜잭션 A가 생기고 (1)의 트랜잭션은 B가 된다. 왜? 불안하니까..
(1)과 (2)에서 문제생기든 A와 B에 문제생기든 무조건 롤백!
이전 프로젝트에 이어서 작성
package com.TransactionX.DTO;
import lombok.Data;
@Data
public class Transaction3Dto {
private String consumerId;
private int amount;
}
package com.TransactionX.DAO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface Transaction3Dao {
public void pay(String consumerId, int amount);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.TransactionX.DAO.Transaction2Dao">
<insert id="pay">
insert into tran3(id, amount)
values(#{param1}, #{param2})
</insert>
</mapper>
package com.TransactionX.SERVICE;
import com.TransactionX.DAO.Transaction1Dao;
import com.TransactionX.DAO.Transaction2Dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Service
public class BuyTicketService { // 👉 implements 제거
@Autowired
Transaction1Dao transaction1Dao; // 인터페이스 Dao1
@Autowired
Transaction2Dao transaction2Dao; // 인터페이스 Dao2
@Autowired
TransactionTemplate transactionTemplate;
public int buy(String consumerId, int amount, String error) {
try{
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
transaction1Dao.pay(consumerId, amount);
// 1번 의도적 에러 발생
if(error.equals("1")) {
int n = 10 / 0; // 0 에러
}
transaction2Dao.pay(consumerId, amount);
}
});
//transactionManager.commit(status);
return 1;
}catch (Exception e){
System.out.println("[Transaction Propagation # 2] ROLLBACK"); // 👉 수정
return 0;
}
}
}
package com.TransactionX.SERVICE;
import com.TransactionX.DAO.Transaction3Dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LogWriteService {
@Autowired
Transaction3Dao transaction3Dao; // 인터페이스 Dao3
public int write(String consumerId, int amount){
try {
transaction3Dao.pay(consumerId, amount);
return 1;
}catch (Exception e){
return 0;
}
}
}
package com.TransactionX.SERVICE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Service
public class BuyAndLogService {
@Autowired
BuyTicketService buyTicketService;
@Autowired
LogWriteService logWriteService;
@Autowired
TransactionTemplate transactionTemplate;
public int buy(String consumerId, int amount, String error) {
try{
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
buyTicketService.buy(consumerId, amount, error);
// 2번 의도적 에러 발생
if(error.equals("2")) {
int n = 10 / 0; // 0 에러
}
logWriteService.write(consumerId, amount);
}
});
//transactionManager.commit(status);
return 1;
}catch (Exception e){
System.out.println("[Transaction Propagation # A] ROLLBACK"); // 👉 수정
return 0;
}
}
}
에러 발생 여부에 2을 입력하면 에러가 발생합니다.
package com.TransactionX;
import com.TransactionX.SERVICE.BuyAndLogService;
import com.TransactionX.SERVICE.IBuyTicketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
//@Autowired
//IBuyTicketService iBuyTicketService;
@Autowired
BuyAndLogService buyAndLogService;
@RequestMapping("/")
public @ResponseBody String root(){
return "Transaction Propagation (4)";
}
@RequestMapping("/buy_ticket")
public String buy_ticket(){
return "buy_ticket";
}
@RequestMapping("/buy_ticket_card")
public String buy_ticket_card(@RequestParam("consumerId") String consumerId,
@RequestParam("amount") String amount,
@RequestParam("error") String error,
Model model)
{
// int nResult = iBuyTicketService.buy(consumerId, Integer.parseInt(amount), error);
int nResult = buyAndLogService.buy(consumerId, Integer.parseInt(amount), error);
model.addAttribute("consumerId", consumerId);
model.addAttribute("amount", amount);
if(nResult == 1){
return "buy_ticket_end";
}
else {
return "buy_ticket_error";
}
}
}
REQUIRED
Default속성- 기본적으로 부모 트랜잭션이 있으면 부모 트랜잭션에 종속
- 부모 트랜잭션이 없을 경우에는 새로운 트랜잭션 생성
REQUIRES_NEW
- 부모 트랜잭션을 무시하고 무조건 새로운 트랜잭션 생성
- 부모 트랜잭션은 현재 트랜잭션이 종료될 때 까지 대기상태로 존재
- 자기 트랜잭션에서 예외가 발생해
Rollback이 진행돼도 부모 트랜잭션에Rollback이 전파되지 않는다.- 부모 트랜잭션에서 예외가 발생해
Rollback이 진행돼도 자기 트랜잭션에Rollback이 전파되지 않는다.SUPPORTS
- 부모 트랜잭션이 있을 때만 해당 부모 트랜잭션에 종속
- 부모 트랜잭션이 없으면 트랜잭션이 적용되지 않는다.
NOT_SUPPORTED
- 부모 트랜잭션이 있으면 부모 트랜잭션을 대기시키고 트랜잭션 없이 실행
- 부모 트랜잭션이 없으면 트랜잭션 없이 실행된다.
MANDATORY
- 부모 트랜잭션이 있을 때만 해당 부모 트랜잭션에 종속
- 부모 트랜잭션이 없으면 예외가 발생한다.
NEVER
- 트랜잭션이 적용되면 안되는 경우에 사용
- 부모 트랜잭션이 있으면 예외가 발생한다.
- 부모 트랜잭션이 없으면 트랜잭션 없이 실행된다.
NESTED
- 부모 트랜잭션이 있으면 새로운 트랜잭션 생성
REQUIRED_NEW와는 다르다.- 부모 트랜잭션의 커밋과 롤백에는 영향을 받지만 자신의 커밋과 롤백은 부모 트랜잭션에게 영향을 주지 않는다.
- 자식 트랜잭션이 실패하면 부모 트랜잭션은
Rollback되지 않는다.- 부모 트랜잭션이 실패하면 자식 트랜잭션은
Rollback된다.
@Autowired
TransactionTemplate transactionTemplate;
@Transactional(propagation = Propagation.REQUIRED) // 👉 추가
public int buy(String consumerId, int amount, String error) {
try{
transactionTemplate.execute(new TransactionCallbackWithoutResult() {



👉 셋다 들어감



👉 롤백 2개 출력, 데이터는 당연히 들어가지 않았다



👉 BuyAndLogService 에서 에러발생, 롤백 1개 출력
@Transactional(propagation = Propagation.REQUIRES_NEW)






👉 롤백 2개 출력



👉 BuyAndLogService 에러, 롤백 1개 출력

👉 Dao1, Dao2

👉 Dao3
Spring 시큐리티 이걸 왜 만들었을까? 👉 개발자 편하라고.. 개발에 집중하라고..
암호화(암호화 키로 평문을 암호화 한다),복호화(암호화된 값을 키로 평문으로 바꾼다),해쉬(비밀번호 1234 👉 23578aergerg2352uj3iruoe 로 변형)등을 쉽게 할 수 있다.
스프링시큐리티의 기본 개념과 구조

👉 Spring Security 의존성 추가, 나머지 설정 알아서
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.0'
compileOnly 'jakarta.servlet:jakarta.servlet-api:6.0.0'
implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.1'
implementation 'org.apache.tomcat:tomcat-jasper:10.1.16'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-jdbc:3.2.0'
implementation 'mysql:mysql-connector-java:8.0.33'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'
}

❗ 책의 내용으로 작성하면 안된다. 2022년에 바뀜
package com.Security.auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
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.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.access.expression.WebExpressionAuthorizationManager;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/").permitAll()
.requestMatchers("/css/**", "/js/**", "/img/**").permitAll()
.requestMatchers("/guest/**").permitAll()
.requestMatchers("/member/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(formLogin -> formLogin.permitAll())
.logout(logout -> logout.permitAll());
return http.build();
}
// @Autowired
// public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth.inMemoryAuthentication()
// .withUser("user").password(passwordEncoder().encode("1234")).
// roles("USER")
// .and()
// .withUser("admin").password(passwordEncoder().encode("1234")).
// roles("ADMIN");
// // ROLE_ADMIN 에서 ROLE_는 자동으로 붙는다
// }
//
// // passwordEncoder() 추가
// @Bean
// public PasswordEncoder passwordEncoder(){
// return new BCryptPasswordEncoder();
// }
//
//}
}
package com.Security;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RequestMapping("/")
public @ResponseBody String root(){
return "Security (1)";
}
@RequestMapping("/guest/welcome")
public String welcome1(){
return "guest/welcome1";
}
@RequestMapping("/member/welcome")
public String welcome2(){
return "member/welcome2";
}
@RequestMapping("/admin/welcome")
public String welcome3(){
return "admin/welcome3";
}
}
<%@ 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 lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
<title>Document</title>
</head>
<body>
Welcome : Guest
</body>
</html>