[GDSC] Spring Introduction(백엔드 스터디)

백엔드 취준생·2022년 11월 20일
0
package com.example.springintroduction.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig {

    // 빈 등록 , 비밀번호 암호화
    @Bean
    public PasswordEncoder getPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

@configuration = @Been을 등록할 때 사용하는 어노테이션 (설정파일의 느낌이 난다.)

@Bean = 스프링에 의하여 생성되고 관리되는 자바 객체

package com.example.springintroduction.controller;

import com.example.springintroduction.member.Member;
import com.example.springintroduction.member.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.net.URI;
import java.net.URISyntaxException;

@Controller
@RequiredArgsConstructor
public class LoginController {

    private final MemberService memberService;

    @GetMapping("/signin")
    public String signInPage(Model model){
        Member member = new Member();
        model.addAttribute("member",member);
        return "signin";
    }

    @PostMapping("/signin")
    public ResponseEntity signIn(@ModelAttribute Member member, HttpServletRequest request) throws URISyntaxException {
        // 비밀번호 검사
        memberService.validate(member);
        // 세션 생성
        HttpSession session =  request.getSession();
        session.setAttribute("sessionUsername",member.getUsername());
        return ResponseEntity.status(HttpStatus.FOUND).location(new URI("/")).build();

    }

    @GetMapping("/signup")
    public String signUpPage(Model model){
        model.addAttribute(new Member());   // member
        return "signup";
    }

    @PostMapping("signup")
    public String signUp(@ModelAttribute @Valid Member member, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return "signup";
        }

        memberService.save(member);
        return "redirect:/#signup=ok";      //# 은 없어도 되나 보기 편하기위해 해놓은거
    }

    @PostMapping("/signout")
    public String signOut(HttpServletRequest request){
        request.getSession().invalidate();
        return "redirect:/";
    }
}

@RequiredArgsConstructor = 어떠한 빈에 생성자가 오직 하나만 있고, 생성자의 파라미터 타입이 빈으로 등록 가능한 존재라면 이 빈은 @Autowired 어노테이션 없이도 의존성 주입을 가능하게 해준다.

package com.example.springintroduction.controller;

import com.example.springintroduction.member.Member;
import com.example.springintroduction.member.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Queue;

@Controller
@RequiredArgsConstructor
public class MainController {

    private final MemberService memberService;

    @GetMapping("/")
    public String mainPage(Model model, @RequestParam(required = false) String query){

        if(query == null){
            List<Member> members = memberService.findAll();
            model.addAttribute("members",members);
            return "home";
        }

        List<Member> members = memberService.findByUsername(query);
        model.addAttribute("members",members);
        return "home";
    }

    // 더미 데이터 생성
    @PostConstruct
    public void createdDummyDate(){
        memberService.save(new Member("상남자","1234"));
        memberService.save(new Member("하남자","1234"));
    }

    @GetMapping("/formembers")
    public String forMembers(HttpServletRequest request){

        // 파라미터 false로 하면, 기존 세션이 유효할 경우만 해당 세션을 가져옴
        HttpSession session =  request.getSession(false);

        if( session == null || session.getAttribute("sessionUsername") == null){
            // 미인증 사용자 홈 화면으로 강제 이동
            return "redirect:/";
        }

        return  "formembers";
    }
}

@PostConstruct = 종속성 주입이 완료된 후 실행되어야 하는 메서드에 사용된다. 이 어노테이션은 다른 리소스에서 호출되지 않아도 수행된다.

package com.example.springintroduction.member;


import lombok.*;
import org.hibernate.validator.constraints.Length;


@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Member {
    @Length(min = 2, max = 8, message = "2~8자 사이로 하세요")
    private  String username;

    @Length(min = 2, max = 8, message = "2~8자 사이로 하세요")
    private String password;

}

@Data가 아닌 @Setter, @Getter 을 사용하는 이유 = @Data를 사용하면 @Getter, @Setter , @ToString, @EqualsAndHashCode, @RequiredArgsConstructor 를 사용하는 거와 같다. 그러면 필요없는 어노테이션을 무분별하게 사용하게 되어 stackoverflow가 발생할 수 있다. 상황에 맞게 사용하는 게 중요하다.

package com.example.springintroduction.member;

import org.springframework.stereotype.Repository;

import java.util.*;

@Repository
public class MemberRepository {

    // DB
    public static Map<String,Member> memberMap = new HashMap<>();

    // Member 저장
    public void save(Member member){
        memberMap.put(member.getUsername(),member);
    }

    // 멤버 모두 조회
    public List<Member> findAll(){
        Collection<Member> values = memberMap.values();
        return new ArrayList<>(values);
    }

    //이름으로 찾기
    public List<Member> findByUsername(String username){
        return List.of(memberMap.get(username));
    }

}

@Repository = 해당 클래스를 루트 컨테이너에 빈 객체를 생성해주는 어노테이션

package com.example.springintroduction.member;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class MemberService {

    private final MemberRepository memberRepository;
    private final PasswordEncoder passwordEncoder;

    public void save(Member member){
        String encodedPassword =  passwordEncoder.encode(member.getPassword());
        member.setPassword(encodedPassword);

        memberRepository.save(member);
    }

    //전체 조회
    public List<Member> findAll(){
        return memberRepository.findAll();
    }

    // 이름으로 단건 조회
    public List<Member> findByUsername(String username){
        return memberRepository.findByUsername(username);
    }

    // 로그인 시도한 회원정보 검증
    public void validate(Member member){
        Member foundMember =MemberRepository.memberMap.get(member.getUsername());
        // 사용자가 입력한 비밀번호가 암호화된 DB상 비밀번호와 일치하는지 검사
        if(!passwordEncoder.matches(member.getPassword(),foundMember.getPassword())){
            throw new IllegalArgumentException("비밀번호 틀림");
        }
    }
}

@Service = 해당 클래스를 루트 컨테이너에 빈 객체를 생성해주는 어노테이션

profile
코딩하는 대학생

0개의 댓글