Struts를 이용한 로그인 예제_Session, validate, ActionErrors 사용
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
이번에는 이전에 만들어본 로그인 기능에 몇 가지 요소를 붙여 기능을 완성 시켜 보도록 하겠습니다. Struts 1.3.8로 작성 되었습니다.
먼저 main.jsp로 접근을 합니다. 이때 사용자가 로그인을 이미 한 사용자라면(세션에서 확인) “반갑습니다. ~~~님” 라는 메시지를 출력하고 logout을 하이퍼링크 걸어서 보여주며, 로그인을 하지 않은 사용자라면 단지 “반갑습니다” 메시지를 출력 하면서 login을 하이퍼링크 걸어서 보여 줍니다.
사용자가 로그인을 하지 않은 상태에서 접근 해 login을 클릭 하면 login화면이 나타나며 이곳에서 로그인 처리를 하게 됩니다. 이때 사용자 ID가 “jclee”라고 입력만 하면 본 예제에서는 인증이 되게 처리를 하였습니다.
login에서 action의 처리는 LoginAction이 했으며 logout에 대한 action은 LogoffAction에서 처리를 하였습니다.
아래의 절차대로 하나씩 만들어 보도록 하겠습니다.
우선 하나씩 따라 하시면서 이해 하도록 하죠^^
1. main.jsp
<%@ page language="java" %>
<%@ page pageEncoding="euc-kr" %>
<!-- 최초 사용자가 접속하게 되는 페이지 입니다. -->
<!-- 아래는 import와 동일한 기능을 하는 태그로 태그 확장을 사용 할 수 있도록 합니다 -->
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
<head>
<title>환영 합니다</title>
<!-- HTML의 BASE 태그와 같은 것으로써 이는 JSP에는 이미지나 다른 리소스를 참조하는 경우
상대 경로를 기술할 때 BASE가 되는 것입니다. -->
<html:base/>
</head>
<body>
<!-- 현재 세션에 “user”빈이 저장 되어 있는지 확인을 해 있는 경우엔… -->
<logic:present scope="session" name="user">
<h3>반갑습니다.<bean:write name="user" property="id"/>님!</h3>
</logic:present>
<!-- 현재 세션에 “user”빈이 저장 되어 있는지 확인을 해 없는 경우엔… -->
<logic:notPresent scope="session" name="user">
<h3>반갑습니다! 먼저 로그인을 해주세요~</h3>
</logic:notPresent>
<html:errors/>
<ul>
<! -- 인증이 된 사용자면 “로그아웃” 버튼을 활성화 하고 인증이 되지 않은 사용자인 경우엔 “로그인”
버튼을 활성화 하고 있습니다. -->
<logic:present scope="session" name="user">
<li>
<!-- 로그아웃을 클릭 하게 되면 이동하게 되는 부분에 대해 기술 한 것인데(하이퍼 링크) “login”은 struts-cinfig.xml에 Forward로써 정의를 하게 됩니다. 이렇게 Config에서 정의 함으로써 추후 생기게 되는 변화에 유연하게 대처 할 수 있는 것입니다. -->
<html:link forward="logoff">로그아웃</html:link>
</li>
</logic:present>
<logic:notPresent scope="session" name="user">
<li>
<html:link forward="login">로그인</html:link>
</li>
</logic:notPresent>
</ul>
<body>
</html>
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
2. login.jsp
<%@ page pageEncoding="euc-kr" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title> Login 화면 </title>
</head>
<body>
<!-- 웹서버가 보내는 응답에 오류가 있다면 출력 -->
<html:errors/>
<!-- LoginSummit에 대해서는 struts-config.xml에 Mapping을 하게 된다 -->
<!-- focus="id" 라는 문법에 의해 자동으로 자바스크립트를 생성 합니다. -->
<html:form action="/LoginSubmit" focus="id">
<table>
<tr>
<th align="right">사용자ID</th>
<!-- 아래는 input type=text 와 동일한 기능을 합니다 -->
<td><html:text property="id"/></td>
</tr>
<tr>
<th align="right">비밀번호</th>
<!-- 만약 로그인을 실패하여 다시 돌아오는 경우 pwd 항목의 값을 비울때는 redisplay="false"
라고 하면 됩니다. HTML의 password 항목과 유사함 -->
<td><html:password property="pwd"/></td>
</tr>
<tr>
<!-- Submit 버튼과 Reset 버튼을 생성 -->
<td><html:submit/></td>
<td><html:reset/></td>
</tr>
</table>
</html:form>
</body>
</html>
3. LoginForm.java (폼빈)
package login2;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public class LoginForm extends ActionForm {
private String id=null;
private String pwd=null;
public String getId() {
return id;
}
public String getPwd() {
return pwd;
}
public void setId(String id) {
this.id = id;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
/* struts-config.xml 에서 메핑시 validate="true" 라고 설정 되면 아래의
validate 함수가 호출 되어 입력되는 값에 대한 validation check를 하게 됩니다.
HTTP 요청으로 부터 해당 폼의 값을 set 한 후 아래 메소드가 호출 됩니다.
참고로 validate에 위해 반환되는 ActionErrors 객체 역시 Framework에 관련된 클래스 입니다.
만약 validate에서 null이나 empty가 아닌 ActionError 객체를 리턴하게 되면
login.jsp에 있는 <html:errors/> 태그는 오류를 출력하고 아니면 넘어가게 됩니다...
error.id.required, error.pwd.required는 일종의 키값으로 각 Locale마다 고유한 리소스를 가질 수
있으므로 메시지에 대해 손쉬운 관리를 제공 합니다.
예를들면 error.id.required = 사용자 ID는 필수 입력 항목 입니다. , 이러한 식으로 설정 합니다.
*/
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if((id == null) || (id.length()<1)) {
errors.add("error.id.required", new ActionMessage("error.id.required"));
}
if((pwd == null) || (pwd.length()<1)) {
errors.add("error.pwd.required", new ActionMessage("error.pwd.required"));
}
return errors;
}
}
4. LoginActoin.java
package login2;
import org.apache.struts.action.Action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import login2.LoginForm;
import login2.Constants;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionServlet;
/**
* @author 이종철
*/
public class LoginAction extends Action {
public boolean authUser(String id, String pwd) {
//이곳에서 디비에 접속해서 ID와 Password가 맞는지 확인 한다.
//본 예제에서는 ID가 "jclee"인 경우 무조건 인증이 된다고 보고 true를 리턴 합니다
if (id.equals("jclee")) {
return true;
}
else {
return false;
}
}
public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) {
String id = ((LoginForm)form).getId();
String pwd = ((LoginForm)form).getPwd();
boolean isOK = authUser(id, pwd);
if (!isOK) {
//인증 실패
ActionMessages errors = new ActionMessages(); errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.login.invalid"));
saveErrors(request,errors);
return (new ActionForward(mapping.getInput()));
}
//인증 성공한 경우 세션에 로그인한 사용자를 저장
HttpSession session = request.getSession();
session.setAttribute(Constants.USER_KEY, form);
//로그를 남기자.
StringBuffer buf = new StringBuffer("LoginAction : User --> ");
buf.append(id + "logged in session");
servlet.log(buf.toString());
return (mapping.findForward(Constants.SUCCESS));
}
}
5. LogoffAction.java
package login2;
import org.apache.struts.action.Action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import login2.LoginForm;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class LogoffAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
//필요한 어트리뷰트를 뽑아 냅니다.
//LoginAction에서 사용자의 로그온개체를 Consants.USER_KEY라는 이름으로 세션에 저장
HttpSession session = request.getSession();
LoginForm user = (LoginForm)session.getAttribute(Constants.USER_KEY);
if (user!= null) {
//로그를 남기자
StringBuffer buf = new StringBuffer("User Logout : " + user.getId());
servlet.log(buf.toString());
}
//사용자의 로그인을 삭제, session.invaidate() 의 경우 세션의 모든 것을 무효화 시킴.
session.removeAttribute(Constants.USER_KEY);
//성공적으로 처리 되었음을 알림
return (mapping.findForward(Constants.SUCCESS));
}
}
6. Constants.java (상수 값을 설정 한 곳)
package login2;
public class Constants {
/**
* 로그인한 사용자의 LoginForm이 저장될 세션 범위의 Attriute 이름
*/
public static final String USER_KEY = "user";
/**
* ActionForward에서 사용되는 값
*/
public static final String SUCCESS = "success";
/**
* ActionForward 로그인 동작을 나타내는 Tocken
*/
public static final String LOGIN = "login";
/**
* ActionForward welcome 동작을 나타내는 Tocken
*/
public static final String WELCOME = "welcome";
}
7. application.properties(/WEB-INF/src/resources 에 위치)
(애플리케이션 전체에 사용될 메시지들을 정리해 놓은 것)
error.id.required=<li>ID REQUIRED.</li>
error.pwd.required=<li>PASSWORD REQUIRED</li>
error.login.invalid=<li>ID/PASSWORD NOT CORRECT</li>
errors.header=<h3><font color="red">ERROR!</font></h3>
You must correct the following error(s) before proceeding:<UL>
errors.footer=</ul><hr>
8. struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<!-- ========== Form Bean Definitions ================================== -->
<form-beans>
<form-bean name="loginForm" type="login2.LoginForm">
<form-property name="pwd" type="java.lang.String" />
<form-property name="id" type="java.lang.String" />
</form-bean>
</form-beans>
<!-- ========== Global Forward Definitions =============================== -->
<global-forwards>
<forward name="success" path="/main.jsp" />
<forward name="logoff" path="/logoff.do" />
<forward name="login" path="/login.jsp" />
</global-forwards>
<!-- ========== Action Mapping Definitions =============================== -->
<!-- valiedate를 true라고 함으로써 LoginForm의 validate가 호출 됩니다. -->
<action-mappings>
<!-- loginAction에 대한 정의 -->
<action
path="/LoginSubmit"
type="login2.LoginAction"
name="loginForm"
validate="true"
input="/login.jsp"
/>
<!-- logoffAction에 대한 정의 -->
<action
path="/logoff"
type="login2.LogoffAction"
validate="false"
/>
</action-mappings>
<!-- ========== 아래는 스트러츠 Application에서 사용할 Message Resource들을 설정 ====== -->
<!-- 확장자가 properties인 application.properties를 만들어 넣으면 된다 ============ -->
<message-resources parameter="resources.application"/>
</struts-config>
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
이번에는 이전에 만들어본 로그인 기능에 몇 가지 요소를 붙여 기능을 완성 시켜 보도록 하겠습니다. Struts 1.3.8로 작성 되었습니다.
먼저 main.jsp로 접근을 합니다. 이때 사용자가 로그인을 이미 한 사용자라면(세션에서 확인) “반갑습니다. ~~~님” 라는 메시지를 출력하고 logout을 하이퍼링크 걸어서 보여주며, 로그인을 하지 않은 사용자라면 단지 “반갑습니다” 메시지를 출력 하면서 login을 하이퍼링크 걸어서 보여 줍니다.
사용자가 로그인을 하지 않은 상태에서 접근 해 login을 클릭 하면 login화면이 나타나며 이곳에서 로그인 처리를 하게 됩니다. 이때 사용자 ID가 “jclee”라고 입력만 하면 본 예제에서는 인증이 되게 처리를 하였습니다.
login에서 action의 처리는 LoginAction이 했으며 logout에 대한 action은 LogoffAction에서 처리를 하였습니다.
아래의 절차대로 하나씩 만들어 보도록 하겠습니다.
우선 하나씩 따라 하시면서 이해 하도록 하죠^^
1. main.jsp
<%@ page language="java" %>
<%@ page pageEncoding="euc-kr" %>
<!-- 최초 사용자가 접속하게 되는 페이지 입니다. -->
<!-- 아래는 import와 동일한 기능을 하는 태그로 태그 확장을 사용 할 수 있도록 합니다 -->
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
<head>
<title>환영 합니다</title>
<!-- HTML의 BASE 태그와 같은 것으로써 이는 JSP에는 이미지나 다른 리소스를 참조하는 경우
상대 경로를 기술할 때 BASE가 되는 것입니다. -->
<html:base/>
</head>
<body>
<!-- 현재 세션에 “user”빈이 저장 되어 있는지 확인을 해 있는 경우엔… -->
<logic:present scope="session" name="user">
<h3>반갑습니다.<bean:write name="user" property="id"/>님!</h3>
</logic:present>
<!-- 현재 세션에 “user”빈이 저장 되어 있는지 확인을 해 없는 경우엔… -->
<logic:notPresent scope="session" name="user">
<h3>반갑습니다! 먼저 로그인을 해주세요~</h3>
</logic:notPresent>
<html:errors/>
<ul>
<! -- 인증이 된 사용자면 “로그아웃” 버튼을 활성화 하고 인증이 되지 않은 사용자인 경우엔 “로그인”
버튼을 활성화 하고 있습니다. -->
<logic:present scope="session" name="user">
<li>
<!-- 로그아웃을 클릭 하게 되면 이동하게 되는 부분에 대해 기술 한 것인데(하이퍼 링크) “login”은 struts-cinfig.xml에 Forward로써 정의를 하게 됩니다. 이렇게 Config에서 정의 함으로써 추후 생기게 되는 변화에 유연하게 대처 할 수 있는 것입니다. -->
<html:link forward="logoff">로그아웃</html:link>
</li>
</logic:present>
<logic:notPresent scope="session" name="user">
<li>
<html:link forward="login">로그인</html:link>
</li>
</logic:notPresent>
</ul>
<body>
</html>
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
2. login.jsp
<%@ page pageEncoding="euc-kr" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title> Login 화면 </title>
</head>
<body>
<!-- 웹서버가 보내는 응답에 오류가 있다면 출력 -->
<html:errors/>
<!-- LoginSummit에 대해서는 struts-config.xml에 Mapping을 하게 된다 -->
<!-- focus="id" 라는 문법에 의해 자동으로 자바스크립트를 생성 합니다. -->
<html:form action="/LoginSubmit" focus="id">
<table>
<tr>
<th align="right">사용자ID</th>
<!-- 아래는 input type=text 와 동일한 기능을 합니다 -->
<td><html:text property="id"/></td>
</tr>
<tr>
<th align="right">비밀번호</th>
<!-- 만약 로그인을 실패하여 다시 돌아오는 경우 pwd 항목의 값을 비울때는 redisplay="false"
라고 하면 됩니다. HTML의 password 항목과 유사함 -->
<td><html:password property="pwd"/></td>
</tr>
<tr>
<!-- Submit 버튼과 Reset 버튼을 생성 -->
<td><html:submit/></td>
<td><html:reset/></td>
</tr>
</table>
</html:form>
</body>
</html>
3. LoginForm.java (폼빈)
package login2;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public class LoginForm extends ActionForm {
private String id=null;
private String pwd=null;
public String getId() {
return id;
}
public String getPwd() {
return pwd;
}
public void setId(String id) {
this.id = id;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
/* struts-config.xml 에서 메핑시 validate="true" 라고 설정 되면 아래의
validate 함수가 호출 되어 입력되는 값에 대한 validation check를 하게 됩니다.
HTTP 요청으로 부터 해당 폼의 값을 set 한 후 아래 메소드가 호출 됩니다.
참고로 validate에 위해 반환되는 ActionErrors 객체 역시 Framework에 관련된 클래스 입니다.
만약 validate에서 null이나 empty가 아닌 ActionError 객체를 리턴하게 되면
login.jsp에 있는 <html:errors/> 태그는 오류를 출력하고 아니면 넘어가게 됩니다...
error.id.required, error.pwd.required는 일종의 키값으로 각 Locale마다 고유한 리소스를 가질 수
있으므로 메시지에 대해 손쉬운 관리를 제공 합니다.
예를들면 error.id.required = 사용자 ID는 필수 입력 항목 입니다. , 이러한 식으로 설정 합니다.
*/
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if((id == null) || (id.length()<1)) {
errors.add("error.id.required", new ActionMessage("error.id.required"));
}
if((pwd == null) || (pwd.length()<1)) {
errors.add("error.pwd.required", new ActionMessage("error.pwd.required"));
}
return errors;
}
}
4. LoginActoin.java
package login2;
import org.apache.struts.action.Action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import login2.LoginForm;
import login2.Constants;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionServlet;
/**
* @author 이종철
*/
public class LoginAction extends Action {
public boolean authUser(String id, String pwd) {
//이곳에서 디비에 접속해서 ID와 Password가 맞는지 확인 한다.
//본 예제에서는 ID가 "jclee"인 경우 무조건 인증이 된다고 보고 true를 리턴 합니다
if (id.equals("jclee")) {
return true;
}
else {
return false;
}
}
public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) {
String id = ((LoginForm)form).getId();
String pwd = ((LoginForm)form).getPwd();
boolean isOK = authUser(id, pwd);
if (!isOK) {
//인증 실패
ActionMessages errors = new ActionMessages(); errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.login.invalid"));
saveErrors(request,errors);
return (new ActionForward(mapping.getInput()));
}
//인증 성공한 경우 세션에 로그인한 사용자를 저장
HttpSession session = request.getSession();
session.setAttribute(Constants.USER_KEY, form);
//로그를 남기자.
StringBuffer buf = new StringBuffer("LoginAction : User --> ");
buf.append(id + "logged in session");
servlet.log(buf.toString());
return (mapping.findForward(Constants.SUCCESS));
}
}
5. LogoffAction.java
package login2;
import org.apache.struts.action.Action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import login2.LoginForm;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class LogoffAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
//필요한 어트리뷰트를 뽑아 냅니다.
//LoginAction에서 사용자의 로그온개체를 Consants.USER_KEY라는 이름으로 세션에 저장
HttpSession session = request.getSession();
LoginForm user = (LoginForm)session.getAttribute(Constants.USER_KEY);
if (user!= null) {
//로그를 남기자
StringBuffer buf = new StringBuffer("User Logout : " + user.getId());
servlet.log(buf.toString());
}
//사용자의 로그인을 삭제, session.invaidate() 의 경우 세션의 모든 것을 무효화 시킴.
session.removeAttribute(Constants.USER_KEY);
//성공적으로 처리 되었음을 알림
return (mapping.findForward(Constants.SUCCESS));
}
}
6. Constants.java (상수 값을 설정 한 곳)
package login2;
public class Constants {
/**
* 로그인한 사용자의 LoginForm이 저장될 세션 범위의 Attriute 이름
*/
public static final String USER_KEY = "user";
/**
* ActionForward에서 사용되는 값
*/
public static final String SUCCESS = "success";
/**
* ActionForward 로그인 동작을 나타내는 Tocken
*/
public static final String LOGIN = "login";
/**
* ActionForward welcome 동작을 나타내는 Tocken
*/
public static final String WELCOME = "welcome";
}
7. application.properties(/WEB-INF/src/resources 에 위치)
(애플리케이션 전체에 사용될 메시지들을 정리해 놓은 것)
error.id.required=<li>ID REQUIRED.</li>
error.pwd.required=<li>PASSWORD REQUIRED</li>
error.login.invalid=<li>ID/PASSWORD NOT CORRECT</li>
errors.header=<h3><font color="red">ERROR!</font></h3>
You must correct the following error(s) before proceeding:<UL>
errors.footer=</ul><hr>
8. struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<!-- ========== Form Bean Definitions ================================== -->
<form-beans>
<form-bean name="loginForm" type="login2.LoginForm">
<form-property name="pwd" type="java.lang.String" />
<form-property name="id" type="java.lang.String" />
</form-bean>
</form-beans>
<!-- ========== Global Forward Definitions =============================== -->
<global-forwards>
<forward name="success" path="/main.jsp" />
<forward name="logoff" path="/logoff.do" />
<forward name="login" path="/login.jsp" />
</global-forwards>
<!-- ========== Action Mapping Definitions =============================== -->
<!-- valiedate를 true라고 함으로써 LoginForm의 validate가 호출 됩니다. -->
<action-mappings>
<!-- loginAction에 대한 정의 -->
<action
path="/LoginSubmit"
type="login2.LoginAction"
name="loginForm"
validate="true"
input="/login.jsp"
/>
<!-- logoffAction에 대한 정의 -->
<action
path="/logoff"
type="login2.LogoffAction"
validate="false"
/>
</action-mappings>
<!-- ========== 아래는 스트러츠 Application에서 사용할 Message Resource들을 설정 ====== -->
<!-- 확장자가 properties인 application.properties를 만들어 넣으면 된다 ============ -->
<message-resources parameter="resources.application"/>
</struts-config>
[100%환급,실무전문]빅데이터/SQL/자바/스프링/안드로이드/닷넷C… | 12-27 | 2788 | ||
[채용확정무료교육]오라클자바개발잘하는신입뽑기2개월과정,교육… | 12-11 | 2023 | ||
53 | [평일100%환급7건]웹퍼블리싱,자바&JSP,안드로이드,C#닷넷,SQL기… | 03-15 | 1830 | |
52 | [주말]C#,ASP.NET마스터 | 01-31 | 2000 | |
51 | [기업100%환급,평일주간]SQL기초에서스키마오브젝트,PLSQL,힌트… | 01-31 | 2945 | |
50 | [주말주간]자바&웹,jQUERY,스프링프레임워크,마이바티스 | 01-31 | 1537 | |
49 | [평일주간,평일야간,주말]Spring,MyBatis,Hibernate개발자과정-… | 01-19 | 1859 | |
48 | [평일야간,주말]안드로이드개발자과정(Android기초실무) | 01-11 | 1734 | |
47 | [평일야간,주말주간야간]JAVA,Network&JSP&Spring,MyBatis,Hiber… | 01-03 | 2300 | |
46 | [100%환급,실무전문]빅데이터/SQL/자바/스프링/안드로이드/닷넷C… | 12-27 | 2788 | |
45 | [평일주간]NoSQL,MongoDB,빅데이터기초과정 | 12-19 | 1950 | |
44 | [평일주간야간, 주말]웹퍼블리싱 마스터(HTML5,CSS3,jQUERY,AJAX… | 12-14 | 1930 | |
43 | [채용확정무료교육]오라클자바개발잘하는신입뽑기2개월과정,교육… | 12-11 | 2023 | |
42 | [평일주간]빅데이터하둡기초과정(BigData Hadoop) | 12-09 | 1575 | |
41 | [평일야간]닷넷(C#,Network,ADO.NET,ASP.NET)마스터 | 12-01 | 1800 | |
40 | [기업100%환급]오라클&자바웹스프링신입과정3주(SQL,JAVA,JSP,Se… | 12-01 | 2016 | |
39 | [평일야간,주말]SQL기초에서실무까지(SQL기초,PLSQL,힌트,튜닝) | 12-01 | 1451 |
댓글 없음:
댓글 쓰기