에러발생 equest processing failed; nested exception is java.lang.NullPointerException: Cannot invoke “com.itwillbs.domain.MemberVO.getUserid()” because “returnVO” is null
따라서 if(returnVO.getUserid() != null) return "redirect:/main"; 대신 if(returnVO != null) return "redirect:/main"; 사용한다.
@Controller @RequestMapping(value = "/member/*") publicclassMemberController{ //3-1. 서비스 처리 객체를 주입(DI) @Inject private MemberService service; privatestaticfinal Logger l = LoggerFactory.getLogger(MemberController.class); /* 회원가입 처리하는 동작 */ //insert라는 하나의 주소로 get과 post방식 즉 입력과 출력 둘 다 처리 가능
// http://localhost:8088/test/insert // http://localhost:8088/test/member/insert // http://localhost:8088/member/insert @RequestMapping(value = "/insert", method = RequestMethod.GET) //value="/member/insert"에서 member를 빼도 됨 public String insertGET()throws Exception { l.info("C: 회원가입 입력페이지 GET"); return"/member/insertMember"; } @RequestMapping(value = "/insert", method = RequestMethod.POST) //value="/member/insertPro"에서 member를 빼도 됨 public String insertPOST(MemberVO vo)throws Exception{ //1. 한글처리 : request객체가 없다 => web.xml에서 filter태그로 인코딩해야한다. //2. 전달된 파라미터 받기 //request.getParameter라는 내장객체가 없다. 따라서 메서드의 매개변수를 통해 가져올 수 있다. //l.info("C: "+ request.getParameter()); 에러발생 l.info("C: "+ vo); //3. 서비스객체 생성(직접생성안하고 의존주입) //3-2. 서비스객체호출 service.insertMember(vo); l.info("C: 회원가입 처리페이지 POST"); //4. 로그인페이지로 이동(주소줄과 view페이지 동시에 insert->login 변경되어야함) return"redirect:/member/login"; } /* 로그인 기능 */ // http://localhost:8088/member/login
@RequestMapping(value = "/login", method = RequestMethod.GET) public String loginGET()throws Exception{ l.info("C: 로그인 입력페이지 GET"); return"/member/loginForm"; } @RequestMapping(value = "/login", method = RequestMethod.POST) //public String loginPOST(@ModelAttribute("userid") String id, @ModelAttribute("userpw") String pw) throws Exception{ public String loginPOST(MemberVO vo, HttpSession session, RedirectAttributes rttr)throws Exception{ l.info("C: 로그인 처리페이지 POST"); //1.한글처리 => web.xml에서 완료 //2.전달받은 파라미터 저장 => loginPOST()메서드의 파라미터값으로 저장함. l.info("C: "+ vo.getUserid() + vo.getUserpw()); //3.서비스객체생성 => 22번째 코드로 의존주입완료 //4.서비스 로그인 체크 동작(HttpSession) MemberVO returnVO = service.loginMember(vo); l.info("C: 리턴VO결과(서비스에서 예외처리를 진행했으므로 null이 출력되면 코드에 문제있다는 의미) "+returnVO); //5.메인페이지로 이동(주소줄과 view페이지 동시에 main으로 변경되어야함) // 해당 정보 있는 경우 : => main페이지로 이동 //if(returnVO.getUserid() != null) { //에러가 발생하는 이유: if(returnVO != null) { //5.세션값생성 session.setAttribute("id", returnVO.getUserid()); //RedirectAttributes의 addAttribute메서드 사용해보려고 했으나 실패. 에러 발생 //Map<String, Object> map = new HashMap<String, Object>(); //map.put("username", returnVO.getUsername()); //map.put("useremail", returnVO.getUseremail()); //rttr.addAttribute("mvo", map); rttr.addFlashAttribute("mvo", returnVO); //l.info("C: 모델에 뭐 들어있니?"+model); return"redirect:/member/main"; } else { // 해당 정보 없는 경우 : => login페이지로 이동 return"redirect:/member/login"; } }//end of loginPOST() }
publicinterfaceMemberService{ // 회원 가입 (일반회원가입테이블에 sns계정 컬럼 추가하기) // 일반적으로는 DAO랑 같은 메소드명을 사용하여 일관성을 유지한다 publicvoidinsertMember(MemberVO vo); // 로그인기능 DAO랑 같은 이름으로 하지않은이유? 이름이 달라도 메서드생성가능하다는 걸 보여주기 위해서. // public MemberVO readMemberWithIDPW(String userid,String userpw) throws Exception; // 로그인기능 public MemberVO loginMember(MemberVO vo); }
MemberServiceImpl.java 인터페이스 오버라이딩 메서드 구현
예외처리를 VO객체로 할 수 있다.
catch구문안에 returnVO = null;을 넣어 실행하다 문제가 생겼을때 해당 데이터를 보내지않겠다는 의미로 예외처리를 할 수 있다.
//DB와 연결 (의존주입) @Inject private MemberDAO mdao; //회원가입 @Override publicvoidinsertMember(MemberVO vo){ //컨트롤러 -> 서비스 호출 -> DAO 호출 -> Mapper -> DB System.out.println("S : 회원가입동작"); if(vo == null) { //처리 return; } mdao.insertMember(vo); }
//로그인기능 @Override public MemberVO loginMember(MemberVO vo){ System.out.println("S : 컨트롤러에서 호출받으면 필요한 정보를 받아서 DAO로 전달"); MemberVO returnVO = null; try { returnVO = mdao.readMemberWithIDPW(vo.getUserid(), vo.getUserpw()); } catch (Exception e) { e.printStackTrace(); returnVO = null; //실행하다 문제가 생겼을때 해당 데이터를 보내지않겠다는 의미 = 예외처리 } return returnVO; //null이 반환되면 앞의 코드가 문제가 있다는 것을 바로 알수있다. } }
MemberDAO.java 인터페이스생성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import com.itwillbs.domain.MemberVO;
publicinterfaceMemberDAO{ //해당 도메인에 관련된 기능 선언 public String getTime();
//C: 회원가입 publicvoidinsertMember(MemberVO vo);
//R: 회원 정보 조회 - 사용자 ID 해당하는 정보 가져오기 public MemberVO readMember(String userid)throws Exception;
//R: 회원 정보 조회 - ID,PW정보에 해당하는 사용자 정보 public MemberVO readMemberWithIDPW(String userid,String userpw)throws Exception; }
@Override public String getTime(){ String result = sqlSession.selectOne(namespace+".getTime"); //괄호안에 쿼리구문입력하기 return result; }
//회원가입구현 -> memberMapper.xml 작성 후 아래 메서드 작성 -> MemberDAOtest.java 이동 @Override publicvoidinsertMember(MemberVO vo){ System.out.println("#####"); sqlSession.insert(namespace+".insertMember", vo); //괄호안은 (쿼리구문, 매개변수)순으로 입력하기 }
//회원 정보 조회-사용자 ID 해당하는 정보 가져오기 @Override public MemberVO readMember(String userid)throws Exception { //테스트(컨트롤러) 호출 -> 정보를 저장 -> DB로이동 MemberVO vo = sqlSession.selectOne(namespace+".readMember", userid); //괄호안의 물음표를 콤마뒤에 쓰는거임 return vo; }
//인터페이스 선언 -> 서브클래스 구현 //회원 정보 조회 - ID,PW정보에 해당하는 사용자 정보 @Override public MemberVO readMemberWithIDPW(String userid, String userpw)throws Exception { //테스트(컨트롤러) 호출 -> 정보를 저장 -> DB로이동
//String인자를 2개를 가져갈 수 없기때문에 파라미터 두개를 객체인 Map에 넣어서 가지고 넘긴다 //return sqlSession.selectOne(namespace+".readMemberWithIDPW", userid, userpw);
// DB로 정보를 전달하기 위해서는 sqlSeesion 객체 활용 // * 1개 이상의 정보를 전달할때는 객체 단위로 전달 // * 객체(VO) 안에 저장이 안되는 정보의 경우 Map을 사용 // Map은 key-value형태 : 이때 key값은 sql구문의 #{ㅇㅇㅇ} 이름과 같아야함
<!-- values(?,?,?,?) sql문법 대신에 Mybatis 문법#{}을 사용 get() 또는 set() 마이바티스가 결정해서 메서드실행--> <insertid="insertMember"> insert into tbl_member(userid,userpw,username,useremail) values (#{userid},#{userpw},#{username},#{useremail}) </insert>
<selectid="readMember"resultType="com.itwillbs.domain.MemberVO"> select * from tbl_member where userid=#{userid} </select>
<selectid="readMemberWithIDPW"resultType="com.itwillbs.domain.MemberVO"> select * from tbl_member where userid=#{userid} and userpw=#{userpw} </select>