유효성 검사를 통해 회원가입을 하는 방법이다. 회원가입을 할때 이용약관의 동의를 해야 넘어가지고, 이메일이 맞는지, 아이디가 존재하는 지 등 유효성 검사를 거친 후 회원가입이 완료 된다. 복잡하지만 복잡하지 않는 듯한 느낌. Validator를 이용해서 유효성 검사를 할 것이다. hibernate로 유효성 검사를 할 수도 있다. 아마 hibernate가 더 간단할 것이다. 다음에 hibernate로 유효성 검사를 하여 회원가입하는 것도 만들어 봐야지!
하나의 기능이 구현되는 순서는 기본적으로 Controller -> Service -> ServiceImp -> DAO -> SQL(XML) -> JSP 이다.
1) DB 생성 (MySQL)
1
2
3
4
5
6
7
8
9
10
11
12
|
CREATE TABLE `user` (
`IDX` int(11) NOT NULL AUTO_INCREMENT,
`ID` varchar(45) NOT NULL,
`EMAIL` varchar(100) NOT NULL,
`NAME` varchar(45) NOT NULL,
`PASSWORD` varchar(45) NOT NULL,
`GRADE` int(11) DEFAULT '0',
`REGDATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`IDX`),
UNIQUE KEY `EMAIL_UNIQUE` (`EMAIL`),
UNIQUE KEY `ID_UNIQUE` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
|
cs |
2) 파일 및 패키지 생성
2-1. UserController.java 생성
1
2
3
4
5
6
7
|
package tody.lovely.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
}
|
cs |
- 5행 : @Controller를 등록해야 한다.
2-2. UserVO.java 생성
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
|
package tody.lovely.vo;
import java.util.Date;
public class UserVO {
private int IDX;
private String ID;
private String EMAIL;
private String NAME;
private String PASSWORD;
private int GRADE;
private Date REGDATE;
public int getIDX() {
return IDX;
}
public void setIDX(int iDX) {
IDX = iDX;
}
public String getID() {
return ID;
}
public void setID(String iD) {
ID = iD;
}
public String getEMAIL() {
return EMAIL;
}
public void setEMAIL(String eMAIL) {
EMAIL = eMAIL;
}
public String getNAME() {
return NAME;
}
public void setMAME(String nAME) {
NAME = nAME;
}
public String getPASSWORD() {
return PASSWORD;
}
public void setPASSWORD(String pASSWORD) {
PASSWORD = pASSWORD;
}
public int getGRADE() {
return GRADE;
}
public void setGRADE(int gRADE) {
GRADE = gRADE;
}
public Date getREGDATE() {
return REGDATE;
}
public void setREGDATE(Date rEGDATE) {
REGDATE = rEGDATE;
}
}
|
cs |
- 7~13행 : DB 필드들을 선언한다.
- 15~26행 : Getter/Setter를 만든다. Alt+Shift+S를 눌러서 Generate Getters and Setters로 쉽게 만들 수 있다.
VO는 Value Object의 약자로써 read only 속성을 가진다. DB의 필드들을 Getter/Setter 메소드 조합으로 형성된 클래스이다. DB의 정보를 담고 보내주는 역할을 한다. DTO라는 이름으로 사용하는 사람들도 있다. VO와 DTO는 거의 비슷한, 똑같은 개념이긴 하다. 두 개를 구분하라면 구분할 순 있지만, 비슷한 개념이다. 불변성이냐 아니냐의 차이이다. VO나 DTO를 쓰지않고 Map만 사용하는 사람들도 있다. 편한 걸로 쓰면 된다.
2-3. UserService.java 생성
1
2
3
4
5
|
package tody.lovely.service;
public interface UserService {
}
|
cs |
- 3행 : 클래스가 아닌 인터페이스다.
Service는 비즈니스 로직의 수행을 위한 메서드들을 정의한다.
2-4. UserServiceImp.java 생성
1
2
3
4
5
6
7
8
|
package tody.lovely.service;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
}
|
cs |
- 5행 : @Service 어노테이션으로 Service 객체임을 선언한다.
Service를 implements받는다. Service 인터페이스를 통해 정의된 메서드들을 구현하는 클래스이다.
2-5. UserDAO.java 생성
1
2
3
4
5
6
7
8
9
10
|
package tody.lovely.dao;
import org.springframework.stereotype.Repository;
import tody.lovely.common.dao.AbstractDAO;
@Repository("userDAO")
public class UserDAO extends AbstractDAO {
}
|
cs |
- 7행 : @Repository 어노테이션을 통해 DAO임을 선언한다.
- 8행: AbstarctDAO를 상속받았다. (MyBatis를 연동할 때 생성했다)
2-6. user_sql.xml 생성
1
2
3
4
5
|
<?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="user">
</mapper>
|
cs |
- 3행 : mapper는 한개가 아니라 여러개가 있기 때문에 namespace로 user이라는 이름을 지정한다.
3) index.jsp
1
2
3
|
<li>
<a href="/register/step1"><i class="fa fa-sign-in"></i>회원가입</a>
</li>
|
cs |
- 2행 : 요청 URL을 설정한다. 회원가입을 누르면 controller의 "/register/step1"를 찾아 갈 것이다.
4) UserController.java ("/register/step1")
1
2
3
4
|
@RequestMapping("/register/step1")
public String step1() throws Exception {
return "/user/register/step1";
}
|
cs |
- 1행 : @RequestMapping 어노테이션은 요청 URL을 매핑하여 해당 메서드를 실행한다.
- 3행 : 보여줄 화면의 jsp경로이다. ModelAndView를 사용하기도 하고, String으로 경로주소를 바로 적는 경우도 있다.
5) step1.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<h4>이용약관</h4>
<div class="panel-body" style="border: 1px solid #ccc">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum tincidunt est vitae ultrices accumsan. Aliquam ornare lacus adipiscing, posuere lectus et, fringilla augue. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
</br>
<h4>개인정보</h4>
<div class="panel-body" style="border: 1px solid #ccc">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum tincidunt est vitae ultrices accumsan. Aliquam ornare lacus adipiscing, posuere lectus et, fringilla augue. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
<br/>
<form role="form" action="/register/step2">
<div class="form-group">
<label class="checkbox-inline">
<input type="checkbox" name="agree" value="true">동의합니다.
</label>
</div>
<button type="submit" class="btn btn-default">다음 단계</button>
</form>
</div>
</div>
|
cs |
- 14행 : form태그이다. action으로 Controller에 요청 URL "/register/step2"를 보낸다.
- 17행 : input태그로 타입을 checkbox로 만든다. 체크를 하면 다음 단계로 넘어가게 한 것이다.
- 20행 : button을 누르면 다음 단계로 넘어가는데, 체크가 되어있지 않으면 넘어가지 않게 할 것이다.
위 3개의 행 말고는 개인적으로 이쁘게 css 작업한거라서 보지 않아도 된다.
6) 확인
서버를 실행시켜 보자. 아래는 index.jsp이다. css입힌거다(ㅎㅎ)
회원가입 버튼을 누르게 되면 step1.jsp가 나오면 된다.
나왔다! 성공!
7) UserController.java (/register/step2)
1
2
3
4
5
6
7
8
9
10
|
@RequestMapping("/register/step2")
public ModelAndView step2(@RequestParam(value="agree", defaultValue="false") Boolean agree) throws Exception {
if(!agree) {
ModelAndView mv = new ModelAndView("user/register/step1");
return mv;
}
ModelAndView mv = new ModelAndView("user/register/step2");
mv.addObject("registerRequest", new RegisterRequest());
return mv;
}
|
cs |
- 1행 : @RequestMapping 어노테이션을 선언한다.
- 2행 : step1.jsp에서 17행의 input태그의 이름이 agree이다. form태그로 타고 온 파라미터값이다. 디폴트값이 false다.
- 3~6행 : agree의 checkbox가 true가 아니면(체크하지 않았으면) 다시 step1.jsp로 돌려보낸다.
- 7행 : 4번 Controller에서는 String으로 경로주소를 썼지만 여기는 ModelAndView로 화면에 보여줄 jsp를 선언한다.
- 8행 : ModelAndView객체에 정보를 담아 jsp로 넘겨준다. 아직 RegisterRequest가 없어서 에러가 뜰 것이다. 만들자.
8) RegisterRequest.java
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
|
package tody.lovely.util;
public class RegisterRequest {
private String email;
private String id;
private String name;
private String pw;
private String checkPw;
//비밀번호 확인
public boolean isPwEqualToCheckPw() {
return pw.equals(checkPw);
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPw() {
return pw;
}
public void setPw(String pw) {
this.pw = pw;
}
public String getCheckPw() {
return checkPw;
}
public void setCheckPw(String checkPw) {
this.checkPw = checkPw;
}
}
|
cs |
회원가입을 하는데 필요한 Command객체들을 담는다. VO와 마찬가지이다.
- 12~14행 : 비밀번호와 비밀번호 확인이 일치하는 지 검사하는 메소드이다.
9) step2.jsp
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
|
<div class="panel-body">
<div class="row">
<div class="col-lg-6">
<form:form role="form" commandName="registerRequest" action="/register/step3" method="post">
<div class="form-group input-group">
<span class="input-group-addon"><i class="fa fa-check"></i></span>
<form:input type="text" class="form-control" placeholder="ID" path="id"/>
<form:errors path="id"/>
</div>
<div class="form-group input-group">
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
<form:input type="email" class="form-control" placeholder="Email" path="email"/>
</div>
<div class="form-group input-group">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
<form:input type="text" class="form-control" placeholder="Name" path="name"/>
<form:errors path="name"/>
</div>
<div class="form-group input-group">
<span class="input-group-addon"><i class="fa fa-lock"></i></span>
<form:password class="form-control" placeholder="Password" path="pw"/>
<form:errors path="pw"/>
</div>
<div class="form-group input-group">
<span class="input-group-addon"><i class="fa fa-lock"></i></span>
<form:password class="form-control" placeholder="Password Check" path="checkPw"/>
<form:errors path="checkPw"/>
</div>
<button type="submit" class="btn btn-default">가입하기</button>
<button type="reset" class="btn btn-default">취소하기</button>
</form:form>
</div>
</div>
</div>
|
cs |
- 4행 : form태그에 정보들이 담길 Command 객체 이름이다. method="post"를 하게 되면 파리미터값들이 주소에 보이지 않게 된다.
- 7행 : path는 RegisterRequest.java에 있는 프로퍼티와 연결된다. 두 개의 이름이 같아야 한다.
- 8행 : errors의 내용을 가져온다. path로 프로퍼티를 지정한다.
**** input 타입에 email을 해줬다면, 유효성 검사에 email을 넣을 필요 없다!
10) 확인
10-1. 동의하지 않고 다음단계를 누른다.
주소 : https://localhost:8080/register/step1
주소 : https://localhost:8080/register/step2?
step2.jsp로 넘어가지 않고, step1.jsp화면에 머물러 있는 것을 확인한다.
10-2. 동의하고 다음단계를 누른다.
주소 : https://localhost:8080/register/step1
주소 : https://localhost:8080/register/step2?agree=true
step2.jsp로 넘어와졌다. 성공!
지금 주소에 agree의 값이 적혀있는데, 보이기 싫으면 form태그에 mehtod="post"를 하면 된다. 고치러가야지.
11) RegisterRequestValidator.java
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
|
package tody.lovely.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
public class RegisterRequestValidator implements Validator{
private static final String emailRegExp =
"^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" +
"[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
private Pattern pattern;
public RegisterRequestValidator() {
pattern = Pattern.compile(emailRegExp);
}
@Override
public boolean supports(Class<?> clazz) {
return RegisterRequest.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
RegisterRequest regReq = (RegisterRequest) target;
if(regReq.getEmail() == null || regReq.getEmail().trim().isEmpty()) {
errors.rejectValue("email", "required", "필수 정보 입니다.");
} else {
Matcher matcher = pattern.matcher(regReq.getEmail());
if(!matcher.matches()) {
errors.rejectValue("email", "bad", "올바르지 않는 형식입니다.");
}
}
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required", "필수 정보 입니다.");
ValidationUtils.rejectIfEmpty(errors, "pw", "required", "필수 정보 입니다.");
ValidationUtils.rejectIfEmpty(errors, "checkPw", "required", "필수 정보 입니다.");
if(!regReq.getPw().isEmpty()) {
if(!regReq.isPwEqualToCheckPw()) {
errors.rejectValue("checkPw", "nomatch", "비밀번호가 일치하지 않습니다.");
}
}
}
}
|
cs |
step2.jsp에서 작성한 것들의 유효성을 검사하는 클래스이다.
- 12행 : 이메일의 정규표현이다.
- 28행 : 가져온 객체를 RegisterRequest에 담는다.
- 30~31행 : 이메일을 입력하지 않으면 에러를 보낸다.
- 33~35행 : 이메일 정규패턴을 확인하고 맞지않으면 에러를 보낸다. *** input 타입을 email로 했으면 필요 없음!
- 38~40행 : 입력되지 않으면 에러를 보낸다.
- 41~45행 : 비밀번호가 입력되지 않고, 비밀번호와 비밀번호 확인이 맞지않으면 에러를 보낸다.
- errors.rejectValue(String field, String errorCode, String defaultMessage)
필드에 대한 에러코드를 추가, 에러코드에 대한 메시지가 존재하지 않을 경우 defaultMessage를 사용한다.
- rejectIfEmpty(Errors errors, String field, String erreCode, String defaultMessage)
값이 공백일 경우, 지정된 errorCode를 가지는 지정된 field가 없으면 defaultMessage를 사용한다.
- rejectIfEmptyOrWhitespace(Errors errors, String field, String erreCode, String defaultMessage)
값이 공백이거나 공백을 포함하고 있는 경우, 지정된 errorCode를 가지는 지정된 field가 없으면 defaultMessage를 사용한다.
다른 메소드도 보려면 여기를 클릭하세요.
12) UserController.java (/register/step3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@Resource(name="userService")
private UserService userSer;
@RequestMapping("/register/step3")
public ModelAndView step3(RegisterRequest regReq, Errors errors) throws Exception{
new RegisterRequestValidator().validate(regReq, errors);
if(errors.hasErrors()) {
ModelAndView mv = new ModelAndView("user/register/step2");
return mv;
}
try {
userSer.register(regReq);
} catch (AlreadyExistingEmailException e) {
errors.rejectValue("email", "duplicate", "이미 가입된 이메일입니다.");
ModelAndView mv = new ModelAndView("user/register/step2");
return mv;
} catch (AlreadyExistingIdException e) {
errors.rejectValue("id", "duplicate", "이미 가입된 아이디입니다.");
ModelAndView mv = new ModelAndView("user/register/step2");
return mv;
}
ModelAndView mv = new ModelAndView("user/register/step3");
return mv;
}
|
cs |
- 1행 : Service 영역을 접근하기 위한 선언이다. @Resource 어노테이션으로 빈(Bean)을 수동으로 등록한다.
- 5행 : 커맨드 객체와 연결된 Errors객체를 생성하여 파라미터로 전달한다.커맨드 객체를 전달 받지 않아도 Errors 객체를 이용해서 지정한 값을 구할 수 있다. Errors객체는 getFieldValue() 메서드를 제공하여 커맨드 객체의 특정 프로퍼티 값을 가져온다. Errors타입의 파라미터는 반드시 커맨드 객체를 위한 파라미터(RegisterRequest) 다음에 위치해야 한다.
- 6행 : RegisterRequestValidator()를 호출한다. RegisterRequest 커맨트 객체값의 유효성을 검사하고 결과를 Errors객체에 담는다.
- 7~8행 : 결과를 담은 errors가 error를 가지면 errors의 내용과 함께 step2.jsp로 간다.
- 12행 : 회원 등록을 위한 비지니스 로직을 수행한다.
- 13~20행 : 예외처리를 해준 것이다.
17) UserService.java
1
2
|
void register(RegisterRequest regReq) throws Exception;
|
cs |
18) UserServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Resource(name="userDAO")
private UserDAO userDAO;
@Override
public void register(RegisterRequest regReq) throws Exception {
UserVO email = userDAO.selectByEmail(regReq.getEmail());
if(email!=null) {
throw new AlreadyExistingEmailException(regReq.getEmail()+" is duplicate email.");
}
UserVO id = userDAO.selectById(regReq.getId());
if(id!=null) {
throw new AlreadyExistingIdException(regReq.getId()+" is duplicate id.");
}
userDAO.insertUser(regReq);
}
|
cs |
- 1행 : @Resource 어노테이션으로 수동으로 빈(Bean)을 등록한다.
- 6~9행 : email이 존재하는 지 확인한다. 있으면 AlreadyExistingEmailException으로 던진다.
- 10~13행 : id가 존재하는 지 확인한다. 있으면 AleradyExistingIdException으로 던진다.
18-1. 예외처리
AlreadyExistingEmailException.java
1
2
3
4
5
6
7
|
package tody.lovely.exception;
public class AlreadyExistingEmailException extends RuntimeException{
public AlreadyExistingEmailException(String message) {
super(message);
}
}
|
cs |
AlreadyExistingIdException.java
1
2
3
4
5
6
7
|
package tody.lovely.exception;
public class AlreadyExistingIdException extends RuntimeException{
public AlreadyExistingEmailException(String message) {
super(message);
}
}
|
cs |
회원을 등록하는 과정에서 생기는 예외처리이다. 그래서 RuntimeException을 상속받았다.
19) UserDAO.java
1
2
3
4
5
6
7
8
9
10
11
|
public UserVO selectByEmail(String email) {
return (UserVO)selectOne("user.selectByEmail", email);
}
public UserVO selectById(String id) {
return (UserVO)selectOne("user.selectById", id);
}
public void insertUser(RegisterRequest regReq) {
insert("user.register", regReq);
}
|
cs |
실제 데이터베이스에 접근하는 클래스이다. AbstarctDAO를 상속받아서 AbstarctDAO 메소드를 사용한다. return할때 "user.XXXX"를 볼 수 있는데, user는 mapper의 namespace를 뜻하고, 뒤에는 쿼리의 이름을 뜻한다. 이렇게 선언하면 수많은 mapper중에서 찾아간다.
- 1행 : email을 찾는다.
- 5행 : id를 찾는다.
- 9행 : 회원을 등록한다.
20) user_sql.xml
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
|
<?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="user">
<select id="selectByEmail" resultType="tody.lovely.vo.UserVO">
<![CDATA[
SELECT
EMAIL,
NAME
FROM
USER
WHERE
EMAIL = #{email}
]]>
</select>
<select id="selectById" resultType="tody.lovely.vo.UserVO">
<![CDATA[
SELECT
ID,
NAME
FROM
USER
WHERE
ID = #{id}
]]>
</select>
<insert id="register">
<![CDATA[
INSERT INTO USER
(
EMAIL,
ID,
NAME,
PASSWORD,
REGDATE
)
VALUES
(
#{email},
#{id},
#{name},
#{pw},
SYSDATE()
)
]]>
</insert>
</mapper>
|
cs |
- 3행 : namespace가 user이다. 아까 DAO에서 "user.XXXX"에서 본 user이다. 그리고 각각의 쿼리의 이름에 찾아간다.
- 5행 : email을 찾는다. <select>태그를 이용해 명시한다. resultType은 쿼리의 값이 UserVO에 담겨서 반환된다는 뜻이다.
- 17행 : id를 찾는다. <select>태그를 이용해 명시한다. resultType은 쿼리의 값이 UserVO에 담겨서 반환된다는 뜻이다.
- 29행 : 회원을 등록한다. <insert>태그를 이용해 명시한다.
***** VALUES의 #{}값을 쓸때 대문자, 소문자에 유의해야 한다. jsp에서 path와 여기의 #{}가 같아야한다. 대소문자까지도.
** <![CDATA[]>는 단순히 로그를 이쁘게 찍히게 하려고 만든것이다. 없어도 상관 없다. 그리고 길게 쭉 적어도 상관없다.
21) step3.jsp
1
2
3
|
<div class="alert alert-success">
축하드립니다, 성공적으로 회원가입이 되었습니다!
</div>
|
cs |
22) 확인
**** CSS 적용한 거라서 다를 수 있음 주의!
22-1. 아이디나 비밀번호 입력이 빠질 경우
22-2. 이메일 형식이 맞지 않을 경우(input타입 email)
기본적으로 제공해주는 기능이다. input type="email"이면 email형식인지 확인해준다.
22-3. 이메일 형식이 맞지 않을 경우(email 유효성 검사)
만약 그냥 input type="text"로 했을 경우, validator를 통해 유효성검사를 해줘야 한다.
22-4. 비밀번호 확인이 틀릴 경우
22-5. 가입된 이메일이나 아이디가 있는 경우
22-6. 가입이 성공한 경우
짠! 최종 회원가입 성공!!!!!
23) DB 확인
IDX 2에 들어가있는것을 확인 할 수 있다!
끝나따 끝나버려따!!! ٩(ˊᗜˋ*)و
이제 로그인 로그아웃 ... (먼산)
'공부 > Spring' 카테고리의 다른 글
스프링(Spring) 개발 - 로그인, 로그아웃 하기 (60) | 2018.05.11 |
---|---|
스프링(Spring) 개발 - Hibernate를 이용한 회원가입하기 (7) | 2018.05.10 |
스프링(Spring) 개발 - Validator를 이용한 회원가입 만들기 (49) | 2018.05.09 |
스프링(Spring) 설정 - MySQL을 사용하여 마이바티스(MyBatis) 연동하기 (8) | 2018.05.02 |
스프링(Spring) 설정 - 인터셉터(Interceptor) 설정 (59) | 2018.04.26 |
스프링(Spring) 설정 - Log4j 설정 (3) | 2018.04.26 |
회원가입 유효성 검사까지 따라왔는데 가입하기를 누르면 500에러가 발생합니다. 다른 곳에 문의를 해 봤을 때 DB연동의 문제라고 하는데 구글링해서 나와있는 글들을 보고 해도 몇 일 째 에러가 안없어져서요.. 소스 그대로 붙이고 패키지명만 수정한 거라 어떤 것을 수정해야 하는 지 알려주실 수 있나요? ㅎㅎ
(❁´▽`❁) #에게 님 블로그 글을 보면서 만든 거라서요..
Exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for user.selectByEmail
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for user.selectByEmail
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Root Cause
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for user.selectByEmail
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for user.selectByEmail
org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:75)
org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:371)
com.sun.proxy.$Proxy4.selectOne(Unknown Source)
org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:163)
zest.web.common.dao.AbstractDAO.selectOne(AbstractDAO.java:45)
zest.web.dao.UserDAO.selectByEmail(UserDAO.java:17)
zest.web.service.UserServiceImpl.register(UserServiceImpl.java:21)
zest.web.controller.UserController.step3(UserController.java:47)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
초보자라 하나씩 따라하면서 만들었는데 에러가 떠서 고생하고 있네요 ㅠㅠ
이게 그 에러로그인데 괜찮으시면 확인 해 주시겠어요? ..
네 DAO랑 user_sql.xml 확인했는데 오타는 없었어요.. (❁´▽`❁) #에게 님 코드로도 확인했구요.. 구글링중에 mysql 8 버전이 스프링이랑 못붙어서 db 접속이 안된다는 글을 보고 지금 mysql 버전 낮춰서 다운 받고 있어요 혹시 mysql 8 쓰셨나요??
안녕하세요 따라하면서 질문을 올립니다.
저는 mapper 규칙을 /mapper/**/*Mapper.xml로 했고
파일은 UserMapper.xml로 해서 DAO 주소를 'tbUser.listUser'로 지정했습니다.
디비에 내용을 일부 넣고 테스트 하려니 500에러가 뜨네요
<?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">심각: Servlet.service() for servlet [appServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for tbUser.listUser
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for tbUser.listUser] with root cause
java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for tbUser.listUser
이렇게 뜨네요. 오타나 그런거를 해봤지만 전혀 없었고요. 주소 중복은 저거 1개만 했기 때문에 전혀 이상없어 보이고요.. 뭐가 문제일까요?
<mapper namespace="tbUser">
<select id="listUser" resultType="java.util.Map">
SELECT ID,PASSWORD
FROM
TB_USER
</select>
</mapper>
spring 카테고리 내용 잘 보고 있습니다.
css 파일은 따로 들고 계신가요 아니면 프레임워크 등을 이용하신건가요..~?
궁금한게 있는데욤
@RequestMapping("register/step1"
이렇게 되어 있는데 register는 views 경로 안에 register라는 폴더를 의미하는거죵? 그리고 return "/user/register/step1"에서 user는 user폴더를 의미하는거구용??? 맞나요?
step2 에서
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
taglib 써야지 form:input 이 문법 쓰는게 가능한걸로 아는데...
태그라이브러리 붙이면 500 에러 뜹니다;
3시간째 계속 500 에러ㅠㅠㅠㅠㅠㅠㅠ
https://to-dy.tistory.com/31?category=702830
선생님 게시글에 저랑 똑같은 에러 관련된 게시물 있었서 봤는데; 아직 이해가 부족해서 엄청 좌절하고 있었는데요....
저는
Neither BindingResult nor plain target object for bean name 'registerRequest' available as request attribute
이렇게 떴었는데;
뭐때문인지 모르겠지만 결국 됩니다ㅠㅠ...
선생님 혹시 이 프로젝트에 관한게 git에도 업로드 되어있나요ㅠㅠ??
Hibernate 이용한 회원가입하면 다른 부분을 어떻게 손봐야할지 몰라서 참고가 가능한지 궁금합니다ㅠ
저도 윗분들 처럼 500 에러 중
Mapped Statements collection does not contain value for user.selectByEmail
selectByEmail 에러가 계속 나는데요...
버젼 바꾼다는건 mysql 워크벤치까지 삭제하고 5.7로 다운받아서 해야하는건가요??
ㅠㅠ...제가 그럼 Mysql 8.0 이랑 워크벤치 사용 중인데 프로그램 자체를 굳이 삭제할 필요는 없는건가요???
저는 윗분들과 같은 에러인데 pom.xml에서 mysql, maven 버전을 낮춰도 보고 mysql서버 및 워크벤치도 다 삭제하고 5.7버전으로 설치도 해보고....스팰링이나 기타등등의 문제점을 다 찾아봤지만 되지 않아서 포기했습니다ㅠㅠ...흑흑...
<form:errors path="email"/> 요거 빠진건가요 없어도 되는건가요 저는 이거없으니 작동이 잘안되네요
오류가 뜨지않는데 회원가입하고 가입하기 버튼을 누르면 값이 안넘어가고 reset처럼 되는데 왜그럴까요.. 코드문제일까요?ㅠㅠ
BCryptPasswordEncoder를 사용해서 회원가입시에 비밀번호 암호화를 해보려고 하는데요...
;
step2 컨트롤러 부분중
ModelAndView mv = new ModelAndView("/common/register/step2"
mv.addObject("registerRequest", new RegisterRequest());
return mv;
이 부분에서 하는것으로 생각해서 작성해보았는데 저의 능력 부족으로 인해 ㅠㅠ
자꾸 안되고있는데 해당 부분에서 작업을 요청하는것이 맞나요?
그리고 ModelAndView에서 작업을 한다면 그냥 model 방식으로 vo값을 가져와하는것과 차이가 있을까요?
전체적인 코드정리는 되어있으나 경로가 불확실하게 나와있어서 진행이 되지않습니다 위에 패키지이름보고 유추한 것을 제외하고는 잘모르겠는데... 혹시 전체적인 경로같은거좀 상세하게 정리해주실수있나요..?
UserVO.java 에 코드중에서 MAME이 있는데 NAME으로 고쳐서 써야되나요???
2020-07-17 공부!
감사합니다 덕분에 공부가 아주 잘 되어 가고있습니다! 감사합니다!
css 적용은 어떻게 하는건가요?
안녕하세요 스프링부트로 프로젝트진행중에 글 잘 봤습니다 ~
DB에 정보를 넘길때는 RegisterRequest객체를 사용하고, DB값을 불러올때는 userVO를 사용하는 것 맞나요?
맞다면 userVO 하나로 DB에 정보 넘기는 것과 DB값 불러오는 것을 전부 수행하지 않고 두개로 나눈 이유가 있을까요??