[이야기] JSP/Servlet의 RestEasy 4.8(Jboss)로 Rest 실험 이야기(한글 미지원)
결론부터 이야기하면, REST 구현에는 성공했다. 하지만, 문제는 한글 문제인데, 인코딩 관련해서 많은 실험을 하였으나 동작하지 않았다.
삽질하려고 하는 사람이 있다면, 정리하는 걸 추천한다.
REST가 쉽사리 활성화되지 않은 이유도 있을 거 같다.
C#이나 PHP, C++은 되는지 아직 확인은 안 해봤으나 C#은 되지 않을까 싶다.
1. 주제, 실험 환경
자바 JSP/Servlet으로 REST를 구축할 수 있는지 실험하였다.
- Apache Tomcat 9 - 2020년 9월 기준 - 최신
- Maven 3.6 - 2020년 9월 기준 - 최신
- 각종 RESTEasy 4.5.3 - 2020년 9월 기준 - 최신 (pom 셋팅)......
2. 내용 - POM.xml 설정 사항
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.restmaven</groupId>
<artifactId>restWeb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>restWeb Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://localhost</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-core -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core</artifactId>
<version>4.5.8.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-jaxb-provider -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>4.5.8.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-jsapi -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jsapi</artifactId>
<version>4.5.8.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-jackson2-provider -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>4.5.8.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-multipart-provider -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>4.5.8.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
<build>
<finalName>restWeb</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
파일명: pom.xml
3. 내용 - web.xml 설정 사항
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>resteasy.resources</param-name>
<param-value>com.example.restweb.resources.MyResources</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy JSAPI</servlet-name>
<servlet-class>org.jboss.resteasy.jsapi.JSAPIServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy JSAPI</servlet-name>
<url-pattern>/rest-js</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HomeServlet</servlet-name>
<servlet-class>com.example.restweb.controller.HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HomeServlet</servlet-name>
<url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>
</web-app>
파일명: web.xml
4. 내용 - 기본 컨트롤러 셋팅하기
RestEasy의 사용자 구현에서는 핵심이라고 보면 된다.
크게 사용방법에서는 어려운 건 아니다.
난해할 수 있는 주제가 있는데, String 등으로 바로 반환이 안 되는지.
고민해볼 수 있는 문제가 있다.
= "안 된다. 미지원이다."
Response로 무조건 return 반환을 해줘야 한다.
(Spring Framework 5 - REST 공부하다가 이거 하라고 하면 납득이 안 될 수 있는 부분이 많다.)
package com.example.restweb.resources;
import com.example.restweb.model.FileInfo;
import javax.ws.rs.Consumes;
import javax.ws.rs.Encoded;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
@Path("/api")
public class MyResources
{
// Index
@GET
@Path("")
@Produces("application/json")
public Response get()
{
StringBuffer buf = new StringBuffer();
buf.append("ok");
return Response.status(200).entity(buf).build();
}
@GET
@Path("users/{id}")
@Produces("application/json")
public Response getUserById(@PathParam("id") Integer id)
{
User user = new User();
user.setId(id);
user.setFirstName("Lokesh");
user.setLastName("Gupta");
return Response.status(200).entity(user).build();
}
@Path("foo/{param}-{other}")
@PUT
@Produces("application/json")
public Response putFooParam(@PathParam("param") String param,
@PathParam("other") String other)
{
StringBuffer buf = new StringBuffer();
buf.append("param").append("=").append(param).append(";");
buf.append("other").append("=").append(other).append(";");
return Response.status(200).entity(buf).build();
}
@Path("form")
@POST
@Produces("application/json")
public String postForm(@FormParam("id") String a,
@FormParam("passwd") String b){
return a +"/" +b;
}
@Path("lookup")
@GET
@Produces("application/json")
public Response lookup(@QueryParam("id") String id,
@Context UriInfo uriInfo)
{
StringBuffer buf = new StringBuffer();
buf.append("param").append("=").append(id).append(";");
return Response.status(200).entity(buf).build();
}
@POST
@Path("/upload-file")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@MultipartForm FileInfo info) throws Exception {
String fileName = info.getFileName();
// RESTEasy는 한글 자체가 안됨.
/*
form.setFileName(filename);
System.out.println("파일명1:" + form.getFileName());
String fileName = form.getFileName() == null ? "Unknown" : form.getFileName() ;
String completeFilePath = "c:/temp2/" + fileName;
try
{
//Save the file
File file = new File(completeFilePath);
if (!file.exists())
{
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(form.getFileData());
fos.flush();
fos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
//Build a response to return
*/
return Response.status(200)
.entity("uploadFile is called, Uploaded file name : " + fileName).build();
}
}
파일명: MyResources.java
5. 결과
실험1)
-> 문자셋 찾기 실험(UTF-8, Euc-kr, us-ascil, windows-1251, ISO-8851-9? 등)
(반복문으로 해당 문자인지 찾는 작업을 하였음.)
(실패)
실험2)
-> <form 태그 accept- utf-8> 가능하도록 설정
(실패)
실험3)
-> new String (originalText.getBytes("ISO-8851-9), "UTF-8") 등 변환 작업
(실패)
.......
실험4)
-> public response 함수명(@Context ServletRequest req......)에 req.setCharacterEncoding 설정
(실패)
(다수의 방법을 적용하였음.)
결과는 RESTEasy 프로젝트에서 한글 자체를 해결해줘야 한다. 그렇지 않으면 어렵다.
이 프로그램은 영어로 글을 작성한다고 했을 때는 동작한다.
단순한 영어나 숫자 형태로 전송 작업을 시도하고 싶다면, 해봐도 무방하다. 한글 등은 기대 안 하는 게 좋을 듯 싶다.
RESTEasy 이외에 흥미로운 발견을 한 부분도 있다.
Servlet 생성할 때 셋팅화면에 자세히 보면, doPut, doDelete, doGet, doPost 기능이 있다.
문제는 패턴 등을 잡을 때 한계가 생긴다. (힘들고 무척 어렵다는 이야기이다.)
이 실험은 그런 부분은 해소하였다.
[첨부(Attachments)]
restEasy-한글미지원(Unsupported_Korean_Language).zip
(Spring Tool-Suite 4.4에서 작성함.)
* 참고자료(References)
1. RESTEasy JAX-RS, https://docs.jboss.org/resteasy/docs/4.5.8.Final/userguide/html/, Accessed by 2020-09-29, Last Modified 2020-09-23.
= (RESTEasy 기술 정보가 해외, 국내에 많이 부족해서 공식 메뉴얼을 참고할 수 밖에 없음)
2. Chapter 3. Installation/Configuration, / 3.3. Deploying to other servlet containers, https://docs.jboss.org/resteasy/docs/4.5.8.Final/userguide/html/Installation_Configuration.html
3. RESTEasy JSON Example with Jackson, https://howtodoinjava.com/resteasy/resteasy-jackson-json-example/, Accessed by 2020-09-29, Last Modified 2013.
= (RESTEasy에서의 다중 업로드 기능에 대해서는 잘 소개하고 있다.)
4. /resteasy/test/smoke/MyResource.java - Github, https://github.com/resteasy/resteasy-examples/blob/master/jsapi-servlet-test/src/main/java/org/jboss/resteasy/test/smoke/MyResource.java, Accessed by 2020-09-29, Last Modified 2016-08-05.
= 조금 된 소스코드이나 RESTEasy를 쉽게 빠르게 구축하는 방법이 적혀져 있다.
= 문제는 저 코드대로 전부 따라해보면, 안 된다. 태스트를 수 차례 각종 URL을 넣어봐서 되는 코드는 살리고 참고를 많이 하였다.
5. JSON Example With RESTEasy + Jackson, https://examples.javacodegeeks.com/enterprise-java/rest/resteasy/json-example-with-resteasy-jackson/, Accessed by 2020-09-29, Last Modified 2013-12-09
= 구축 원리를 차근차근 화면 그림 위주로 소개하고 있다.
6. RESTEasy File Upload – Html Form Example, https://howtodoinjava.com/resteasy/jax-rs-resteasy-file-upload-html-form-example/, Accessed by 2020-09-29, Last Modified 2013.
= RESTEasy 2.3 기반으로 작성된 것이라서 다소 일부분만 참고하였다. 동작이 안 되는 코드들도 많다.
7. RESTEasy JAX-RS 4.5.8.Final API, https://docs.jboss.org/resteasy/docs/4.5.8.Final/javadocs/, Accessed by 2020-09-29, Last Modified 2020-09.
= JAVA API 메뉴얼처럼 RestEasy도 API 메뉴얼이 있다. 변화가 다소 있었다. 2.3버전의 메뉴얼과 현재 버전의 기능 변화가 많이 있었다.
'이야기(Story) > 이야기(Story)' 카테고리의 다른 글
[이야기(Story)] 블로그를 하면서 느낀 점 정리해보기 (11) | 2023.02.21 |
---|---|
[이야기(Story)] MariaDB 테이블 파티셔닝과 고가용성 클러스터의 이해(HaProxy) (14) | 2021.01.01 |
[이야기] Maven, Oracle 19, Hibernate 5.4 - ORM 구현 및 동작하나요? (11) | 2020.09.21 |
[이야기(Story)] 웹 어플리케이션과 웹 프로그래밍 ([Story] Web Applications and Web Programming) (10) | 2019.11.15 |
[이야기(Story)] 티맥스 OS 사용후기 - 이클립스(Eclipse), APT (10) | 2019.11.13 |