spring使用内置jetty创建提供http接口服务

news/2024/5/15 10:10:59

1、添加pom文件依赖

<dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-server</artifactId><version>9.4.22.v20191022</version>
</dependency>
<dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-deploy</artifactId><version>9.4.22.v20191022</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.2.9.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.9.RELEASE</version>
</dependency>

2、编写代码

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;/*** Spring root context keeper*/
@Component
public class ApplicationContextKeeper implements ApplicationContextAware {private static WebApplicationContext webAppCtx;@Overridepublic void setApplicationContext(ApplicationContext appCtx)throws BeansException {XmlWebApplicationContext xmlWebAppCtx = new XmlWebApplicationContext();xmlWebAppCtx.setParent(appCtx);xmlWebAppCtx.setConfigLocation("");xmlWebAppCtx.setClassLoader(appCtx.getClassLoader());xmlWebAppCtx.refresh();xmlWebAppCtx.registerShutdownHook();webAppCtx = xmlWebAppCtx;}public static WebApplicationContext getWebAppCtx() {return webAppCtx;}}
import org.eclipse.jetty.server.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;/*** 服务生命周期辅助程序, 用于:* 1. 优雅关闭API服务, 加入JVM钩子, 保护数据.* 2. 可用于缓存持久化至数据库, 文件等操作*/
public final class Bootstrap implements Lifecycle, InitializingBean, ApplicationListener<ContextRefreshedEvent> {private static final Logger LOG = LoggerFactory.getLogger(Bootstrap.class);private Server jettyServer;@Value("${rest.status}")private int status;@Value("${server.port}")private int port;/*** The set of registered LifecycleListeners for event notifications.*/private LifecycleListener[] listeners = new LifecycleListener[0];private final Object listenersLock = new Object(); // Lock object for changes to listeners@Overridepublic void addLifecycleListener(LifecycleListener listener) {synchronized (listenersLock) {LifecycleListener[] results = new LifecycleListener[listeners.length + 1];System.arraycopy(listeners, 0, results, 0, listeners.length);results[listeners.length] = listener;listeners = results;}}@Overridepublic void removeLifecycleListener(LifecycleListener listener) {synchronized (listenersLock) {int n = -1;for (int i = 0; i < listeners.length; i++) {if (listeners[i] == listener) {n = i;break;}}if (n < 0) {return;}LifecycleListener[] results = new LifecycleListener[listeners.length - 1];int j = 0;for (int i = 0; i < listeners.length; i++) {if (i != n) {results[j++] = listeners[i];}}listeners = results;}}/*** @return true: no error, false: has error*/private boolean doStop() {try {jettyServer.stop(); // 1. Gracefully shutdown// 2for (LifecycleListener listener : listeners) {listener.lifecycleEvent(new LifecycleEvent(this, Lifecycle.AFTER_STOP_EVENT));}return true;} catch (Exception e) {LOG.error("Shutdown jetty server error: ", e);}return false;}@Overridepublic void afterPropertiesSet() {Runtime.getRuntime().addShutdownHook(new Thread(() -> {if (doStop()) {LOG.info("Shutdown completed");} else {LOG.warn("Shutdown completed with error, please check logs !!!");}}));LOG.info("Added JVM shutdown hook ...");}@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {if (event.getApplicationContext().getParent() == null) { // Notify when ROOT CONTEXT loadedtry {/** Start Jetty container after all bean have been initialize.** 1.In case of load big data from DB slowly but the WEB PORT*   have been open, some request maybe send to here but*   application can't process them.** 2. Jetty will parse web.xml, DispatcherServlet need WebApplicationContext to make*    handlerMapping (URL -> process bean), so if the Spring Container haven't load*    controllers specified on "springmvc-context.xml" and Jetty parse web.xml,*    springmvc maybe not found the beans, finally will throw 404 error to client.*/if (status == 1) {jettyServer.start();System.out.println("Start http server on port:" + port);}} catch (Exception e) {LOG.error("Start jetty server error: ", e);System.exit(1);throw new RuntimeException(e);}}}public void setJettyServer(Server jettyServer) {this.jettyServer = jettyServer;}}
import org.springframework.web.servlet.DispatcherServlet;
public class CustomDispatcherServlet extends DispatcherServlet {private static final long serialVersionUID = 1L;public CustomDispatcherServlet() {super(ApplicationContextKeeper.getWebAppCtx());}}
public interface Lifecycle {String BEFORE_START_EVENT = "before_start";String AFTER_START_EVENT = "after_start";String BEFORE_STOP_EVENT = "before_stop"; // Before jetty gracefully shutdownString AFTER_STOP_EVENT = "after_stop"; // After jetty gracefully shutdownvoid addLifecycleListener(LifecycleListener listener);void removeLifecycleListener(LifecycleListener listener);}

import java.util.EventObject;public class LifecycleEvent extends EventObject {private static final long serialVersionUID = 1L;/*** The event type this instance represents.*/private final String type;public LifecycleEvent(Object source, String type) {super(source);this.type = type;}public String getType() {return type;}}
/*** Interface defining a listener for significant events (including "server* start" and "server stop")*/
public interface LifecycleListener {/*** Acknowledge the occurrence of the specified event.** @param event LifecycleEvent that has occurred*/void lifecycleEvent(LifecycleEvent event);}

3、配置bean

<bean id="bootstrap" class="com.xuanwu.msggate.mto.mos.server.Bootstrap"><property name="jettyServer" ref="jettyServer" />
</bean>

4、配置mvc注解驱动

<mvc:annotation-driven />

通过mvc:annotation-driven/配置,Spring MVC会启用对注解的支持,使得可以在控制器类和方法上使用注解来定义请求映射、参数绑定等操作。

具体来说,mvc:annotation-driven/会启用以下功能:
支持@Controller注解,用于标识控制器类
支持@RequestMapping注解,用于定义请求映射
支持@RequestParam注解,用于绑定请求参数
支持@ResponseBody注解,用于将方法返回值直接作为HTTP响应体返回
支持@PathVariable注解,用于绑定URI模板变量

注意: 如果没有mvc注解支持。则会出现No mapping for POST

5、添加jetty配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"><bean id="contextHandlerCollection" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"></bean><bean id="jettyServer" class="org.eclipse.jetty.server.Server" destroy-method="stop"><constructor-arg name="pool"><bean class="org.eclipse.jetty.util.thread.QueuedThreadPool"><constructor-arg name="minThreads" value="${rest.api.jetty.poolSize.minThreads}" /><constructor-arg name="maxThreads" value="${rest.api.jetty.poolSize.maxThreads}" /></bean></constructor-arg><property name="stopAtShutdown" value="true" /><property name="stopTimeout" value="3000" /><property name="connectors"><array><bean class="org.eclipse.jetty.server.ServerConnector"><constructor-arg name="server" ref="jettyServer" /><property name="port" value="${server.port}" /><property name="acceptQueueSize" value="1024" /></bean></array></property><property name="handler"><bean class="org.eclipse.jetty.server.handler.HandlerCollection"><property name="handlers"><list><ref bean="contextHandlerCollection" /></list></property></bean></property><property name="beans"><list><ref bean="deploymentManager" /></list></property></bean><bean id="deploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager"><property name="contexts" ref="contextHandlerCollection" /><property name="appProviders"><list><ref bean="webAppProvider" /></list></property></bean><bean id="webAppProvider" class="org.eclipse.jetty.deploy.providers.WebAppProvider"><property name="monitoredDirName" value="${webapps.dir}webapps" /><property name="scanInterval" value="5" /><property name="extractWars" value="true" /><property name="configurationManager"><bean class="org.eclipse.jetty.deploy.PropertiesConfigurationManager" /></property></bean></beans>

6、在spring中导入

<import resource="classpath:/com/xuanwu/msggate/mto/mos/jetty-context.xml"/>

7、创建webapps目录并创建web.xml文件

<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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>rest api</display-name><servlet><servlet-name>dispatcher</servlet-name><servlet-class>com.xuanwu.msggate.rest2mtreceiver.server.CustomDispatcherServlet</servlet-class><init-param><param-name>detectAllHandlerAdapters</param-name><param-value>true</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/*</url-pattern></servlet-mapping><!-- Spring字符集过滤器      建议放前面 不然拦截可能有问题--><filter><filter-name>SpringEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>SpringEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter><filter-name>HttpRequestFilter</filter-name><filter-class>com.xuanwu.msggate.rest2mtreceiver.rest.filter.HttpRequestFilter</filter-class></filter><filter-mapping><filter-name>HttpRequestFilter</filter-name><url-pattern>/api/authorization/*</url-pattern></filter-mapping></web-app>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.tangninghui.cn.cn/item-12315.htm

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

主机安全-德迅卫士

什么是主机安全&#xff1f; 主机安全&#xff0c;其核心内容包括安全应用交付系统、应用监管系统、操作系统安全增强系统和运维安全管控系统。它的具体功能是指保证主机在数据存储和处理的保密性、完整性&#xff0c;可用性&#xff0c;它包括硬件、固件、系统软件的自身安全&…

Netty核心原理剖析与RPC实践6-10

Netty核心原理剖析与RPC实践6-10 06-粘包拆包问题&#xff1a;如何获取一个完整的网络包 本节课开始我们将学习 Netty 通信过程中的编解码技术。编解码技术这是实现网络通信的基础&#xff0c;让我们可以定义任何满足业务需求的应用层协议。在网络编程中&#xff0c;我们经常…

【Java八股面试系列】数据库(总结市面所有数据库知识点)

文章目录 索引索引是什么聚簇&非聚簇索引索引的实现方式HashBTree&#xff08;多路平衡二叉树&#xff09;两种实现方式区别 引申红黑树红黑树和AVL树的区别最大堆和最小堆 索引的优劣优点劣势 索引的使用索引失效的时候 事务特性事务并发问题隔离级别 锁锁的分类行锁表锁意…

【字节二面】SpringBoot可以同时处理多少请求

目录 一、示例代码二、那么springboot可以处理多少请求&#xff1f;三、maxConnections、maxThreads、acceptCount的关系 一、示例代码 RestController Slf4j public class RequestController {GetMapping("/test")public String test(HttpServletRequest request) …

【python】flask基于cookie和session来实现会话控制

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

第十四届蓝桥杯(八题C++ 题目+代码+注解)

目录 题目一&#xff08;日期统计 纯暴力&#xff09;&#xff1a; 代码&#xff1a; 题目二&#xff08;01串的熵 模拟&#xff09;&#xff1a; 代码&#xff1a; 题目三&#xff08;治炼金属&#xff09;&#xff1a; 代码&#xff1a; 题目四&#xff08;飞机降落 深度…