728x90

인프런 김영한 님의 강의를 참고했습니다.

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

 

저번에 만들었던 서블릿에 컨트롤러를 추가해보자.

 

현재 만들어둔 컨트롤러는 공통된 부분이 많고 하는 일도 비슷하다.

그럴 때는 FrontController를 생성해준다.

이 FrontController가 요청을 받고 그 요청에 맞는 컨트롤러를 호출해주는 역할을 한다.

 

우선 프론트 컨트롤러 자체를 도입해보자.

우선 다형성을 이용해 컨트롤러 인터페이스를 만들어보자.

package hello.servlet.web.frontcontroller.version1;

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

import java.io.IOException;

public interface ControllerV1 {
    void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}

이렇게 만들고 각 컨트롤러들이 이 인터페이스를 구현하게 해주면 요청에 따른 컨트롤러는 모두 준비가 된다.

 

이제 FrontController를 만들어준다.

package hello.servlet.web.frontcontroller.version1;

import hello.servlet.web.frontcontroller.version1.controller.StudentFormControllerV1;
import hello.servlet.web.frontcontroller.version1.controller.StudentListControllerV1;
import hello.servlet.web.frontcontroller.version1.controller.StudentSaveControllerV1;
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;
import java.util.HashMap;
import java.util.Map;

@WebServlet(name = "frontControllerServletV1", urlPatterns = "/front-controller/v1/*")
public class FrontControllerServletV1 extends HttpServlet {
    private Map<String, ControllerV1> controllerMap = new HashMap<>();
    
    public FrontControllerServletV1(){
        controllerMap.put("/front-controller/v1/students/new-form", new StudentFormControllerV1());
        controllerMap.put("/front-controller/v1/students/save", new StudentSaveControllerV1());
        controllerMap.put("/front-controller/v1/students", new StudentListControllerV1());
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ControllerV1 controller = controllerMap.get(req.getRequestURI());
        if(controller == null){
            resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        
        controller.process(req, resp);
    }
}

이렇게 Map에 컨트롤러들을 담아준 후 URI를 확인하여 거기에 맞는 컨트롤러로 보내준다.

 

이제 계속 리팩토링을 진행해보자.

모든 컨트롤러에서 중복되는 부분이 있다.

이 부분을 모아주어야 깔끔하고, 후에 수정하기도 쉽다.

이런 상태에서 중간에 MyView를 추가하여 dispatcher.forward()를 맡길 예정이다.

package hello.servlet.web.frontcontroller;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class MyView {

    private String viewPath;

    public MyView(String viewPath){
        this.viewPath = viewPath;
    }

    public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        RequestDispatcher requestDispatcher = request.getRequestDispatcher(viewPath);
        requestDispatcher.forward(request, response);
    }
}

이렇게 생성자로 viewPath를 입력받아서 render를 이용하여 jsp로 넘겨준다.

 

나머지 코드들은 저 부분을 빼서 다시 작성한다고 생각하면 된다.

package hello.servlet.web.frontcontroller.version2;

import hello.servlet.web.frontcontroller.MyView;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public interface ControllerV2 {

    MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
package hello.servlet.web.frontcontroller.version2.controller;

import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.version2.ControllerV2;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class StudentFormControllerV2 implements ControllerV2 {

    @Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        return new MyView("/WEB-INF/views/new-form.jsp");
    }
}
package hello.servlet.web.frontcontroller.version2.controller;

import hello.servlet.domain.student.Student;
import hello.servlet.domain.student.StudentRepository;
import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.version2.ControllerV2;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class StudentSaveControllerV2 implements ControllerV2 {

    private StudentRepository studentRepository = StudentRepository.getInstance();

    @Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String studentName = request.getParameter("studentName");
        int year = Integer.parseInt(request.getParameter("year"));

        Student student = new Student(studentName, year);
        studentRepository.save(student);

        request.setAttribute("student", student);

        return new MyView("/WEB-INF/views/save-result.jsp");
    }
}
package hello.servlet.web.frontcontroller.version2.controller;

import hello.servlet.domain.student.Student;
import hello.servlet.domain.student.StudentRepository;
import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.version2.ControllerV2;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.List;

public class StudentListControllerV2 implements ControllerV2 {

    private StudentRepository studentRepository = StudentRepository.getInstance();

    @Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Student> students = studentRepository.findAll();
        request.setAttribute("students", students);

        return new MyView("/WEB-INF/views/students.jsp");
    }
}

그러고 FrontController는 이렇게 작성을 해준다.

package hello.servlet.web.frontcontroller.version2;

import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.version2.controller.StudentFormControllerV2;
import hello.servlet.web.frontcontroller.version2.controller.StudentListControllerV2;
import hello.servlet.web.frontcontroller.version2.controller.StudentSaveControllerV2;
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;
import java.util.HashMap;
import java.util.Map;

@WebServlet(name = "frontControllerServletV2", urlPatterns = "/front-controller/v2/*")
public class FrontControllerServletV2 extends HttpServlet {

    private Map<String, ControllerV2> controllerMap = new HashMap<>();

    public FrontControllerServletV2(){
        controllerMap.put("/front-controller/v1/students/new-form", new StudentFormControllerV2());
        controllerMap.put("/front-controller/v1/students/save", new StudentSaveControllerV2());
        controllerMap.put("/front-controller/v1/students", new StudentListControllerV2());
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ControllerV2 controller = controllerMap.get(req.getRequestURI());
        if(controller == null){
            resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        MyView view = controller.process(req, resp);
        view.render(req, resp);
    }
}

request와 response에 데이터를 받고 view로 경로를 받은 후에 실행해주는 것이다.

 

다음 리펙토링이다.

컨트롤러에서는 request와 response가 꼭 필요하지 않다.

어차피 데이터를 넘길거면 담아서 넘기는 게 아니라 그냥 넘기면 되기 때문이다.

그렇기 때문에 컨트롤러에서 서블릿 기술을 제외해보자.

 

스프링처럼 Model을 만들어 데이터를 넘기도록 한다.

이렇게 Controller에서 Model에 데이터만 담아서 가져오는 것이다.

package hello.servlet.web.frontcontroller;

import lombok.Getter;
import lombok.Setter;

import java.util.HashMap;
import java.util.Map;

@Getter
@Setter
public class ModelView {
    
    private String viewName;
    private Map<String, Object> model = new HashMap<>();

    public ModelView(String viewName, Map<String, Object> model) {
        this.viewName = viewName;
    }
}

이렇게 Map으로 key, value로 데이터들을 저장하도록 만든다.

그러고 경로를 저장하기 위해서 viewName을 사용한다.

 

이제 ModelView를 리턴하도록 코드들을 바꾸어보자.

package hello.servlet.web.frontcontroller.version3;

import hello.servlet.web.frontcontroller.ModelView;

import java.util.Map;

public class StudentFormControllerV3 implements ControllerV3{

    @Override
    public ModelView process(Map<String, String> paramMap) {
        return new ModelView("new-form");
    }
}

이렇게 Model에 jsp의 경로와 데이터들을 넣어준다.

package hello.servlet.web.frontcontroller.version3;

import hello.servlet.domain.student.Student;
import hello.servlet.domain.student.StudentRepository;
import hello.servlet.web.frontcontroller.ModelView;

import java.util.Map;

public class StudentSaveControllerV3 implements ControllerV3{
    
    private StudentRepository studentRepository = StudentRepository.getInstance();

    @Override
    public ModelView process(Map<String, String> paramMap) {
        String studentName = paramMap.get("studentName");
        int year = Integer.parseInt(paramMap.get("year"));
        
        Student student = new Student(studentName, year);
        studentRepository.save(student);
        
        ModelView modelView = new ModelView("save-result");
        modelView.getModel().put("student", student);
        return modelView;
    }
}
package hello.servlet.web.frontcontroller.version3;

import hello.servlet.domain.student.Student;
import hello.servlet.domain.student.StudentRepository;
import hello.servlet.web.frontcontroller.ModelView;

import java.util.List;
import java.util.Map;

public class StudentListControllerV3 implements ControllerV3{

    private StudentRepository studentRepository = StudentRepository.getInstance();

    @Override
    public ModelView process(Map<String, String> paramMap) {
        List<Student> students = studentRepository.findAll();

        ModelView modelView = new ModelView("students");
        modelView.getModel().put("students", students);
        
        return modelView;
    }
}

 

이제 이렇게 작동할 FrontController를 작성한다.

package hello.servlet.web.frontcontroller.version2;

import hello.servlet.web.frontcontroller.ModelView;
import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.version2.controller.StudentFormControllerV2;
import hello.servlet.web.frontcontroller.version2.controller.StudentListControllerV2;
import hello.servlet.web.frontcontroller.version2.controller.StudentSaveControllerV2;
import hello.servlet.web.frontcontroller.version3.ControllerV3;
import hello.servlet.web.frontcontroller.version3.StudentFormControllerV3;
import hello.servlet.web.frontcontroller.version3.StudentListControllerV3;
import hello.servlet.web.frontcontroller.version3.StudentSaveControllerV3;
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;
import java.util.HashMap;
import java.util.Map;

@WebServlet(name = "frontControllerServletV3", urlPatterns = "/front-controller/v3/*")
public class FrontControllerServletV3 extends HttpServlet {

    private Map<String, ControllerV3> controllerMap = new HashMap<>();

    public FrontControllerServletV3(){
        controllerMap.put("/front-controller/v3/students/new-form", new StudentFormControllerV3());
        controllerMap.put("/front-controller/v3/students/save", new StudentSaveControllerV3());
        controllerMap.put("/front-controller/v3/students", new StudentListControllerV3());
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ControllerV3 controller = controllerMap.get(req.getRequestURI());
        if(controller == null){
            resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        Map<String, String> paramMap = createParamMap(req);
        ModelView modelView = controller.process(paramMap);

        String viewName = modelView.getViewName();
        MyView view = viewer(viewName);
        view.render(modelView.getModel(), req, resp);
    }

    private MyView viewer(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

    private Map<String, String> createParamMap(HttpServletRequest req) {
        Map<String, String> paramMap = new HashMap<>();
        req.getParameterNames().asIterator()
                .forEachRemaining(paramName -> paramMap.put(paramName, req.getParameter(paramName)));

        return paramMap;
    }
}

여기에 MyView에 파라미터가 3개 들어가는 생성자가 호출 되었으니, 그에 맞게 생성자를 추가해준다.

 

 

'백엔드 > 스프링' 카테고리의 다른 글

스프링 17일차  (0) 2023.03.31
스프링 15일차  (0) 2023.03.28
스프링 14일차  (0) 2023.03.26
스프링 13일차  (0) 2023.03.25
스프링 12일차  (0) 2023.02.15
728x90

인프런 김영한 님의 강의를 참고했습니다.

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

 

간단한 학생 관리 웹을 만들어보자.

학생의 정보에는 학번, 이름, 입학년도가 있다.

 

우선 학생의 클래스를 작성해보자.

전에도 사용했던 Lombok을 사용한다.

package hello.servlet.domain.student;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class Student {
    private Long studentId;
    private String name;
    private String year;
}

학생들의 정보를 저장할 저장소이다.

 

package hello.servlet.domain.student;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class StudentRepository {
    private static Map<Long, Student> store = new HashMap<>();
    private static long STUDENT_ID_SEQUENCE = 0L;

    private static final StudentRepository instance = new StudentRepository();

    public static StudentRepository getInstance(){
        return instance;
    }

    private StudentRepository() {}

    public Student save(Student student){
        student.setStudentId(++STUDENT_ID_SEQUENCE);
        store.put(student.getStudentId(), student);
        return student;
    }

    public Student findById(Long id){
        return store.get(id);
    }

    public List<Student> findAll(){
        return new ArrayList<>(store.values());
    }
    
    public void clearStore(){
        store.clear();
    }
}

저장소는 싱글톤으로 생성했고, 저장과 검색 메서드들을 추가했다.

 

command + shift + T로 테스트 코드를 작성해보자.

package hello.servlet.domain.student;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

class StudentRepositoryTest {

    StudentRepository studentRepository = StudentRepository.getInstance();

    @AfterEach
    void afterEach(){
        studentRepository.clearStore();
    }

    @Test
    void save(){
        //given
        Student student = new Student("hyunttai", 2022);

        //when
        Student savedStudent = studentRepository.save(student);

        //then
        Student findStudent = studentRepository.findById(savedStudent.getStudentId());
        Assertions.assertEquals(savedStudent, findStudent);
    }

    @Test
    void findAll(){
        //given
        Student student1 = new Student("hyeontae", 2022);
        Student student2 = new Student("hyeonttai", 2022);

        //when
        studentRepository.save(student1);
        studentRepository.save(student2);
        List<Student> result = studentRepository.findAll();

        //then
        Assertions.assertEquals(result.size(), 2);
        org.assertj.core.api.Assertions.assertThat(result).contains(student1, student2);
    }
}

@AfterEach로 각 테스트마다 저장소를 초기화 해주었다.

문제없이 작성했다면 테스트를 통과 했을 것이다.

 

이제 servlet으로 HTML form을 응답하도록 코드를 작성해보자.

package hello.servlet.web.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;
import java.io.PrintWriter;

@WebServlet(name = "studentFormServlet", urlPatterns = "/servlet/students/new-form")
public class StudentFormServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");

        PrintWriter writer = resp.getWriter();
        writer.write("<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <title>Title</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "<form action=\"/servlet/students/save\" method=\"post\">\n" +
                "    studentName: <input type=\"text\" name=\"studentName\" />\n" +
                "           year:      <input type=\"text\" name=\"year\" />\n" +
                " <button type=\"submit\">전송</button>\n" + "</form>\n" +
                "</body>\n" +
                "</html>\n");
    }
}

response 객체에 ContentType을 html로해서 html로 응답한 모습이다.

 

action에 save를 달아주었기 때문에 이 요청을 받을 save도 작성을 해야한다.

package hello.servlet.web.servlet;

import hello.servlet.domain.student.Student;
import hello.servlet.domain.student.StudentRepository;
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;
import java.io.PrintWriter;

@WebServlet(name = "studentSaveServlet", urlPatterns = "/servlet/students/save")
public class StudentSaveServlet extends HttpServlet {

    private StudentRepository studentRepository = StudentRepository.getInstance();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String studentName = req.getParameter("studentName");
        int year = Integer.parseInt(req.getParameter("year"));

        Student student = new Student(studentName, year);
        studentRepository.save(student);

        PrintWriter writer = resp.getWriter();

        writer.write("<html>\n" +
                "<head>\n" +
                " <meta charset=\"UTF-8\">\n" + "</head>\n" +
                "<body>\n" +
                "<ul>\n" +
                "    <li>studentId="+student.getStudentId()+"</li>\n" +
                "    <li>name="+student.getStudentName()+"</li>\n" +
                " <li>year="+student.getYear()+"</li>\n" + "</ul>\n" +
                "<a href=\"/index.html\">메인</a>\n" + "</body>\n" +
                "</html>");
    }
}

그러고 http://localhost:8080/servlet/students/new-form 해당 페이지에 접근하면 잘 작동하는 것을 볼 수 있다.

 

이번엔 하나씩 조회하는 것이 아니라 모든 학생들을 조회하는 기능을 만들어보자.

package hello.servlet.web.servlet;

import hello.servlet.domain.student.Student;
import hello.servlet.domain.student.StudentRepository;
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;
import java.io.PrintWriter;
import java.util.List;

@WebServlet(name = "studentListServlet", urlPatterns = "/servlet/students")
public class StudentListServlet extends HttpServlet {

    private StudentRepository studentRepository = StudentRepository.getInstance();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");

        List<Student> students = studentRepository.findAll();

        PrintWriter writer = resp.getWriter();

        writer.write("<html>");
        writer.write("<head>");
        writer.write("    <meta charset=\"UTF-8\">");
        writer.write("    <title>Title</title>");
        writer.write("</head>");
        writer.write("<body>");
        writer.write("<a href=\"/index.html\">메인</a>");
        writer.write("<table>");
        writer.write("    <thead>");
        writer.write("    <th>studentId</th>");
        writer.write("    <th>studentName</th>");
        writer.write("    <th>year</th>");
        writer.write("    </thead>");
        writer.write("    <tbody>");
        for (Student student : students) {
            writer.write("    <tr>");
            writer.write("        <td>" + student.getStudentId() + "</td>");
            writer.write("        <td>" + student.getStudentName() + "</td>");
            writer.write("        <td>" + student.getYear() + "</td>");
            writer.write("    </tr>");
        }
        writer.write("    </tbody>");
        writer.write("</table>");
        writer.write("</body>");
        writer.write("</html>");
    }
}

이렇게 for-each문을 이용해서 반복되는 html들을 찍어주었다.

이렇게 잘 출력되는 것을 볼 수 있다.

하지만 이렇게 자바코드 안에 HTML을 넣어서 작업하는 방법은 너무 힘들다.

 

그렇기에 HTML에 자바코드를 작성하는 JSP로 페이지를 만들어보자.

신입생을 등록하는 jsp는 html과 크게 다르지 않다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>신입생 등록</title>
</head>
<body>
<form action = "/jsp/students/save.jsp" method="post">
    studentName: <input type = "text" name="studentName">
    year: <input type="text" name="age">
    <button type="submit">전송</button>
</form>

</body>
</html>

 

여기서 응답을 하는 save.jsp는

<%@ page import="hello.servlet.domain.student.StudentRepository" %>
<%@ page import="hello.servlet.domain.student.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
  StudentRepository studentRepository = StudentRepository.getInstance();

  String studentName = request.getParameter("studentName");
  int year = Integer.parseInt(request.getParameter("year"));

  Student student = new Student(studentName, year);
  studentRepository.save(student);

%>
<html>
<head>
    <title>신입생 등록 완료</title>
</head>
<body>
<ul>
  <li>studentId=<%=student.getStudentId()%></li>
  <li>studentName=<%=student.getStudentName()%></li>
  <li>year=<%=student.getYear()%></li>
</ul>

<a href="/index.html">메인</a>

</body>
</html>

이렇게 자바코드와 html이 합쳐져 있다.

윗 부분에 자바 코드들을 작성하고 html의 body에서 데이터들을 가져오는 것이다.

이렇게 보면 기존과 크게 차이가 없어 보이지만, html에 자바코드를 사용해서 반복문으로 값을 출력하면 훨씬 작업하기 편해진다.

 

학생들의 목록을 출력해주는 JSP이다.

<%@ page import="hello.servlet.domain.student.StudentRepository" %>
<%@ page import="hello.servlet.domain.student.Student" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    StudentRepository studentRepository = StudentRepository.getInstance();
    List<Student> students = studentRepository.findAll();
%>
<html>
<head>
    <title>학생 조회</title>
    <meta charset="UTF-8">
</head>
<body>
<a href="/index.html">메인</a>
<table>
    <thead>
    <th>studentId</th>
    <th>studentName</th>
    <th>year</th>
    </thead>
    <tbody>
    <%
        for(Student student: students){
            out.write("<tr>\n");
            out.write("<td>" + student.getStudentId() + "</td>\n");
            out.write("<td>" + student.getStudentName() + "</td>\n");
            out.write("<td>" + student.getYear() + "</td>\n");
            out.write("</tr>\n");
        }
    %>
    </tbody>
</table>

</body>
</html>

이렇게 html 안에서 자바코드를 사용하여 html 코드들을 반복해서 출력하는 것으로 코드가 훨씬 보기 좋고 편해졌다.

하지만 현재의 JSP는 너무 많은 역할을 담당하고 있다.

그렇기 때문에 Model, View, Controll의 MVC 패턴에 맞추어 작성하도록 해야한다.

Model은 컨트롤러에서 뷰로 넘기는 데이터로 뷰가 출력하는 데에 필요한 데이터들을 가지고 있다.

View는 Model에 있는 데이터를 사용해서 화면을 보여주는 역할을 한다.

Controller는 HTTP 요청을 받아 파라미터를 보고, 로직을 실행한다. 그러고 Model에 데이터를 담아 View에 넘긴다.

 

여기서 Controller에 로직들을 둘 수 있지만, 역할을 나누기위해 서비스를 만들어 그 서비스를 호출하여 실행하는 역할을 한다.

요청부터 응답까지의 과정을 살펴보면

이렇게 MVC를 이용하여 요청에 응답을 한다.

그러면 여기서 로직을 수행하는 부분은 서블릿으로, 뷰를 보여주는 부분은 JSP로 작성을 한다.

 

package hello.servlet.web.servletmvc;

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(name = "mvcStudentFormServlet", urlPatterns = "servlet-mvc/students/new-form")
public class MvcStudentFormServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String viewPath="/WEB-INF/views/new-form.jsp";
        RequestDispatcher dispatcher = req.getRequestDispatcher(viewPath);
        dispatcher.forward(req, resp);
    }
}

 

이렇게 작성을 하면 urlPattern으로 mapping 한 주소에 접속할 때 dispatcher.forward를 통해 viewPath에 있는 JSP를 열어주게 된다.

여기서 /WEB-INF를 만들어야 하는데, 이 경로 안에 있는 JSP는 외부에서 호출할 수 없고 서버 내부에서만 호출이 가능하다.

 

이제 새로 열릴 new-form.jsp를 만들어준다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>신입생 등록</title>
    <meta charset="UTF-8">
</head>
<body>
<form action="save" method="post">
    studentName: <input type="text" name="studentName"/>
    year: <input type="text" name="year"/>
    <button type="submit">전송</button>
</form>
</body>
</html>

action을 save로 잡아주었으니 이제 save를 작성한다.

전송을 하면 아래의 서블릿에서 로직이 실행이 된다.

 

request를 보고 파라미터들을 이용하여 값을 가져온 후 다시 request.setAttribute()를 이용하여 데이터를 넣어준 후 jsp로 넘겨준다.

package hello.servlet.web.servletmvc;

import hello.servlet.domain.student.Student;
import hello.servlet.domain.student.StudentRepository;
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(name = "mvcStudentSaveServlet", urlPatterns = "/servlet-mvc/students/save")
public class MvcStudentSaveServlet extends HttpServlet {
    private StudentRepository studentRepository = StudentRepository.getInstance();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String studentName = req.getParameter("studentName");
        int year = Integer.parseInt(req.getParameter("year"));
        
        Student student = new Student(studentName, year);
        studentRepository.save(student);
        
        req.setAttribute("student", student);
        
        String viewPath = "/WEB-INF/views/save-result.jsp";
        RequestDispatcher dispatcher = req.getRequestDispatcher(viewPath);
        dispatcher.forward(req, resp);
    }
}

 

이제 결과를 출력할 jsp를 작성해준다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>신입생 등록 완료</title>
    <meta charset="UTF-8">
</head>
<body>

<ul>
  <li>studentId=${student.studentId}</li>
  <li>studentName=${student.studentName}</li>
  <li>year=${student.year}</li>
</ul>

<a href="/index.html">메인</a>

</body>
</html>

${}를 이용하면 attribute에 있는 데이터를 조회할 수 있다.

 

 

'백엔드 > 스프링' 카테고리의 다른 글

스프링 17일차  (0) 2023.03.31
스프링 16일차  (0) 2023.03.29
스프링 14일차  (0) 2023.03.26
스프링 13일차  (0) 2023.03.25
스프링 12일차  (0) 2023.02.15
728x90

인프런 김영한 님의 강의를 참고했습니다.

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

 

스프링 부트를 설정해서 다운로드하여 오고, 추가 설정들을 해준다.

저번에 워낙 많이 해서 그냥 넘어가도록 하겠다.

 

이번에는 서블릿을 사용하기 때문에 스프링 메인에 @ServletComponentScan annotation을 달아준다.

그러고 같은 패키지 내에 이런 자바 코드를 작성해 보자.

package hello.servlet.basic;

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;
import java.io.PrintWriter;

@WebServlet(name = "hiServlet", urlPatterns = "/hi")
public class HiServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType("text/plain");
        resp.setCharacterEncoding("utf-8");


        PrintWriter writer = resp.getWriter();
        writer.println("HiServlet");
        writer.println("request = " + req);
        writer.println("response = " + resp);

        writer.println("name = " + req.getParameter("name"));

    }
}

실행을 하고 url에 접속한 결과이다.

 

@WebServlet annotation은 서블릿 어노테이션으로 name에 들어가는 값은 서블릿의 이름이고, urlPatterns에 들어가는 값은 mapping 되는 url이다.

저번에 서블릿 공부 할 때 공부했을 것이다.

그리고 서블릿을 사용하기 위해서는 HttpServlet을 extends 받아야 한다.

 

메서드 내의 코드를 잠깐 설명해 보자면, 응답의 ContentType을 text/plain으로 설정하고 CharacterEncoding을 utf-8로 설정을 한 후 response에 getWriter로 request와 response 객체를 출력해 보는 것이다.

 

  • HTTPServletRequest 객체

객체의 이름을 보면 알겠지만, HTTP의 Request를 Servlet이 다루기 편하게 만들어주는 객체이다.

이곳을 보면 HTTP 요청 메시지에 대한 정보를 얻어 올 수 있다.

당연히 직접 HTTP 요청 메시지를 사용할 수 있겠지만, 난이도가 매우 어렵다.

 

HTTPServletRequest 객체를 이용해서 안의 내용들을 출력해 보자.

우선 시작 줄부터이다.

주석으로 설명을 달지 않아도 시작줄의 어떤 내용을 출력하려 하는 것인지 알 수 있을 것이다.

package hello.servlet.basic.request;

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;
import java.io.PrintWriter;

@WebServlet(name = "requestHeaderServlet", urlPatterns = "/requestHeader")
public class RequestHeader extends HttpServlet {

    private void printStart(HttpServletResponse httpServletResponse, String string) throws IOException {
        httpServletResponse.getWriter().printf("--- %s-Line start ---\n", string);
    }

    private void printEnd(HttpServletResponse httpServletResponse, String string) throws IOException {
        httpServletResponse.getWriter().printf("--- %s-Line end ---\n", string);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        StartLine(req, resp);
    }

    private void StartLine(HttpServletRequest request,HttpServletResponse response)throws IOException{

        response.setContentType("text/plain");
        response.setCharacterEncoding("utf-8");

        PrintWriter writer = response.getWriter();

        printStart(response, "Request");

        writer.println("Method = " + request.getMethod());
        writer.println("Protocol = " + request.getProtocol());
        writer.println("Scheme = " + request.getScheme());
        writer.println("RequestURL = " + request.getRequestURL());
        writer.println("RequestURI = " + request.getRequestURI());
        writer.println("QueryString = " + request.getQueryString());
        writer.println("isSecure = " + request.isSecure());
        printEnd(response, "Request");

        writer.println();
    }
}

실행을 한 후에 접속해 보면

이렇게 요청 메서드에 관한 정보들이 나오게 된다.

 

이번엔 헤더이다.

package hello.servlet.basic.request;

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;
import java.io.PrintWriter;

@WebServlet(name = "requestHeaderServlet", urlPatterns = "/requestHeader")
public class RequestHeader extends HttpServlet {

    private void printStart(HttpServletResponse httpServletResponse, String string) throws IOException {
        httpServletResponse.getWriter().printf("--- %s-Line start ---\n", string);
    }

    private void printEnd(HttpServletResponse httpServletResponse, String string) throws IOException {
        httpServletResponse.getWriter().printf("--- %s-Line end ---\n", string);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        StartLine(req, resp);
        Headers(req, resp);
    }

    private void Headers(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
        response.setCharacterEncoding("utf-8");

        PrintWriter writer = response.getWriter();

        printStart(response, "Headers");

        request.getHeaderNames().asIterator()
                .forEachRemaining(headerName -> writer.println(headerName + " = " + request.getHeader(headerName)));

        printEnd(response, "Headers");
        writer.println();
    }
}

이번엔 Iterator로 빠르게 출력했다.

이렇게 이어서 잘 출력이 되는 것을 볼 수 있다.

나머지 부분들도 request를 보면 찾을 수 있지만, 이 정도만 하고 넘어가 보겠다.

 

  • HTTP request - GET

데이터를 서버로 전송해 보자.

서버로 데이터를 전송할 때는 Postman을 사용하면 된다.

package hello.servlet.basic.request;

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;
import java.io.PrintWriter;

@WebServlet(name = "requestParam", urlPatterns = "/requestParam")
public class RequestParam extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("[파리미터 조회] - start");
        req.getParameterNames().asIterator()
                .forEachRemaining(paramName -> System.out.println(paramName + " = " + req.getParameter(paramName)));

        System.out.println("[파리미터 조회] - end");
        System.out.println();

        System.out.println("[개별 파라미터 조회]");
        System.out.println("name : " + req.getParameter("name"));
        System.out.println("age: " + req.getParameter("age"));

        System.out.println();
    }
}

이렇게 Iterator를 이용하여 전체를 조회할 수 있지만, 보통 getParameter()를 이용해서 개별 조회를 한다.

Postman으로 데이터를 전송하면

이렇게 출력되게 된다.

 

  • HTTP request - POST

이번엔 POST 방식이다.

저번 GET 방식은 URL로 데이터를 보낼 수도 있긴 했지만, 이번 POST 방식은 Postman을 이용해야 할 것이다.

근데 코드는 수정할 필요가 없다.

POST 방식도 GET과 쿼리 파라미터 형식이 같기 때문에 조회 메서드는 동일하게 사용할 수 있다.

이렇게 동일한 결과가 나오는 것을 볼 수 있다.

 

  • HTTP request - 텍스트
package hello.servlet.basic.request;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@WebServlet(name = "requestBodyString", urlPatterns = "/requestBodyString")
public class RequestBodyString extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletInputStream inputStream = req.getInputStream();

        String message = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

        System.out.println("message = " + message);

    }
}

InputStream은 바이트 코드를 반환하기 때문에 UTF_8로 지정을 해주어 바꿔줘야 한다.

 

Postman으로 POST에 raw로 그냥 메시지를 보내면

이렇게 잘 출력이 되는 것을 볼 수 있다.

 

  • HTTP request - JSON

요즘 많이 사용하는 JSON 형식이다.

우선 Postman에서 JSON으로 데이터를 보내는 방법부터 알아보겠다.

Body에서 raw, JSON을 선택하고 형식에 맞게 작성을 하면 된다.

 

그러고 JSON 형식으로 데이터를 가져올 수 있게 그에 맞는 객체를 생성한다.

package hello.servlet.basic;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class JsonData {
    private String name;
    private int age;
}

깔끔하게 Lombok을 사용한다.

 

package hello.servlet.basic.request;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.JsonData;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@WebServlet(name = "requestBodyJson", urlPatterns = "/requestBodyJson")
public class RequestBodyJson extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletInputStream inputStream = req.getInputStream();
        String message = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
        
        JsonData jsonData = objectMapper.readValue(message, JsonData.class);

        System.out.println(jsonData);
    }
}

ObjectMapper를 이용해서 가져온 데이터를 해당 객체로 변환해 준다.

이렇게 잘 출력되는 것을 볼 수 있다.

 

  • HTTP response

HttpServletResponse를 사용하여 응답 메시지를 작성할 수 있다.

package hello.servlet.basic.response;

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

import java.io.IOException;

@WebServlet(name = "responseHeader", urlPatterns = "/response-header")
public class ResponseHeaderServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //상태 라인
        resp.setStatus(HttpServletResponse.SC_OK);
        
        //response header
        resp.setContentType("text/plain");
        resp.setCharacterEncoding("utf-8");
        resp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        resp.setHeader("Pragma", "no-cache");
        resp.setHeader("my-header", "hi");
        
    }
    
    private void redirect(HttpServletResponse response) throws IOException{
        response.sendRedirect("/basic/hi-form.html");
    }
    
    private void cookie(HttpServletResponse response){
        Cookie cookie = new Cookie("myCookie", "good!");
        cookie.setMaxAge(60);
        response.addCookie(cookie);
    }
}

이렇게 response 객체를 이용해서 편하게 응답 메시지를 만들 수 있다.

 

이번에는 중요한 응답 메시지로 JSON을 작성하는 방법이다.

여기서도 ObjectMapper를 사용한다.

package hello.servlet.basic.response;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.JsonData;
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(name = "responseJson", urlPatterns = "/responseJson")
public class ResponseJson extends HttpServlet {
    
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json");
        resp.setCharacterEncoding("utf-8");
        
        JsonData jsonData = new JsonData();
        jsonData.setName("hi");
        jsonData.setAge(20);
        
        String result = objectMapper.writeValueAsString(jsonData);
        
        resp.getWriter().write(result);
    }
}

이렇게 객체를 만들고 ObjectMapper를 이용하여 문자열로 바꿔준 후 write로 작성을 해주면 된다.

그러면 이렇게 잘 전달이 되는 것을 볼 수 있다.

'백엔드 > 스프링' 카테고리의 다른 글

스프링 16일차  (0) 2023.03.29
스프링 15일차  (0) 2023.03.28
스프링 13일차  (0) 2023.03.25
스프링 12일차  (0) 2023.02.15
스프링 11일차  (0) 2023.02.12
728x90

한글을 사용할 경우에 깨지지 않고 정상적으로 출력하는 방법에 대해 알아보자.

 

한글을 이용해서 post 방식으로 넘긴다면

이런 식으로 깨져서 넘어가고 나타나게 된다.

 

이럴 땐

request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");

국제 표준인 UTF-8로 설정을 하면 된다.

 

일단 이름이랑 사는 곳을 입력 받을 jsp를 만들어보자.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action="mSignUp" method="post">
    이름 : <input type = "text" name="m_name"><br>
    사는 곳 : <input type="text" name="m_location">
    <input type="submit" value="sign up">
</form>

</body>
</html>

post 방식으로 mSignUp에 mapping 된 곳으로 넘긴다.

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;

import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/mSignUp")
public class SignUp extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        PrintWriter out = response.getWriter();

        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        String mName = request.getParameter("m_name");
        String mLoc = request.getParameter("m_location");

        out.print("<p> mName : " + mName + "</p>");
        out.print("<p> mLoc : " + mLoc + "</p>");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

이렇게 mapping 된 Servlet에

request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");

 

을 추가하고 실행해보자.

아까와 다르게 한글이 제대로 표시되는 것을 볼 수 있다.

 

이번엔 Servlet이 아닌 jsp로 넘기는 경우를 살펴보자.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action="mSignUp.jsp" method="post">
    이름 : <input type = "text" name="m_name"><br>
    사는 곳 : <input type="text" name="m_location">
    <input type="submit" value="sign up">
</form>

</body>
</html>

action을 mSignUp.jsp로 바꾸어 주고

<% request.setCharacterEncoding("UTF-8");%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<%!
    String mName;
    String mLoc;
%>

<%
    mName = request.getParameter("m_name");
    mLoc = request.getParameter("m_location");
%>

이름 : <%= mName%> <br>
사는 곳: <%=mLoc%>

</body>
</html>

이렇게 jsp 파일을 만들어준다.

 

그러면 이렇게 한글이 제대로 출력 되는  것을 볼 수 있다.

 

만약

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%!
    String mName;
    String mLoc;
%>

<%
    mName = request.getParameter("m_name");
    mLoc = request.getParameter("m_location");
%>

이름 : <%= mName%> <br>
사는 곳: <%=mLoc%>

</body>
</html>

이런 jsp 파일을 사용했다면

 

이렇게 깨져서 나오는 것을 볼 수 있다.

 

이렇게 하나씩 코드를 추가하는 것 말고 filter를 사용해서 한글 출력을 할 수 있는데

filter interface를 구현해서 web.xml에 추가하는 것이다.

 

import jakarta.servlet.*;

import java.io.IOException;

public class myFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("-- filter doFilter() --");

        //request filter
        servletRequest.setCharacterEncoding("UTF-8");
        servletResponse.setCharacterEncoding("UTF-8");

        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("-- filter init() --");
    }

    @Override
    public void destroy() {
        System.out.println("-- filter destroy() --");
    }
}

filter를 implements 해서 doFilter 안에 UTF-8로 인코딩 하는 코드를 달아준다.

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <filter>
        <filter-name>myFilter</filter-name>
        <filter-class>myFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

그리고 xml에 이렇게 filter 관련된 태그를 달아주면 위처럼 한글이 깨지지 않게 된다.

 

'백엔드 > JSP, Servlet' 카테고리의 다른 글

JSP & Servlet 11일차  (0) 2023.02.05
JSP & Servlet 10일차  (0) 2023.01.16
JSP & Servlet 9일차  (0) 2023.01.15
JSP & Servlet 8일차  (0) 2023.01.04
JSP & Servlet 7일차  (0) 2023.01.04
728x90

클라이언트와 서버의 연결을 유지시켜주는 방법으로 Session에 대해 알아보자.

 

쿠키는 연결 정보를 클라이언트에 저장을 했지만 Session은 서버에 저장하는 방법이다.

Session을 구현하는 방법은

다음과 같다.

 

바로 만들어보도록 하자.

우선 login.jsp이다.

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action="loginCon" method="post">
    ID : <input type="text" name="mID"><br>
    PW : <input type="password" name="mPW"><br>
    <input type="submit" value="login">
</form>

</body>
</html>

이렇게 body 부분에 form으로 ID와 PW를 받고 post로 loginCon에 넘겨준다.

 

여기에 mapping된 메서드는

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;

import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/loginCon")
public class loginCon extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();

        String mID = request.getParameter("mID");
        String mPW = request.getParameter("mPW");

        out.print("mID : " + mID);
        out.print("mPW : " + mPW);

        HttpSession session = request.getSession();
        session.setAttribute("memberId", mID);

        response.sendRedirect("loginOk.jsp");

    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

어차피 doPost에서 doGet으로 넘어가기에 doGet에 저렇게 작성을 하고 request에서 mID와 mPW를 각각 받아온다.

그리고 session에 memberId로 mID 속성을 저장하고 loginOk.jsp를 열어준다.

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <%
        PrintWriter printWriter = response.getWriter();
        session = request.getSession();
        printWriter.print("memberId : " + session.getAttribute("memberId") + "<br>");
    %>

    <form action = "logoutCon" method="post">
        <input type = "submit" value="logout">
    </form>

</body>
</html>

 

loginOk.jsp에서는 session에서 memberId를 찾아 출력해주고 logoutCon을 연결해주는 버튼을 달아준다.

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;

import java.io.IOException;

@WebServlet(name = "logoutCon", value = "/logoutCon")
public class logoutCon extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.invalidate();

        response.sendRedirect("login.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

logoutCon은 session을 비워주고 처음화면인 login.jsp로 돌려 보내준다.

 

login.jsp는 session에 저장이 되어 있는지 확인을 해보아야 한다.

그렇기에 앞부분에 조건문을 추가하여 session에 데이터가 있다면 loginOk.jsp를 열어주게 만든다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE HTML>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    if(session.getAttribute("memberId") != null)
        response.sendRedirect("loginOk.jsp");
%>
<form action="loginCon" method="post">
    ID : <input type="text" name="mID"><br>
    PW : <input type="password" name="mPW"><br>
    <input type="submit" value="login">
</form>

</body>
</html>

'백엔드 > JSP, Servlet' 카테고리의 다른 글

JSP & Servlet 12일차  (0) 2023.02.05
JSP & Servlet 10일차  (0) 2023.01.16
JSP & Servlet 9일차  (0) 2023.01.15
JSP & Servlet 8일차  (0) 2023.01.04
JSP & Servlet 7일차  (0) 2023.01.04
728x90

오늘은 클라이언트와 서버의 연결을 유지시켜주는 방법인 Cookie에 대해서 알아본다.

 

  • Cookie란?

서버와 클라이언트의 연결에 대한 흔적을 남기는 것을 Cookie라고 한다.

다음에 연결할 일이 생긴다면 이 Cookie를 참고하게 된다.

  • Cookie 구현

Cookie[] cookies = request.getCookies();
Cookie cookie = null;

for(Cookie c : cookies){
	System.out.println("c.getName(): " + c.getName() + ", c.getValue() :" + c.getValue());
    
    if(c.getName().equals("memberId")){
    	cookie = c;
	}
}

if(cookie == null){
	System.out.println("cookie is null");
    cookie = new Cookie("memberId", mId);
}

response.addCookie(cookie);
cookie.setMaxAge(60 * 60);

response.sendRedirect("loginOk.jsp");

 

이렇게 Cookie를 찾아보고 없으면 새로운 Cookie를 만드는 방식으로 구현을 한다.

 

이제 실습을 해보도록 하자, 바로 프로젝트를 생성을 해주면 된다.

우선 jsp로 페이지를 먼저 만들도록 하자.

loginCon으로 처리를 하도록 페이지를 작성했다.

 

그럼 해당 데이터를 받는 loginCon Servlet을 작성해보자

해당 데이터를 받고 클라이언트에서 모든 Cookie를 검사하고 만약 memberId에 해당하는 쿠키가 없다면 쿠키를 생성해준다.

쿠키의 유지 시간을 60 * 60초로 갱신을 해주고

loginOk.jsp로 보낸다.

loginOk.jsp이다

Cookie 배열에 있는 모든 쿠키를 출력해준다.

 

이제 다시 login.jsp로 돌아가야 한다.

 

만약 쿠키가 남아있다면 login을 하지 않아도 접속이 될 수 있도록 만들어야 할 것이다.

그렇기 때문에

윗 부분에 서블렛 태그로 만약 memberId에 해당하는 Cookie가 있다면 loginOk.jsp를 실행해주는 코드를 추가해준다.

 

그렇다면 만약 쿠키가 남아있다면

이런 화면이 출력되게 된다.

 

이렇게 웹에서 쿠키를 남기는 방법에 대해 알아보았다.

'백엔드 > JSP, Servlet' 카테고리의 다른 글

JSP & Servlet 12일차  (0) 2023.02.05
JSP & Servlet 11일차  (0) 2023.02.05
JSP & Servlet 9일차  (0) 2023.01.15
JSP & Servlet 8일차  (0) 2023.01.04
JSP & Servlet 7일차  (0) 2023.01.04
728x90

Servlet에서 데이터를 공유하는 방법에 대해 공부하자

 

  • Servlet parameter

이렇게 늘 그렇게 했듯이 

xml에 작성된 데이터를 가져오는 방법이다.

 

당연히 한 번 해보도록 하자

프로젝트를 생성한 후

web.xml에 servlet을 mapping 해주고

이렇게 init-parameter들도 넣어준다.

 

이러면 이제 Servlet으로 가서

이렇게 초기값들도 getServletConfig를 이용해 가져와본다.

 

실행을 해보면 당연히

이렇게 초기값들이 잘 출력이 되게 된다.

 

  • context parameter

이것도 jsp 때와 비슷하다.

전체적으로 공유될 수 있는 데이터이며

 

바로 사용을 해보자면

이렇게 xml에 context-param을 적어주고

이렇게 getServletContext로 가져와보면

잘 가져와지는 것을 확인 할 수 있다.

 

  • context attribute

JSP 때와 마찬가지로 데이터를 set하고 get하는 방법을 알아보자

이렇게 setAttribute를 작성해두고

이것을 가져와보기 위해 다른 Servlet을 작성해본다.

다른 Servlet에서 getAttribute를 이용해 데이터를 가져와보고

실행을 해보면

처음에는 이렇게 데이터들을 가져올 수 없어 null이 뜨게 된다.

setAttribute가 작성된 페이지를 켜본 후

새로고침을 해보면 이렇게 원하는 결과가 출력되는 것을 볼 수 있다.

'백엔드 > JSP, Servlet' 카테고리의 다른 글

JSP & Servlet 12일차  (0) 2023.02.05
JSP & Servlet 11일차  (0) 2023.02.05
JSP & Servlet 10일차  (0) 2023.01.16
JSP & Servlet 8일차  (0) 2023.01.04
JSP & Servlet 7일차  (0) 2023.01.04
728x90

request, response 외에 JSP에서 기본적으로 제공하는 객체에 대해 알아보자

 

  • config 객체

Web.xml의 데이터를 JSP에서 데이터를 공유하는 방식이다.

init-param으로 name과 value 쌍을 이루어 값을 초기화 해두고 작업을 하는 JSP에서 얻어 올 수 있다.

Config 객체로 부터 getInitParameter를 이용하여 초기화 된 값을 가져오는 방식이다.

 

한 번 해보도록 할 텐데 JSP 초기 설정하는 방법에서 자꾸 실수해서 오랜만에 여기다가 다시 기록하려 한다.

이렇게 jakarta EE로 server는 tomcat을 설정을 해주고

다음 페이지에서는 Servlet을 설정을 해준 뒤 만들어준다.

 

만든 후 Project Structure에서

web.xml을 추가해준다.

src -> main -> webapp에 jsp를 만들 수 있게 된다.

그럼 이대로 만들어보자

 

우선 web.xml에서

이렇게 mapping을 해준 다음

이렇게 init-param들을 추가해준다.

그 다음에는 jsp파일을 만든 후 초기화된 값들을 가져와보자

이렇게 출력을 위해 <p>태그까지 달고

실행 한 후 접속해보면

이렇게 xml에 설정해 둔 초기값들이 출력되는 것을 볼 수 있다.

  • application 객체

application 객체는 해당 프로젝트 전체에 영향을 미친다.

 

여기에 context param을 이용하면 모든 Servlet에서 모두 공유될 수 있는 데이터를 만들 수 있다.

 

우리가 사용했던 web.xml에 context-param을 추가한다.

application에서 전체적으로 공유하고 싶어하는 데이터를 이렇게 web.xml에 context-param으로 정의를 하고

JSP 파일에도 application.getInitParam을 이용해 데이터를 가져온다.

그러면 공유 객체도 이렇게 잘 가져오는 것이 보여진다.

application 객체는 프로젝트 전체에 영향을 미치기 때문에 속성을 저장하고 다른 곳에서 그렇게 만들어진 속성을 가져갈 수 있다.

이렇게 application.setAttribute를 이용해서 값을 설정해주고

application.getAttribute를 이용해서 값을 가져오는 방식이다.

이렇게 추가된 속성을 가져올 수 있다.

 

'백엔드 > JSP, Servlet' 카테고리의 다른 글

JSP & Servlet 12일차  (0) 2023.02.05
JSP & Servlet 11일차  (0) 2023.02.05
JSP & Servlet 10일차  (0) 2023.01.16
JSP & Servlet 9일차  (0) 2023.01.15
JSP & Servlet 7일차  (0) 2023.01.04

+ Recent posts