Spring Properties
API KEY 를 프로퍼티로 설정한 후 호출하는 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| /**
* application.yml에 값 추가
*/
open-api:
key: API-key값 입력
/**
* Properties Class 생성
*/
@Data
@Component
@ConfigurationProperties("open-api") // 설정파일의 이름과 동일하게 입력
public class OpenApiProperties {
private String key;
}
/**
* 사용할 클래스에서 @RequiredArgsConstructor로 선언 후 사용
*/
@RestController
@RequiredArgsConstructor
public class ApiExtraController {
private final OpenApiProperties openApiProperties;
@GetMapping("/api/extra/air")
public String air(@RequestBody AirInput airInput) {
String url = "https://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty?serviceKey=%s&pageNo=1&sidoName=%s&ver=1.0";
String apiResult = "";
String key = openApiProperties.getKey();
try {
URI uri = new URI(String.format(url, key, URLEncoder.encode(airInput.getSearchSido(), StandardCharsets.UTF_8)));
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
apiResult = restTemplate.getForObject(uri, String.class);
} catch (Exception e) {
log.debug(e.getMessage());
}
return apiResult;
}
}
|
이메일 전송 설정
build.gradle
1
2
| // Spring Boot Starter Mail(이메일 전송 라이브러리)
implementation 'org.springframework.boot:spring-boot-starter-mail:3.2.3'
|
application.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
| spring:
mail:
host: smtp.gmail.com //SMTP 서버 호스트
port: 587 // SMTP 서버 포트
username: uj.mail.send@gmail.com //발신자 이메일
password: cobnqvncqckvcutn //발신자 앱 비밀번호
properties:
mail:
smtp:
auth: true // 사용자 인증 시도 여부(기본값 false)
starttls:
enable: true //StartTLS 활성화 여부(기본값 false)
|
MailComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| @Slf4j
@Component
@RequiredArgsConstructor
public class MailComponent {
private final JavaMailSender javaMailSender;
public boolean send(String fromEmail, String fromName,
String toEmail, String toName,
String title, String contents) {
boolean result = false;
MimeMessagePreparator mimeMessagePreparator = mimeMessage -> {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
InternetAddress from = new InternetAddress();
from.setAddress(fromEmail);
from.setPersonal(fromName);
InternetAddress to = new InternetAddress();
to.setAddress(toEmail);
to.setPersonal(toName);
mimeMessageHelper.setFrom(from);
mimeMessageHelper.setTo(to);
mimeMessageHelper.setSubject(title);
mimeMessageHelper.setText(contents, true);
};
try {
javaMailSender.send(mimeMessagePreparator);
result = true;
} catch (Exception e) {
log.info(e.getMessage());
}
return result;
}
}
|
이메일 전송
Q1) 회원가입시 가입된 회원에게 가입 메일을 전송하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| @RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberService memberService;
@PostMapping("/api/public/member")
public ResponseEntity<?> addMember(@RequestBody MemberInput memberInput) {
ServiceResult result = memberService.addMember(memberInput);
return ResponseResult.result(result);
}
}
public interface MemberService {
ServiceResult addMember(MemberInput memberInput);
}
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
private final MailComponent mailComponent;
@Override
public ServiceResult addMember(MemberInput memberInput) {
Optional<Member> optionalMember = memberRepository.findByEmail(memberInput.getEmail());
if (optionalMember.isPresent()) {
throw new BizException("이미 가입된 이메일 입니다.");
}
String encryptedPassword = PasswordUtils.encryptedPassword(memberInput.getPassword());
Member member = Member.builder()
.email(memberInput.getEmail())
.memberName(memberInput.getMemberName())
.regDate(LocalDateTime.now())
.password(encryptedPassword)
.phone(memberInput.getPhone())
.status(MemberStatus.Using)
.build();
memberRepository.save(member);
// 메일을 전송
String fromEmail = "admin@gmail.com";
String fromName = "관리자";
String toEmail = member.getEmail();
String toName = member.getMemberName();
String title = "회원가입을 축하드립니다.";
String contents = "회원가입을 축하드립니다.";
mailComponent.send(fromEmail, fromName, toEmail, toName, title, contents);
return ServiceResult.success();
}
}
|
Q2) 비밀번호 초기화를 위해서 이메일로 인증코드를 전송하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
| @RestController
@RequiredArgsConstructor
public class ApiMemberController {
private final MemberRepository memberRepository;
@PostMapping("/api/public/member/password/reset")
public ResponseEntity<?> resetPassword(
@RequestBody @Valid MemberPasswordResetInput input, Errors errors) {
if (errors.hasErrors()) {
return ResponseResult.fail("입력값이 정확하지 않습니다.", ResponseError.of(errors.getAllErrors()));
}
ServiceResult result = null;
try {
result = memberService.resetPassword(input);
} catch (BizException e) {
return ResponseResult.fail(e.getMessage());
}
return ResponseResult.result(result);
}
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MemberPasswordResetInput {
@Email(message = "이메일 형식이 아닙니다.")
@NotBlank(message = "이메일은 필수 입력 사항입니다.")
private String email;
@NotBlank(message = "이름은 필수 입력 사항입니다.")
private String memberName;
}
public interface MemberService {
ServiceResult resetPassword(MemberPasswordResetInput memberPasswordResetInput);
}
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
private final MailComponent mailComponent;
private final MailTemplateRepository mailTemplateRepository;
@Override
public ServiceResult resetPassword(MemberPasswordResetInput input) {
Optional<Member> optionalMember = memberRepository.findByEmailAndMemberName(
input.getEmail(), input.getMemberName());
if (optionalMember.isEmpty()) {
throw new BizException("회원 정보가 존재하지 않습니다.");
}
Member member = optionalMember.get();
String passwordResetKey = UUID.randomUUID().toString();
member.setPasswordResetYn(true);
member.setPasswordResetKey(passwordResetKey);
memberRepository.save(member);
String serverUrl = "http://localhost:8080";
Optional<MailTemplate> optionalMailTemplate = mailTemplateRepository.findByTemplateId("MEMBER_PASSWORD_RESET");
optionalMailTemplate.ifPresent(e -> {
String fromEmail = e.getSendEmail();
String fromMemberName = e.getSendMemberName();
String title = e.getTitle().replaceAll("\\{MEMBER_NAME\\}", member.getMemberName());
String contents = e.getContents().replaceAll("\\{MEMBER_NAME\\}", member.getMemberName()
.replaceAll("\\{SERVER_URL\\}", serverUrl)
.replaceAll("\\{RESET_PASSWORD_KEY\\}", passwordResetKey));
mailComponent.send(fromEmail, fromMemberName, member.getEmail(), member.getMemberName(), title, contents);
});
return ServiceResult.success();
}
}
|
Q3) 게시판에 글을 작성했을 때 사용자에게 작성된 글의 정보를 메일로 전송하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| /**
* 기존 글쓰기 로직에 추가
*/
@Service
@RequiredArgsConstructor
public class BoardServiceImpl implements BoardService {
private final BoardTypeRepository boardTypeRepository;
private final BoardRepository boardRepository;
private final MemberRepository memberRepository;
private final MailComponent mailComponent;
private final MailTemplateRepository mailTemplateRepository;
@Override
public ServiceResult add(String email, BoardInput boardInput) {
Optional<Member> optionalMember = memberRepository.findByEmail(email);
if (optionalMember.isEmpty()) {
throw new BizException("회원 정보가 존재하지 않습니다.");
}
Member member = optionalMember.get();
Optional<BoardType> optionalBoardType = boardTypeRepository.findById(boardInput.getBoardType());
if (optionalBoardType.isEmpty()) {
return ServiceResult.fail("게시판 정보가 존재하지 않습니다.");
}
BoardType boardType = optionalBoardType.get();
Board board = Board.builder()
.member(member)
.title(boardInput.getTitle())
.contents(boardInput.getContents())
.boardType(boardType)
.regDate(LocalDateTime.now())
.build();
boardRepository.save(board);
//메일 전송 로직
Optional<MailTemplate> optionalMailTemplate = mailTemplateRepository.findByTemplateId("BOARD_ADD");
optionalMailTemplate.ifPresent(e -> {
String fromEmail = e.getSendEmail();
String fromMemberName = e.getSendMemberName();
String title = e.getTitle().replaceAll("\\{MEMBER_NAME\\}", member.getMemberName());
String contents = e.getContents().replaceAll("\\{BOARD_TITLE\\}", board.getTitle())
.replaceAll("\\{BOARD_CONTENTS\\}", board.getContents());
mailComponent.send(fromEmail, fromMemberName, member.getEmail(), member.getMemberName(), title, contents);
});
return ServiceResult.success();
}
}
|
Q4) 문의 게시판이 글에 답변을 달았을 때 메일로 답변 정보를 전송하는 API를 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
| @Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BoardReplyInput {
private String replyContents;
}
@RequiredArgsConstructor
@RestController
public class ApiAdminBoardController {
private final BoardService boardService;
@PostMapping("/api/admin/board/{id}/reply")
public ResponseEntity<?> reply(@PathVariable Long id,
@RequestBody BoardReplyInput boardReplyInput) {
ServiceResult result = boardService.replyBoard(id, boardReplyInput);
return ResponseResult.result(result);
}
}
public interface BoardService {
ServiceResult replyBoard(Long id, BoardReplyInput boardReplyInput);
}
@Service
@RequiredArgsConstructor
public class BoardServiceImpl implements BoardService {
private final BoardRepository boardRepository;
private final MailComponent mailComponent;
private final MailTemplateRepository mailTemplateRepository;
@Override
public ServiceResult replyBoard(Long id, BoardReplyInput boardReplyInput) {
Optional<Board> optionalBoard = boardRepository.findById(id);
if (optionalBoard.isEmpty()) {
return ServiceResult.fail("게시글이 존재하지 않습니다.");
}
Board board = optionalBoard.get();
board.setReplyContents(boardReplyInput.getReplyContents());
boardRepository.save(board);
// 메일 전송
Optional<MailTemplate> optionalMailTemplate = mailTemplateRepository.findByTemplateId("BOARD_REPLY");
optionalMailTemplate.ifPresent(e -> {
String fromEmail = e.getSendEmail();
String fromMemberName = e.getSendMemberName();
String title = e.getTitle().replaceAll("\\{MEMBER_NAME\\}", board.getMember().getMemberName());
String contents = e.getContents().replaceAll("\\{BOARD_TITLE\\}", board.getTitle())
.replaceAll("\\{BOARD_CONTENTS\\}", board.getContents())
.replaceAll("\\{BOARD_REPLY_CONTENTS\\}", board.getReplyContents());
mailComponent.send(fromEmail, fromMemberName,
board.getMember().getEmail(), board.getMember().getMemberName(), title, contents);
});
return ServiceResult.success();
}
}
|
Q5) 스프링 스케쥴러를 이용하여 매일 새벽4시에 로그정보를 삭제하는 기능을 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| public interface LogService {
void deleteLog();
}
@RequiredArgsConstructor
@Service
public class LogServiceImpl implements LogService {
private final LogsRepository logsRepository;
@Override
public void deleteLog() {
logsRepository.deleteAll();
}
}
@Component
@RequiredArgsConstructor
public class Scheduler {
private final LogService logService;
@Scheduled(cron = "0 0 4 * * *")
public void deleteLog() {
logService.deleteLog();
}
}
@EnableAspectJAutoProxy //AOP
@EnableScheduling //Schedule
@SpringBootApplication
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
|
Q6) 스프링 스케쥴러를 이용하여 회원중 가입일이 1년이 도래한 회원에 대해서
서비스 통지 메일을 보내는 기능을 작성해 보세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| public interface MemberService {
void sendServiceNotice();
}
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
private final MailComponent mailComponent;
private final MailTemplateRepository mailTemplateRepository;
@Override
public void sendServiceNotice() {
Optional<MailTemplate> optionalMailTemplate = mailTemplateRepository.findByTemplateId("MEMBER_SERVICE_NOTICE");
optionalMailTemplate.ifPresent(e -> {
String fromEmail = e.getSendEmail();
String fromMemberName = e.getSendMemberName();
String contents = e.getContents();
memberRepository.findAll().forEach(u -> {
String title = e.getTitle().replaceAll("\\{MEMBER_NAME\\}", u.getMemberName());
mailComponent.send(fromEmail, fromMemberName, u.getEmail(), u.getMemberName(), title, contents);
});
});
}
}
@Component
@RequiredArgsConstructor
public class Scheduler {
private final MemberService memberService;
@Scheduled(cron = "0 0 0 1 1 *")
public void sendServiceNotice() {
memberService.sendServiceNotice();
}
}
|
이메일 전송메세지를 DB에 템플릿 형태로 저장
Entity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| @Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class MailTemplate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String templateId;
private String title;
private String contents;
private String sendEmail;
private String sendMemberName;
private LocalDateTime regDate;
}
|
Repository
1
2
3
4
| @Repository
public interface MailTemplateRepository extends JpaRepository<MailTemplate, Long> {
Optional<MailTemplate> findByTemplateId(String templateId);
}
|
SQL Query
1
2
3
4
5
6
7
| INSERT INTO MAIL_TEMPLATE(TEMPLATE_ID, TITLE, CONTENTS, SEND_EMAIL, SEND_MEMBER_NAME, REG_DATE)
VALUES ('MEMBER_PASSWORD_RESET', '{MEMBER_NAME}님의 비밀번호 초기화 요청입니다.',
'<div><p>{MEMBER_NAME}님 안녕하세요</p><p>아래 링크를 클릭하여, 비밀번호를 초기화 해주세요.</p><p><a href="{SERVER_URL}/reset?key={RESET_PASSWORD_KEY}">초기화</a></p></div>',
'uj.mail.send@gmail.com', '관리자', '2022-02-02 01:12:20.000000'),
('BOARD_ADD', '{MEMBER_NAME}님이 글을 게시하였습니다.',
'<div><p>제목 : {BOARD_TITLE}</p><p>내용</p><div>{BOARD_CONTENTS}</div></div>',
'uj.mail.send@gmail.com', '관리자', '2022-02-02 01:12:20.000000');
|
댓글남기기