Java/JSP Web Application을 WAR 파일로 만든 후 Tomcat 웹 애플리케이션 서버에 배포하는 법.


본 포스팅은 다음 상황에서의 설명이다.

 -. Ubuntu 16.04 LTS 버전

 -. Tomcat 8.0

 -. 톰캣 가상 호스트를 이용해서 joe.iptime.org에 대한 웹 루트를 /home/joe/www/ROOT/로 변경하였다.

    (톰캣 가상 호스트 설정하는 법은 여기를 참조)


Java/JSP로 개발된 웹 애플리케이션을 실제 서버에 배포할때 WAR 파일을 만들어 배포하게 된다. 그런데 톰캣 가상호스트를 만들어 디폴트 웹 root 디렉토리를 /home/joe/www/ROOT/로 변경하였을 경우 WAR 파일을 배포하는 방법에 대한 것이다.


Ubuntu의 경우 Tomcat의 웹 루트(DocumentRoot)는 /var/lib/tomcat8/webapps/ROOT/이다. 따라서 가상호스트를 만들지 않은 상황에서는 WAR 파일을 /var/lib/tomcat8/webapps 폴더로 FTP 등을 이용해서 올리면 자동으로 WAR 파일을 압축을 풀어서 해당 웹 애플리케이션이 배포가 된다. 만일 압축 해제및 배포가 자동으로 되지 않는다면 터미널 창에서 다음과 같이 tomcat을 재시작해 주면 정상적으로 배포가 된다.


# service tomcat8 restart


그런데 가상 호스트를 만들을 때는 WAR 파일을 어디로 올려야 되는가?

/home/joe/www로 WAR 파일을 올려도 WAR 파일이 자동으로 압축해제 및 배포가 되지를 않는다. 톰캣을 재시작해도 마찬가지이다.


/etc/tomcat8/server.xml을 열어보면 unpackWARs="true" autoDeploy="true"로 되어 있음에도 불구하고 /home/joe/www에 WAR 파일을 업로드해도, 혹은 톰캣을 재시작해도 WAR파일이 자동으로 배포가 되지 않는다.


      <Host name="joe.iptime.org"  appBase="/home/joe/www"

            unpackWARs="true" autoDeploy="true">

... 중 략 ...

       </Host>


이런 경우 다른 더 좋은 방법이 있는지 모르겠으나 톰캣의 디폴트 웹 root인 /var/lib/tomcat8/webapps/에 WAR 파일을 업로드하면 자동으로 배포가 이루어진다. 이렇게 압축이 풀려진 해당 디렉토리와 그 하위 디렉토리 및 전체를 가상 호스트를 만든 해당 웹 루트(여기서는 /home/joe/www/ROOT/)에 복사하는 수 밖에는 없다.  Flower.WAR 파일이라고 한다면 이 파일을 /var/lib/tomcat8/webapps/로 업로드하면 이 디렉토리에 Flower라는 새로운 디렉토리가 생성이 되고 그 하위에 개발했던 웹 애플리케이션의 파일과 해당 디렉토리들이 압축이 풀려져 있다. 따라서 다음 명령을 이용해서 가상 호스트의 해당 웹 root로 복사를 하면 정상적으로 웹 애플리케이션이 구동이 된다.


# pwd

/var/lib/tomcat8/webapps

# cp -r ./Flower/* /home/joe/www/


이클립스에서 WAR 파일을 만드는 방법은 해당 프로젝트 위에 마우스 우측 클릭하여 다음 그림과 같이 진행하면 WAR 파일을 얻을수 있다.






이클립스에서 JSP/Servlet 실행시 아래와 같은 에러가 발생하는 경우가 있다. 내용은 톰캣이 사용하는 포트가 있는데(8005, 8181, 8009) 그 포트를 이미 다른 곳에서 사용하고 있다는 뜻이다.


Several ports (8005, 8181, 8009) required by Tomcat v7.0 Server at localhost are already in use. The server may already be running in another process, or a system process may be using the port. To start this server you will need to stop the other process or change the port number(s).


이럴 경우는 netstat 명령어를 이용하여 위의 포트의 Process ID(PID)를 알아내서 해당 Process를 kill 시켜 버린 후 다시 이클립스로 해당 프로젝트를 실행하면 정상적으로 구동이 된다.


netstat -anop tcp

 

활성 연결


  프로토콜  로컬 주소              외부 주소              상태            PID

  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       948

  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4

  TCP    0.0.0.0:3306           0.0.0.0:0              LISTENING       3596

  TCP    0.0.0.0:5357           0.0.0.0:0              LISTENING       4

  TCP    0.0.0.0:7680           0.0.0.0:0              LISTENING       10260

  TCP    0.0.0.0:8009           0.0.0.0:0              LISTENING       8604

  TCP    0.0.0.0:8181           0.0.0.0:0              LISTENING       8604

  TCP    0.0.0.0:xxxx          0.0.0.0:0              LISTENING       644

  TCP    0.0.0.0:xxxx          0.0.0.0:0              LISTENING       1412

  TCP    0.0.0.0:xxxx          0.0.0.0:0              LISTENING       1296

  TCP    0.0.0.0:xxxx          0.0.0.0:0              LISTENING       2344

  TCP    0.0.0.0:xxxx          0.0.0.0:0              LISTENING       2096

  TCP    0.0.0.0:xxxx          0.0.0.0:0              LISTENING       716

  TCP    0.0.0.0:xxxx          0.0.0.0:0              LISTENING       724

  TCP    0.0.0.0:xxxx          0.0.0.0:0              LISTENING       4

  TCP    127.0.0.1:1235         0.0.0.0:0              LISTENING       3916

  TCP    127.0.0.1:8005         0.0.0.0:0              LISTENING       8604

  TCP    192.168.xxx.xxx:139    0.0.0.0:0              LISTENING       4

  TCP    192.168.xxx.xxx:49651  xxx.xxx.xxx.xxx:443    ESTABLISHED     11008

  TCP    192.168.xxx.xxx:50782  xxx.xxx.xx.x:80        TIME_WAIT       0

  TCP    192.168.xxx.xxx:50837  xxx.xxx.xx.x:80        TIME_WAIT       0

  TCP    192.168.xxx.xxx:50838  xxx.xxx.xx.x:80        TIME_WAIT       0

  TCP    192.168.xxx.xxx:50839  xxx.xxx.xx.x:80        TIME_WAIT       0

... 중 략 ...


이 명령어에서 출력된 내용중 8005, 8181, 8009 포트에 대한 PID가 8604임을 확인할수 있고 해당 Process를 다음과 같이 죽이면 된다.

DOS(커맨더) 창에서 아래 명령어로 해당 Process를 죽이면 된다.


taskkill -f /pid 8604



JSP에서 JSTL의 forTokens 태그의 간단 예제 


<%-- member라는 변수에 value에 있는 값들을 저장 --%>

<c:set var="member" value="홍길동, 고길동, 둘리, 챨리"/>


<%-- items에 지정된 배열 혹은 Collection 데이터들을 delims가 지정한 문자인 ,를 구분자로

          각각의 데이터를 var이 지정한 변수에 저장. 

          Java의 foreach문과 StringTokenizer가 결합된 형태이다.

--%>

<c:forTokens var="data" items="${member }" delims=",">

<font face="궁서" size="25"><b><c:out value="${data },"/>&nbsp;</b></font>

</c:forTokens>


출력결과는


홍길동,  고길동,  둘리,  챨리,  




JSP에서 MySQL을 이용하여 Database Connection Pool(DBCP) 구현하기


Database와 Connection을 맺는 작업은 좀 무거운 작업으로 설명되어 있고 이에 반해서 Connection Pool을 이용하는 것은 DB와의 연결을 구현하는데 아주 좋은 방법으로 평가되고 있다.


"Rather than getting the connection object through the DriverMan-

ager class, we get them through an instance of the DataSource class. This

is considered a best practice because a DataSource object maintains a pool

of persistent database connections in order to eliminate the time consuming

step of establishing a database connection each time the application wishes

to interact with the database."

 -. by David Turner, Jinsok Chae of 'Java Web Programming with Eclipse'


그런데 Oracle과의 DBCP에 대해서는 많이 나와있는데 MySQL과의 연동에 대해서는 자료가 많지 않은듯 하다.

Eclipse에서의 DBCP를 위한 환경설정을 어떻게 할지를 정리해 본다.


 -. DBCP를 위해 필요한 라이브러리는 아래와 같고 이것을 이클립스의 WebContent/WEB-INF/lib 아래에 복사해 둔다. 혹은 톰캣이 설치되어 있는 디렉토리의 lib 폴더에 복사해 둔다.

    ㆍcommons-collections4-4.1.jar

    ㆍcommons-pool2-2.5.0.jar

    ㆍcommons-dbcp2-2.2.0.jar

    ㆍmysql-connector-java-5.1.40-bin.jar


위 라이브러리들은 http://commons.apache.org/에서 다운받을수 있다.


이클립스 상의 Project Explorer의 Servers 항목의 하위 항목 중 context.xml을 열어서 다음의 내용을 추가해 준다.

추가하는 위치는 <Context>...</Context> 사이이다.


<Context>

... 중 략 ...

  <Resource 

  name=""

  type="javax.sql.DataSource"

  auth="Container"

  maxActive="30"

  maxIdle="3"

  maxWait="3000"

  username=""

  password=""

  testOnBorrow="true"

  driverClassName="com.mysql.jdbc.Driver"

  url="jdbc:mysql://localhost:3306/?autoReconnect=true"

  />

</Context>


  DBCP를 이용할 Java 코드에서 지칭할 이름. 즉 Java코드와 context.xml에서 설정한 DBCP의 설정 부분을 연결하는 연결 고리역할 하는 이름이다. 이 이름과 Java 소스 코드 상에서의 명칭이 대소문자가 같아야 하고 이 명칭이 잘못될 경우 다음과 같은 에러가 발생한다.  


Name [MYmysqles] is not bound in this Context. Unable to find [MYmysqles].


그리고 이 두 양자간의 이름이 일치 하지 않을 경우 dataSource.getConnection()에서 java.lang.NullPointerException 에러가 발생한다.


본 예제에서는 ①에 jdbc/MYmysqles라고 지정했다. 

name="jdbc/MYmysqles"

이럴 경우 Java 소스에서는 다음과 같이 표현하게 될 것이다. 즉 context.xml의 name 항목에 지정한 이름과 아래 코드의 envContext.lookup()에서 지정하는 이름이 동일해야 한다는 것이다.


Context context = new InitialContext();

Context envContext = (Context)context.lookup("java:comp/env"); 

DataSource dataSource = (DataSource)envContext.lookup("jdbc/MYmysqles");


  MySQL에 접속하기 위한 계정의 ID


  MySQL에 접속하기 위한 계정의 password


  MySQL에 있는 사용할 실제 DB 명. 여기서는 mysql을 사용하고자 한다. 


여기서 아래 2줄의 코드를 

Context envContext = (Context)context.lookup("java:comp/env"); 

DataSource dataSource = (DataSource)envContext.lookup("jdbc/MYmysqles");


다음과 같이 한줄의 코드로 표현해도 가능하다.

 

dataSource = (DataSource)context.lookup("java:comp/env/jdbc/MYmysqles");


이하 나머지는 JSP의 DB 연동하는 일반적인 코드로 구현하면되므로 나머지는 생략.



JSP(Java)에서 MySQL 연동하기


Java에서 MySQL 연동하는 코드 자체는 단순하고 간단하다. 

 ① 연동을 위해 필요한 2개의 클래스 : Connection, DriverManager

 ② 필요한 클래스를 import 한다.

    <%@page import="java.sql.DriverManager"%>

    <%@page import="java.sql.Connection"%>

 ③ 연동을 위해 필요한 .jar 라이브러리(mysql-connector-java-5.1.40-bin.jar)를 톰캣이 설치된 디렉토리의 lib 폴더에 복사해 둔다. 혹은 해당 프로젝트의 \WebContent\WEB-INF\lib 아래에 복사해 둔다.

     예) D:\apache-tomcat-7.0.69\lib에 복사해 둔다.


코드는 아래와 같다.


<%@page import="java.sql.DriverManager"%>

<%@page import="java.sql.Connection"%>

<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>Insert title here</title>

</head>

<body>

<%

Connection conn = null;

      

                //localhost는 MySQL이 설치된 곳의 IP

                //mysql : DB 명

                //3306 : MySQL 접속을 위한 디폴트 포트

String url = "jdbc:mysql://localhost:3306/mysql";

String id = "root";                     //MySQL에 접속을 위한 계정의 ID

String pwd = "xxxxxxx";            //MySQL에 접속을 위한 계정의 암호

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection(url, id, pwd);

out.println("<h1>MySQL DB 연결 성공</h1>");

%>

</body>

</html>


실행 중에 만일 아래와 같은 에러가 발생한다면 이 문제는 위 ③을 하지 않음으로 인한 문제이다. ③과정을 처리하면 된다.


org.apache.jasper.JasperException: An exception occurred processing JSP page /connect.jsp at line 19


18:

19: Class.forName("com.mysql.jdbc.Driver");

20: conn = DriverManager.getConnection(url, id, pwd);

21:


... 중 략 ...


javax.servlet.ServletException: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver


위의 코드는 로컬 상에서(JSP가 구동되는 곳과 MySQL이 설치된 곳이 동일 컴퓨터일 경우)의 MySQL 연동하는 법이다.

그런데 개발을 할때 원격의 서버에 있는 MySQL과 연동하면서 개발하는 경우가 있다. 이때는 아래 코드를 


String url = "jdbc:mysql://localhost:3306/mysql";


다음과 같이 IP 주소 혹은 도메인 이름으로 접속해야 한다.

String url = "jdbc:mysql://192.168.x.x:3306/mysql";


이렇게 MySQL에 접속을 시도했을 때 다음과 같은 에러가 발생한다면 


org.apache.jasper.JasperException: An exception occurred processing JSP page /connect.jsp at line 21


19:

20: Class.forName("com.mysql.jdbc.Driver");

21: conn = DriverManager.getConnection(url, id, pwd);

22:


...중 략...


javax.servlet.ServletException: java.sql.SQLException: null,  message from server: "Host 'xxxx' is not allowed to connect to this MySQL server"


이 에러는 MySQL이 외부 접속을 허용하지 않음으로 인한 에러이다.

이 문제에 대한 해법은 아래 링크 참조


MySQL의 외부 접속 허용하기(외부 IP에서의 접속 허용하기)



JSP/Servlet을 이용하여 웹 프로그램을 개발하다보면 DB를 사용하는 일은 통상적으로 있는 일이다. DB의 성격상 보안이 잘 유지되어야 할텐데 이때 Java 소스 코드 안에 DB 접속 정보를 그대로 코딩하는 경우가 있다. 이는 보안상 결코 바람직 하지 않은 일이다.

물론 Java(Servlet)을 컴파일한 class 파일만 서버에 올리면 일단 해당 정보가 막바로 보이지는 않겠지만 좀더 보안을 생각한다면 Servlet의 초기화 파라미터를 이용하는 것이 더 좋은 방법일 것이다.

Servlet 초기화 파라미터는 모든 Servlet에서 사용할수 있는 것이 아니라 특정 Servlet에 국한되어 사용하는 경우이다. 

해당 프로젝트의 web.xml 안에 해당 Servlet이 생성될 때 사용할 데이터들을 작성해 두면 된다. 


<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

  <display-name>ExServlet</display-name>

  <welcome-file-list>

    <welcome-file>index.html</welcome-file>

    <welcome-file>index.htm</welcome-file>

    <welcome-file>index.jsp</welcome-file>

    <welcome-file>default.html</welcome-file>

    <welcome-file>default.htm</welcome-file>

    <welcome-file>default.jsp</welcome-file>

  </welcome-file-list>

  <servlet>

  <servlet-name>OhServlet</servlet-name>

  <servlet-class>com.joe.myservlet.HelloServlet</servlet-class>

  </servlet>

  <servlet-mapping>

  <servlet-name>OhServlet</servlet-name>

  <url-pattern>/OhSRLT</url-pattern>

  </servlet-mapping>

</web-app>


이때 초기화 파라미터를 작성하는 위치는 이 초기화 데이터를 사용할 Servlet의 태그 안에 작성해야 한다. 이 경우에는 com.joe.myservlet.HelloServlet에서 초기화 데이터를 사용하고자 한다고 가정하면 아래와 같이 작성을 하면 된다.


  <servlet>

  <servlet-name>OhServlet</servlet-name>

  <servlet-class>com.joe.myservlet.HelloServlet</servlet-class>

  <init-param>

  <param-name>myDB</param-name>

  <param-value>jdbc:mysql://①:3306/②?autoReconnect=true</param-value>

  </init-param>

  <init-param>

  <param-name>dbUser</param-name>

  <param-value>hisUser</param-value>

  </init-param>

  <init-param>

  <param-name>dbPW</param-name>

  <param-value>qwerty1</param-value>

  </init-param>

  </servlet>

  <servlet-mapping>

  <servlet-name>OhServlet</servlet-name>

  <url-pattern>/OhSRLT</url-pattern>

  </servlet-mapping>


여기에서 위 ①에는 MySQL이 설치되어 있는 서버의 IP 주속 혹은 도메인 이름을, ②에는 사용할 Database 이름을 명기하면된다.

다음과 같은 형태가 될 것이다.


<param-value>jdbc:mysql://118.277.xxx.x:3306/theDB?autoReconnect=true</param-value>

혹은

<param-value>jdbc:mysql://myblog.or.kr:3306/theDB?autoReconnect=true</param-value>


그러면 이렇게 작성된 초기화 값을 Servlet에서 사용할려면 ServletConfig 인터페이스의 getInitParameter() 메소드를 이용해서 초기화 파라미터의 값을 가져올수 있다.

ServletConfig 인터페이스에 대한 Oralce의 API 문서에는 다음과 같이 설명되어 있다.


public interface ServletConfig

A servlet configuration object used by a servlet container to pass information to a servlet during initialization.


All Known Implementing Classes:

GenericServlet, HttpServlet


package com.joe.myservlet;


public class HelloServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

... 중 략 ...


private void doAction(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException 

{


... 중 략 ...

//아래에서 getInitParameter() 메소드를 막바로 사용할수 있는 이유는 본 클래스가 HttpServlet을 

//상속받았는데 HttpServlet이 ServletConfig라는 interface을 implement했기 때문이다.

//즉 getInitParameter()는 ServletConfig 인터페이스의 메소드인데 HttpServlet이

//이 ServletConfig를 구현했기 때문에 아래에서 막바로 사용가능한 것이다.

String db = getInitParameter("myDB");

String dbUser = getInitParameter("dbUser");

String dbPw = getInitParameter("dbPW");

... 중 략 ...

     PrintWriter out = response.getWriter();

out.println("<hr/>");

out.println("db : " + db+"<br/>");

out.println("user : " + dbUser+"<br/>");

out.println("dbPassword : " + dbPw+"<br/>");

out.close();

}



meta 태그를 이용해서 일정 시간 경과하면 특정 웹 페이지로 자동 이동하기


아래 코드는 3초 후에 같은 경로상의 MyJsp.jsp로 이동한다.


<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<title>Insert title here</title>

<meta http-equiv="Refresh" content="3;url=./MyJsp.jsp">

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<style type="text/css">

.joe {color:Green; font-size:30pt;}

</style>

</head>

<body>

<span class="joe">This is Test</span>

<p/>

<input type="text" size="10" value=<%out.println("방가 방가"); %>>

</body>

</html>


만일 네이버로 이동하고 싶다면 아래와 같이 http를 붙여서 다음과 같이 수정한다.

<meta http-equiv="Refresh" content="3;url=http://www.naver.com">


만일 다른 페이지로의 이동 없이 현재 페이지를 1문마다 자동으로 새로 고침할려면 다음과 같이 이동 url없이 

<meta http-equiv="Refresh" content="60">



JSP에서 EL(Expression Language)이 값을 출력하지 못할 경우


JSP에서 EL을 사용하여 값을 출력하고자 할때 다음 코드에서 str1의 값 "Hello world~~~"이 정상적으로 출력이 될까?


<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>

<jsp:useBean id="member" class="com.joe.test.MemberInfo" scope="page"/>

<jsp:setProperty name="member" property="id" value="abcde" />

<jsp:setProperty name="member" property="pwd" value="kog" />

<jsp:setProperty name="member" property="name" value="고길동" />    

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>EL 사용시 주의 사항</title>

</head>

<body>

<%

String str1 = "Hello world~~~";

%>

아이디 : <jsp:getProperty name="member" property="id"/><br/>

비밀번호 : <jsp:getProperty name="member" property="pwd"/><br/>

이름 : <jsp:getProperty name="member" property="name"/><br/>

<hr/>

아이디 : ${member.id }<br/>

비밀번호 : ${member.pwd }<br/>

이름 : ${member.name }<br/>

<hr/>

str1 : ${str1 }<br/>

</body>

</html>


정답은 출력되지 않는다이다.  출력 결과는 다음과 같다.


아이디 : abcde

비밀번호 : kog

이름 : 고길동

아이디 : abcde

비밀번호 : kog

이름 : 고길동

str1 : 


str1에는 아무것도 출력되지 않는다. 이유가 뭘까? 저 값이 출력되게 할려면 어떻게 해야 할까?

관건은 EL에서 사용할수 있는 변수의 범위(scope)와 관련된 문제이다. 즉 EL 태그가 값을 참조할수 있는 가용 영역(범위, scope)의 문제 때문이다.

EL 태그가 값을 가져올수 있는 영역은 pageContext 영역에 있는 변수의 값, request 영역에 있는 값, session 영역에 있는 값, application 영역에 있는 값이다.

따라서 위의 코드를 다음과 같이 수정하면 Hello world~~~라는 문자열이 정상적으로 출력이 된다.


<%

String str1 = "Hello world~~~";

    

                //다음 4개 중 어느 하나를 추가하면 str1의 값을 EL에서 정상적으로 출력가능하다.

pageContext.setAttribute("str1", str1);

//request.setAttribute("str1", str1);

//session.setAttribute("str1", str1);

//application.setAttribute("str1", str1);

%>


이때 str1의 값을 현재 페이지에서만 사용하면 되는 상황이라면 pageContext, request 영역에 str1의 값을 저장하면 될 것이다(pageContext.setAttribute() 혹은 request.setAttribute() 사용).

만일 좀 더 넓은 범위에서 사용이 필요하다면 session 영역에 저장하면 될 것이다. 

혹은 웹 애플리케이션 전 영역에서 서버 가동 동안 계속 사용이 필요하다면 application 영역에 값을 저장하면 될 것이다(application.setAttribute() 사용).


혹은 JSTL을 사용하여 


<%

     String str1 = "Hello world~~~";

%>

대신에 다음과 같이 JSTL 태그를 사용하면 pageContext, request, session.... 등 사용 없이 EL에서 정상적으로 값을 참조가능 하다.


<%

    <c:set var="str1" value="Hellow world~~~" />

%>


같은 개념으로 다음 코드는 어떻게 될까?


<%

    String myId = (String)request.getAttribute("id");

    String mAtt = (String)request.getAttribute("ctrlAttr");

%>


(1) 컨트롤럴에서 넘어온 값(myId) : ${myId}<br/>

(2) 컨트롤럴에서 넘어온 값(id) : ${id}<br/>

(3) 컨트롤럴에서 넘어온 값(mAtt) : ${mAtt}<br/>

(4) 컨트롤럴에서 넘어온 값(ctrlAttr) : ${ctrlAttr}<br/>


결과는 (1)(3)은 아무 값도 출력되지 않는다.

반면에 (2)(4)은 정상적으로 값이 출력이 된다.

이 경우는 request 영역에 이미 값이 저장되어 있으므로 저장된 값을 가져오기 위한 key 값인 id, ctrlAttr을 막바로 사용하면된다. 


만일 다음과 같이 parameter 형태로 넘어올 경우 EL에서 값을 참조하는 방법은 다음과 같다.


<jsp:forward page="toPage.jsp">

<jsp:param name="mUrl" value="www.naver.com"/>

<jsp:param name="mUser" value="고길동"/>

</jsp:forward>


이 경우 toPage.jsp에서 다음과 같이 파라미터로 넘어오는 값을 받을 수 있다.


<body>

<%

String tUrl = request.getParameter("mUrl");

String tUser = request.getParameter("mUser");

%>


<h1>여기는 toPage.jsp입니다.</h1>

<ul>

<li>url : <%=tUrl %></li>  <!-- 정상적으로 값이 출력된다 -->

<li>user : <%=tUser %></li>

</ul>

<hr/>

<ul>

<li>*url => ${mUrl }</li> <!-- 이런식으로는 값을 참조할 수 없다. -->

<li>*user => ${mUser }</li>

</ul>


<hr/>

<ol>

<li>URL : ${param.mUrl }</li>  <!-- 정상적으로 값이 출력된다 -->

<li>USER : ${param.mUser }</li>

</ol>

</body>



다른 PC에서 개발하던 (프로젝트들이 담겨 있는) 워크 스페이스를 통채로 복사해 와서 이클립스로 열었더니 아래 그림과 같이 프로젝트들 이름마다 빨간 색 엑스박스가 떴다. 이클립스에서의 이 문제는 흔히 만나는 문제이다.




이럴 경우는 대부분 이전 PC에서의 JDK, Tomcat 등의 개발 환경 설정과 현재 PC에서의 개발환경 설정이 달라서 생기는 문제이다.

즉 JDK, Tomcat 등의 클래스 패스가 잘못됨 때문이다.


해당 프로젝트에서 마우스 우 클릭 ⇒ 팝업 메뉴의 Build Path ⇒ Configure Build Path... ⇒ Libraries 탭으로 이동한다.




아래 이미지에서 보는 것 처럼 JRE의 클래스 패스가 잘못되었다고 빨간색 엑스박스가 표시되어 있다. 해당 항목을 클릭하면 우측에 Remove 버튼이 활성화되고 이 버튼을 클릭해서 해당 항목을 삭제한다. 




그 후에 Add Library... 버튼을 클릭한다. 그 후에 JRE System Library를 선택 후 Next 버튼으로 넘어간다.




아래 그림과 같이 현재 PC에 설치되어 있는 JRE를 선택한다. 디폴트가 잡혀있지 않다면 우측의 Installed JREs... 버튼을 클릭해서 현재 PC에 설치된 JRE를 선택한다. Finish 버튼을 눌러 완료한다. 




만일에 아래 그림과 같이 Java Build Path에 톰캣 라이브러리가 없는 경우가 있다.




이때도 우측의 Add Library... 버튼 클릭. Add Library 창에서 이번에는 Server Runtime 항목을 선택 후 Next 버튼. 새로운 창에서 현재 PC에 설치되어 있는 Apache Tomcat v7.0을 선택 후 Finish.


이렇게 하면 외부 개발환경과 다른 문제로 인해 발생하는 문제들을 해결할수 있다.



JSP로 웹 프로젝트를 개발하다 보면 JSP의 변수를 JavaScript에서 사용해야 할 일이 종종발생한다.

간단한 JSP 변수로부터 ArrayList의 값을 자바스크립트에서 사용해야 할 경우도 있다.

아래 코드는 JSP의 변수를 JavaScript에서 사용하는 간단한 코드이다.


<%@page import="java.util.ArrayList"%>

<%@ page language="java" contentType="text/html; charset=EUC-KR"

    pageEncoding="EUC-KR"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>Insert title here</title>

</head>

<body>

<!-- 

아래 코드는 JSP의 변수를 자바스크립트에서 사용하는 방법에 대한 코드이다.

 -->

<script type="text/javascript">

<%

ArrayList<String> arr = new ArrayList<String>();

arr.add(0, "첫 번째");

arr.add(1, "두 번째");

arr.add(2, "세 번째");

arr.add(3, "네 번째");

arr.add(4, "다섯 번째");

for(int i=0; i<5; i++)

{

%>

//alert("i: "+ i); //이런 식으로는 다음 에러 발생 Uncaught ReferenceError: i is not defined 

//이런식으로 해야 정상적으로 JSP 변수의 값을 자바스크립트에서 사용 가능

//JSP쪽 변수 i의 값을 자바스크립트에서 다음과 같이 사용한다.

alert("i~: " + <%= i %>); 

//아래 코드의 경우는 다음 에러 발생. Uncaught SyntaxError: missing ) after argument list

//따옴표로 감싸야한다. 왜냐하면 데이터가 문자열이기 때문에

//console.log("arr : ", <%= arr.get(i) %>); 

console.log("arr[", <%= i %>, "] ⇒ ", '<%= arr.get(i) %>'); //가능

//위 console.log()에서 다음과 같이 출력된다.

//arr[ 0 ] ⇒  첫 번째

//arr[ 1 ] ⇒  두 번째

//arr[ 2 ] ⇒  세 번째

//arr[ 3 ] ⇒  네 번째

//arr[ 4 ] ⇒  다섯 번째

<%

}

%>


</script>

</body>

</html>


+ Recent posts