JSP 구구단

ChoRong0824·2023년 4월 2일
0

Web

목록 보기
23/25
post-thumbnail

JSP/서블릿 간단히 연습
2023.04

프로젝트 생성

  • 꼭 메이븐으로 만들어줘야함.
  • archetype-webapp 으로 생성.
  • (Arhetype)버전은 크게 상관없음.

porm.xml

여기엔 리포지토리를 넣을 예정.

깃 처음 연동

  1. git init 로컬환경의 저장소에 파일을 올려서 깃허브에 올리겠다는 뜻
  2. git config --global user.name "sjMun09"
  3. git config --global user.email "ohoh7391@naver.com"
  4. 로컬에 있는 저장소랑 깃허브랑 연결 git remote origin https://github.com/sjMun09/sjMun09-JSP_community.git
    error 뜰 시, 저장소 추가가 안된 거임. git remote add origin + 주소
  • 깃 저장소 확인 : git remote -v
  1. 깃에 추가 git add .
  2. 세팅(커밋) git commit -m "세팅"
  3. 푸쉬 git push -u origin main

참고, 2번째 연동부터는 푸쉬 전에 항상 pull 해줘야함.

.idea 는 올라가면 안됨.


한글설정


Help 에서 Edit Custom VM Options 에서
한글 설정해줘야함.
-Difile.encoding=UTF-8 가 들어가 있어야함.

어떤 설정을 했을 때는, 항상 재시작 해주는 것이 좋음.
Just restart 눌러줌

세팅

IntelliJ 누르고 setting 누르고 Plugins 에서 필수 설치해줘야함
1. lombok
2. Smart Tomcat

webapp에 index.html 파일 생성

! 하고 탭치면 html 기본형식 불러옴

한글로 읽을 수 있게 해당 코드만 남기고 다 지움.

프로젝트를 만들었으니, 이젠 톰캣을 등록해야함.


configurences 누른 후, 톰캣 서버를 추가해준다.

이후, 현재 내가 프로젝트를 하고 있는 디렉토리의 경로를 설정해줘야 하기때문에,
디렉토리가 마지막에 webapp 인지 꼭 확인하고 설정해주기.
그후, Context path 에는 /만 남기고 나머진 다 지우면된다. 그래야지 로컬호스트 8080이 됨.


  • 톰캣 서버를 사용하는방법

    Deployment에서 + 누른 후, Artifact를 누른뒤 프로젝트 배포 모듈을 적용.

    적용하고 난 뒤 Application context 부분을 보면 경로가 설정되어 있는데,
    이것을 /로 변경해줘야 기본 주소가 http://localhost:포트번호/가 된다.
    만일 원하는 기본 경로가 있다면 그것으로 변경하면 된다.

기타 상식

  • 우리가 만드는 프로젝트는 톰캣 입장에서는 하나의 모듈(JSPcommunity)이고, 모듈 안에는 여러 서블릿이 존재 및 수많은 모듈이 존재.
  • 서블릿 하나하나가 하나의 사이트 주소라고 생각하면됨.
    http://localhost:8081/JSPcommunity/(JSP)

main 파일에

  • java 디렉토리 생성
  • 메인클래스 생성

어노테이션

http://localhost:8081/JSPcommunity/hello (이전에 상식에 했던 내용)
@WebServlet("/hello") 어노테이션을 통해서 클래스를 만들게 되면, 클래스가 서블릿으로 인식됨 (톰캣이 알아서 인식)

필요한 라이브러리

  • lib -> jsp-api.jar servlet-api.jar 필수적으로 필요하고,
    여기에 추가적으로 필요한 라이브러리가 있음.
  • maven repository 검색해서 사이트로 이동, jakarta servle 검색,

    제일 많이 쓰는 버전으로 누르면 위와같이 코드가 보임.
    복사한 후,

pom.xml의 dependencies 태그 안에 붙여넣어줌. (우측상단 메이븐 눌러서 적용)

로직

  • 자카르타 api는 기본적으로 톰캣에도 설치되어 있는 상태.
    우리 프로세스에 다운받아서 들어갈 필요없음.
    프로바이드는 이미 자카르타가 있고, 톰캣에도 자카르타가 있으니까,
    자카르타 api는 컴파일 할 때만 있으면 된다는 뜻임.
    그래서 당장 프로젝트의 컴파일을 하기 위해선 자카르타가 꼭 필요함.
    즉, 컴파일 할 때만 필요함. (최종에선 필요가 없음, 톰캣에 자카르타가 있기때문)

  • main 클래스 삭제.(필요 x)
  • HelloServlet 생성

    어노테이션 및 상속 필수
    오버라이드 필요한 메서드 불러옴.
    이후,
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    // 메서드 오버라이드
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter().append("HI!!"); // 이걸 쓰게되면 주소창에 localhost:8081/hello 를 치면 HI!! 이 출력됨.

    }
}

한글 안깨지게 해당 코드 추가.

req.setCharacterEncoding("UTF-8"); //들어오는 데이터를 UTF-8로 해석
        resp.setCharacterEncoding("UTF-8"); // 완성되는 HTML의 인코딩을 UTF-8로 함.
        resp.setContentType("text/html; charset-utf-8"); // 브라우저에게 우리가 만든 결과물이 UTF-8이라고 알리는 의미임.

세팅 변경

개발할 때, 편리하게 도와주는 도구 (프로젝트 생성마다 해줘야함)
append(" ")에 내용 추가 및 수정할 때, 웹에 바로 반영되게 하기 위해서 설정

  • Allow auto 부분 체크
  • setting에 compile 검색, Builde project auto~ 체크해줌

    이렇게 까지만 하면 반영이 안됨.
    톰캣 설치파일로 가서, conf에 들어가서 context.xml 파일을 열어서 reloadable="true"로 설정해줘야함.

이렇게 해도 적용이 안되면, invalidate Caches 에서 just restar 하면 됨.


구구단 클래스 생성

@WebServlet("/gugudan")
public class GugudanServlet extends HttpServlet {

해당 부분은 당연히 필수적으로 들어가야 하는부분

  • 이후, ctrl + 엔터 로 오버라이드 메서드 doget 생성

한글 설정

req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset-utf-8");
resp.getWriter().append(String.format("<h1>%d단</h1>", dan));
resp.getWriter().append("<h1>%d단</h1>".formatted(dan));
  • 위에 코드에서 (위 || 아래) 코드로 작성하면 됩니다. (자바 버전에 따라 문법이 다른 것 같음. 뜻은 똑같음)
  • %d 랑 위의 dan 이랑 치환됨.

파라미터 1개 받는 방법

http://localhost:8081/gugudan?dan=5 를 만들고 싶음

  • 여기 코드에서, =을 기준으로 우측에 있는 5는 파람 벨류임.
    (주소창에 있는 dan=5 가 파라미터, //localhost:8081/gugudan는 url 패스)
    근데 이러면 5는 문자열로 들어옴. (정수로 표현하고 싶으면, 숫자로 바꿔줘야함)
  • req.getParameter("dan"); // 이러면 파라미터와 파라미터의 벨류를 받아올 수 있음.
    (String으로 읽기 때문에, 정수로 표현하고 싶으면, 숫자로 바꿔줘야함)
  • (바꿔준 코드)
 		int dan = Integer.parseInt(req.getParameter("dan"));
        resp.getWriter().append(String.format("<h1>%d</h1>", dan));
        for (int i = 1; i < 10; i++) {
            resp.getWriter().append(String.format("<div>%d * %d = %d</div>", dan, i, dan * i));

즉, getParameter를 하게 되면 파라미터를 받아올 수 있음.

파라미터 2개 받아올 때

  • http://localhost:8081/gugudan?dan=5&limit=4
    & 뒤에 넣어주면 됨.

  • (수정)

 int dan = Integer.parseInt(req.getParameter("dan"));
        int limit = Integer.parseInt(req.getParameter("limit"));

        resp.getWriter().append(String.format("<h1>%d</h1>", dan));
        for (int i = 1; i <= limit; i++) {
            resp.getWriter().append(String.format("<div>%d * %d = %d</div>", dan, i, dan * i));
        }

서블릿 = HTML 생성기 라고 생각하면 쉬움.


  • 요청을 보통 request라고 함.
  • 요쳥을 하면, 다시 처리를 해서 돌아오는 것을 response

응답은 headerbody가 있음.
get.writer() 할 때마다 html의 태그가 들어감.

  • 내부적으로 모아졌다가 한번에 합침. (톰캣에서 렌더링을 함.)
    즉, append를 계속 톰캣에 쌓아둠.

정리하면, req 는 요청, resp는 요청한 것을 내가 보는 화면에 보여줌.

근데, 이렇게 계속 resp 등 이렇게 코드를 계속 짜면 귀찮으니까, rq객체 도입할거임.

(요청, 응답) 자주 사용하는 것을 묶어서 객체로 만들거임 -> (아래코드 참조)

  • (try_catch 가 필요할 경우)
    위와 같이 빨간줄이 뜰 것이다. 이럴 때는 사진과 같이 해당 기능을 눌러주면 try-catch해줌.

rq 클래스

import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class Rq {
    private final HttpServletRequest req;
    private final HttpServletResponse resp;

    public Rq(HttpServletRequest req, HttpServletResponse resp) {
        // final 로 만들게 되면 this.는 필수적으로 추가되어야함.
        this.req =req;
        this.resp=resp;


        try {
            req.setCharacterEncoding("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset-utf-8");
    }

    // default 를 쓰는 이유는, param 벨류가 안들어올 수도 있으니까, default
    public int getIntParam(String paramName, int defaultValue) {
        String value = req.getParameter(paramName);

        // 없을 경우
        if (value == null) {
            return defaultValue;
        }
        /*
        - 문장으로 들어오기 때문에, 형변환 해줌.
        return Integer.parseInt(value);
        - 근데 이렇게만 하면 예외로 5단 등 '단'이 추가되면 실행 자체가 안되기 때문에, 예외처리를 해줄거임.
        */
        try {
            return Integer.parseInt(value);
        }
        // 정수를 규정하는 예외 규정
        catch (NumberFormatException e) {
            return defaultValue;
        }
    }
    // 계속 쓰기 귀찮으니까 여기에 처리해줌.
    public void appendBody(String str) {
        try {
            resp.getWriter().append(str);
        } catch (IOException e) {
            // 아래 코드는 프로그램 꺼지면 바로 꺼지는 거임. (없애면 그냥 계속 돌아감)
            throw new RuntimeException(e);
        }
    }
}

gugudan 클래스

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

// 필수 양식
@WebServlet("/gugudan")
public class GugudanServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset-utf-8");
        */
        // 위 코드 대신 이젠 rq 객체 생성.
        Rq rq = new Rq(req, resp);

        /*
        int dan = Integer.parseInt(req.getParameter("dan"));
        int limit = Integer.parseInt(req.getParameter("limit"));
        */

        // 들어오지 않으면 0을 넣어준다는 소리.
        int dan = rq.getIntParam("dan", 0);
        int limit = rq.getIntParam("limit", 0);

        resp.getWriter().append(String.format("<h1>%d단</h1>", dan));
        /* 이런 식으로도 작성 가능.
        String rs = String.format("<h1>%d단</h1>", dan);
        resp.getWriter().append(rs);
        */
        for (int i = 1; i <= limit; i++) {
            resp.getWriter().append(String.format("<div>%d * %d = %d</div>", dan, i, dan * i));
        }
    }
}

JSP 방식으로 구구단 구현

  • 서블릿은 HTML 생성기. (태그가 눈에 잘 안들어옴)

불편하게도, jsp 자동완성 기능이 없음.
야매로 인위적으로 파일 확장자명을 바꿔줘서 사용할 수 있음.
setting -> Editor -> File type -> HTML -> *.jsp, *.jspf 추가.
이러면 확장자가 jsp로 인식되지만, html 코드를 자동완성을 쓸 수 있음.
(인텔리제이 커뮤니티에서 사용되지 않음) -> 좋은 방식은 아님. 오류 코드를 발견할 수 없음.
코드 추가
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
이 코드가 있어야지만 제대로 작성가능.
<% = %> 치환
<h1><%=dan%>단</h1> // 치환해줌,<% int dan=9; %> // 자바 문법 사용가능,

  • jsp 는 단축 표현 사용할 수 없음 그래서 req.getParam~~이 안됨, request.getPa~~로 작성.

웹 백엔드는

  • 보통 MVC 패턴으로 구현함.
  • 모델 2 방식은, 서블릿과 jsp의 방식을 확실하게 구분해주자는 소리.

Model2로, 구분, 최종 코드

GugudanServlet.java

package com.sbs.exam.servlet;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

// 필수 양식
@WebServlet("/gugudan")
public class GugudanServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset-utf-8");
        */
        // 위 코드 대신 이젠 rq 객체 생성.
        Rq rq = new Rq(req, resp);

        /*
        int dan = Integer.parseInt(req.getParameter("dan"));
        int limit = Integer.parseInt(req.getParameter("limit"));
        */

        // 들어오지 않으면 0을 넣어준다는 소리.
        int dan = rq.getIntParam("dan", 0);
        int limit = rq.getIntParam("limit", 0);

//        rq.appendBody(String.format("<div class=\"a\">%d단</div>\n", dan));
//        //rq.appendBody(String.format("<h1>%d단</h1>", dan));
//        // 1. resp.getWriter().append(String.format("<h1>%d단</h1>", dan));
//        /* 2. 이런 식으로도 작성 가능.
//        String rs = String.format("<h1>%d단</h1>", dan);
//        resp.getWriter().append(rs);
//        */
//        for (int i = 1; i <= limit; i++) {
//            resp.getWriter().append(String.format("<div>%d * %d = %d</div>", dan, i, dan * i));
//        }


        // request 에 정볼르 담는다.
        // 왜냐하면, 나중에 gugudan2.jsp 에서 해당 내용을 꺼낼 수 있기 때문에.
        // 키, 벨류 (꺼내 쓰는거라고 보면됨)
        req.setAttribute("dan",dan);
        req.setAttribute("limit",limit);

        // 그냥 외워야함.
        // gugudan2.jsp 에게 나머지 작업을 토스한다고 생각하면 됨.
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/gugudan2.jsp");
        requestDispatcher.forward(req, resp);
        // url을 입력했으니까 forward에서 처리해라 라는 소리.
    }
}

HelloServlet.java

package com.sbs.exam.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;


@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    // 메서드 오버라이드
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        req.setCharacterEncoding("UTF-8"); //들어오는 데이터를 UTF-8로 해석
        resp.setCharacterEncoding("UTF-8"); // 완성되는 HTML의 인코딩을 UTF-8로 함.
        resp.setContentType("text/html; charset-utf-8"); // 브라우저에게 우리가 만든 결과물이 UTF-8이라고 알리는 의미임.

        resp.getWriter().append("안녕하세여, ddadsad."); // 이걸 쓰게되면 주소창에 localhost:8081/hello 를 치면 HI!! 이 출력됨.

    }
}

Rq.java

import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class Rq {
    private final HttpServletRequest req;
    private final HttpServletResponse resp;

    public Rq(HttpServletRequest req, HttpServletResponse resp) {
        // final 로 만들게 되면 this.는 필수적으로 추가되어야함.
        this.req =req;
        this.resp=resp;


        try {
            req.setCharacterEncoding("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset-utf-8");
    }

    // default 를 쓰는 이유는, param 벨류가 안들어올 수도 있으니까, default
    public int getIntParam(String paramName, int defaultValue) {
        String value = req.getParameter(paramName);

        // 없을 경우
        if (value == null) {
            return defaultValue;
        }
        /*
        - 문장으로 들어오기 때문에, 형변환 해줌.
        return Integer.parseInt(value);
        - 근데 이렇게만 하면 예외로 5단 등 '단'이 추가되면 실행 자체가 안되기 때문에, 예외처리를 해줄거임.
        */
        try {
            return Integer.parseInt(value);
        }
        // 정수를 규정하는 예외 규정
        catch (NumberFormatException e) {
            return defaultValue;
        }
    }
    // 계속 쓰기 귀찮으니까 여기에 처리해줌.
    public void appendBody(String str) {
        try {
            resp.getWriter().append(str);
        } catch (IOException e) {
            // 아래 코드는 프로그램 꺼지면 바로 꺼지는 거임. (없애면 그냥 계속 돌아감)
            throw new RuntimeException(e);
        }
    }
}

gugudan.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.sbs.exam.Rq"%>


<%
    Rq rq = new Rq(request, response);
    int dan = rq.getIntParam("dan",9);
    int limit = rq.getIntParam("limit",9);

%>
<!-- -->

<h1><%=dan%>단</h1>
<% for(int i = 1; i<=limit; i++){ %>
<div><%=dan%> * <%=i%> = <%=dan * i%></div>
<% } %>
profile
컴퓨터공학과에 재학중이며, 백엔드를 지향하고 있습니다. 많이 부족하지만 열심히 노력해서 실력을 갈고 닦겠습니다. 부족하고 틀린 부분이 있을 수도 있지만 이쁘게 봐주시면 감사하겠습니다. 틀린 부분은 댓글 남겨주시면 제가 따로 학습 및 자료를 찾아봐서 제 것으로 만들도록 하겠습니다. 귀중한 시간 방문해주셔서 감사합니다.

0개의 댓글