diff --git a/ks.server/pom.xml b/ks.server/pom.xml index 6c3c718..c107d4a 100644 --- a/ks.server/pom.xml +++ b/ks.server/pom.xml @@ -17,8 +17,10 @@ 1.8 1.7.25 2.11.1 + 5.1.0.RELEASE + 9.4.12.v20180830 lib - ks.server.Main + ks.server.WebApplication kinosearch @@ -33,18 +35,58 @@ slf4j-api ${slf4j.version} + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + org.apache.logging.log4j log4j-slf4j-impl ${log4j.version} + + + org.springframework + spring-core + ${spring.version} + + + commons-logging + commons-logging + + + + + org.springframework + spring-webmvc + ${spring.version} + + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + + org.projectlombok lombok 1.18.2 + + com.google.code.gson + gson + 2.8.5 + diff --git a/ks.server/src/main/java/ks/server/Main.java b/ks.server/src/main/java/ks/server/Main.java deleted file mode 100644 index e84a2d0..0000000 --- a/ks.server/src/main/java/ks/server/Main.java +++ /dev/null @@ -1,10 +0,0 @@ -package ks.server; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class Main { - public static void main(String[] args) { - log.info("KinoSearch - Server"); - } -} diff --git a/ks.server/src/main/java/ks/server/SpringConfigMVC.java b/ks.server/src/main/java/ks/server/SpringConfigMVC.java new file mode 100644 index 0000000..d137829 --- /dev/null +++ b/ks.server/src/main/java/ks/server/SpringConfigMVC.java @@ -0,0 +1,20 @@ +package ks.server; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.GsonHttpMessageConverter; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +@Configuration +@ComponentScan({ "ks.server.controllers" }) +@EnableWebMvc +public class SpringConfigMVC implements WebMvcConfigurer { + @Override + public void configureMessageConverters(List> converters) { + converters.add(new GsonHttpMessageConverter()); + } +} diff --git a/ks.server/src/main/java/ks/server/WebApplication.java b/ks.server/src/main/java/ks/server/WebApplication.java new file mode 100644 index 0000000..6ea0404 --- /dev/null +++ b/ks.server/src/main/java/ks/server/WebApplication.java @@ -0,0 +1,100 @@ +package ks.server; + +import ks.server.controllers.ErrorPageController; +import ks.server.controllers.WebController; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.server.ConnectionFactory; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ErrorPageErrorHandler; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Slf4jLog; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +import java.net.InetSocketAddress; + +@Slf4j +@RequiredArgsConstructor +public class WebApplication { + private final String host; + private final int port; + + private DispatcherServlet getDispatcherServlet(WebApplicationContext context) { + DispatcherServlet dispatcherServlet = new DispatcherServlet(context); + dispatcherServlet.setThrowExceptionIfNoHandlerFound(true); + return dispatcherServlet; + } + + private ErrorPageErrorHandler getErrorHandler() { + ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler(); + errorHandler.addErrorPage(500, "/err500"); + return errorHandler; + } + + /** + * Подготавливаем обработчик запросов + * + * @param context Spring-контекст веб-приложения {@link WebApplicationContext} + * @return {@link ServletContextHandler} + */ + private ServletContextHandler getServletContextHandler(WebApplicationContext context) { + ServletContextHandler contextHandler = new ServletContextHandler(); + contextHandler.setContextPath("/"); + contextHandler.setErrorHandler(getErrorHandler()); + contextHandler.addServlet(new ServletHolder(getDispatcherServlet(context)), "/*"); + contextHandler.addEventListener(new ContextLoaderListener(context)); + return contextHandler; + } + + /** + * Создаем Spring-контекст + * + * @return {@link WebApplicationContext} + */ + private WebApplicationContext getWebApplicationContext() { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.register(SpringConfigMVC.class); + return context; + } + + /** + * Запуск встроенного веб-сервера + */ + private void start() { + Log.setLog(new Slf4jLog("Jetty.Logger")); + + Server jettyServer = new Server(new InetSocketAddress(host, port)); + for (Connector connector : jettyServer.getConnectors()) { + for (ConnectionFactory factory : connector.getConnectionFactories()) { + if (factory instanceof HttpConnectionFactory) { + ((HttpConnectionFactory)factory).getHttpConfiguration().setSendServerVersion(false); + } + } + } + + jettyServer.setHandler(getServletContextHandler(getWebApplicationContext())); + + try { + jettyServer.start(); + jettyServer.join(); + } catch (Exception e) { + log.error("Error start server", e); + } + } + + public static void main(String[] args) { + final String host = System.getProperty("host", "127.0.0.1"); + final int port = Integer.parseInt(System.getProperty("port", "8080")); + + log.info("Server listen {}:{}", host, port); + WebApplication webApplication = new WebApplication(host, port); + webApplication.start(); + } +} diff --git a/ks.server/src/main/java/ks/server/controllers/ErrorPageController.java b/ks.server/src/main/java/ks/server/controllers/ErrorPageController.java new file mode 100644 index 0000000..b140088 --- /dev/null +++ b/ks.server/src/main/java/ks/server/controllers/ErrorPageController.java @@ -0,0 +1,47 @@ +package ks.server.controllers; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.NoHandlerFoundException; + +import javax.servlet.ServletException; +import java.util.HashMap; +import java.util.Map; + +@ControllerAdvice +@RequestMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE) +@ResponseBody +public class ErrorPageController { + + private Map createErrorMap(HttpStatus httpStatus) { + return createErrorMap(httpStatus.value(), httpStatus.getReasonPhrase()); + } + + private Map createErrorMap(int code, String message) { + Map map = new HashMap<>(); + + map.put("error", String.valueOf(code)); + map.put("errorMessage", message); + + return map; + } + + @ExceptionHandler(NoHandlerFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public Map handleNotFound() { + return createErrorMap(HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(ServletException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public Map handleUnexceptedError() { + return createErrorMap(-1, "Unexcepted error"); + } + + @RequestMapping(path = "/err500", method = RequestMethod.GET) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public Map handleInternalError() { + return createErrorMap(HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/ks.server/src/main/java/ks/server/controllers/WebController.java b/ks.server/src/main/java/ks/server/controllers/WebController.java new file mode 100644 index 0000000..747e6fb --- /dev/null +++ b/ks.server/src/main/java/ks/server/controllers/WebController.java @@ -0,0 +1,21 @@ +package ks.server.controllers; + +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.Collections; +import java.util.Map; + +@Controller +@RequestMapping(path = "/", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) +@ResponseBody +public class WebController { + + @RequestMapping(method = RequestMethod.GET) + public Map index() { + return Collections.singletonMap("message", "hello?"); + } +} diff --git a/ks.server/src/main/resources/log4j2.xml b/ks.server/src/main/resources/log4j2.xml index ec2cbdd..d52c2ae 100644 --- a/ks.server/src/main/resources/log4j2.xml +++ b/ks.server/src/main/resources/log4j2.xml @@ -6,8 +6,10 @@ - + + +