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

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;

    @Override
    public 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

    @Override
    public 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;
        }
    }

    @Override
    public 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

            // 2
            for (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;
    }

    @Override
    public 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 ...");
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().getParent() == null) { // Notify when ROOT CONTEXT loaded
            try {
                /*
                 * 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 shutdown
    String AFTER_STOP_EVENT = "after_stop"; // After jetty gracefully shutdown

    void 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/beans
           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://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>

在这里插入图片描述

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

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

相关文章

azure服务器通过手机客户端远程连接

下载客户端 输入ip地址 输入用户名和密码 连接成功 人工智能学习网站&#xff1a; https://chat.xutongbao.top

大鱼来客实景无人直播系统源码开发部署---支持OEM贴牌-无限开户

实景无人直播系统需要包含以下几个主要功能&#xff1a; 视频采集与编码&#xff1a;使用摄像头或其他视频设备进行视频采集&#xff0c;并对视频进行编码压缩&#xff0c;以便实现实时传输。 视频传输与接收&#xff1a;将编码后的视频通过网络传输至客户端&#xff0c;客户端…

探究 HTTPS 的工作过程

目录 1. HTTPS 协议原理 1.1. 为什么要有HTTPS协议 1.2. 如何理解安全 1.3. HTTPS 协议是什么 2. HTTPS 的前置概念 2.1. 什么是加密 && 解密 2.2. 为什么要加密 2.3. 常见的加密方式 2.3.1. 对称加密 2.3.2. 非对称加密 2.4. 数据摘要 && 数据指纹…

Avalonia11.0.2+.Net6.0支持多语言,国际化

Avalonia11.0.2+.Net6.0支持多语言,国际化 操作系统项目结构最终效果具体实现安装Prism.Avalonia准备多语言文件语言资源加载类界面标记扩展类界面中使用国际化VM具体实现VM里面使用多语言方法操作系统 项目结构 最

【jenkins+cmake+svn管理c++项目】windows修改jenkins的工作目录

jenkins默认的存放源码的workspace是&#xff1a; C:\Users\用户\AppData\Local\Jenkins\.jenkins\workspace。由于jenkins会拉取大量的源代码以及编译生成一些文件&#xff0c;我希望我能自己指定目录作为它的工作空间&#xff0c;放在这里显然不太合适。 那么修改目录的方式有…

【剑指offer】顺时针打印矩阵

题目链接 acwing leetcode 题目描述 输入一个矩阵&#xff0c;按照从外向里以顺时针的顺序依次打印出每一个数字。 数据范围矩阵中元素数量 [0,400]。 输入&#xff1a; [ [1, 2, 3, 4], [5, 6, 7, 8], [9,10,11,12] ] 输出&#xff1a;[1,2,3,4,8,12,11,10,9,5,6,7] 解题 …

移动端Web笔记day03

移动 Web 第三题 01-移动 Web 基础 谷歌模拟器 模拟移动设备&#xff0c;方便查看页面效果&#xff0c;移动端的效果是当手机屏幕发生了变化&#xff0c;页面和页面中的元素也要跟着等比例变化。 屏幕分辨率 分类&#xff1a; 硬件分辨路 -> 物理分辨率&#xff1a;硬件…

【软考】设计模式之状态模式

目录 1. 说明2. 应用场景3. 结构图4. 构成5. 优缺点5.1 优点5.2 缺点 6. java示例6.1 非状态模式6.1.1 问题分析6.1.2 接口类6.1.2 实现类6.1.3 客户端6.1.4 结果截图 6.2 状态模式6.2.1 抽象状态类6.2.2 状态类6.2.3 上下文类6.2.4 上下文类 1. 说明 1.允许一个对象在其内部状…

算法之美:二叉树演进之AVL平衡二叉树底层原理

在之前的文章中&#xff0c;我们初步了解了二叉查找树&#xff08;又称二叉排序树&#xff09;&#xff0c;这使我们意识到使用特定策略的查询可以显著提高查找效率。本文将进一步探讨二叉树的演进。由于树相关算法较多且相对复杂&#xff0c;因为我后续将拆解讲述&#xff0c;…

SUSE 15 SP5 一键安装 Oracle 19C(19.22)单机版

前言 Oracle 一键安装脚本&#xff0c;演示 SUSE 15 SP5 一键安装 Oracle 19C&#xff08;19.22&#xff09;单机版过程&#xff08;全程无需人工干预&#xff09;&#xff1a;&#xff08;脚本包括 ORALCE PSU/OJVM 等补丁自动安装&#xff09; ⭐️ 脚本下载地址&#xff1…

集成ES分组查询统计求平均值

前言 之前其实写过ES查询数据&#xff0c;进行分组聚合统计&#xff1a; 复杂聚合分组统计实现 一、目标场景 机房机柜的物联网设备上传环境数据&#xff0c;会存储到ES存到ES的温湿度数据需要查询&#xff0c;进行分组后&#xff0c;再聚合统计求平均值 二、使用步骤 1.引入…

【Linux系统】进程概念创建进程进程标示符

什么是进程&#xff1f; 操作系统中&#xff0c; 进程可以同时存在非常多的。根据我们之前谈的操作系统具有“管理”的特性&#xff0c; 那么就有&#xff0c;既然要管理&#xff0c;就要 --- 先描述&#xff0c;在组织&#xff01;&#xff01;&#xff01; 由冯诺依曼体系结…

AIGC,ChatGPT,Prompt 万能提示词

AIGC ChatGPT 职场案例 AI 绘画 与 短视频制作 PowerBI 商业智能 68集 Mysql 8.0 54集 Oracle 21C 142集 Office 2021实战应用 Python 数据分析实战&#xff0c; ETL Informatica 数据仓库案例实战 51集 Excel 2021实操 100集&#xff0c; Excel 2021函数大全 80集 Excel 2021…

进入消息传递的魔法之门:ActiveMQ原理与使用详解

嗨&#xff0c;亲爱的童鞋们&#xff01;欢迎来到这个充满魔法的世界&#xff0c;今天我们将一同揭开消息中间件ActiveMQ的神秘面纱。如果你是一个对编程稍有兴趣&#xff0c;但又对消息中间件一知半解的小白&#xff0c;不要害怕&#xff0c;我将用最简单、最友好的语言为你呈…

Linux——命名管道

Linux——命名管道 命名管道命名管道和匿名管道的区别 创建命名管道利用命名管道实现简单通信 我们之前学习了匿名管道&#xff0c;这种管道有一个缺点就是只有两个有血缘关系的进程才能够使用匿名管道&#xff0c;这个非常不方便。所以我们又在匿名管道的基础之上引入了命名管…

Flask python :logging日志功能使用

logging日志的使用 一、了解flask日志1.1、Loggers记录器1.2、Handlers 处理器1.3、Formatters 格式化器 二、使用日志2.1、官网上的一个简单的示例2.2、基本配置2.3、具体使用示例2.4、运行 三、写在最后 一、了解flask日志 日志是一种非常重要的工具&#xff0c;可以帮助开发…

系列学习前端之第 7 章:一文掌握 AJAX

1、AJAX 简介 AJAX 全称为 Asynchronous JavaScript And XML&#xff08;中文名&#xff1a;阿贾克斯&#xff09;&#xff0c;就是异步的 JS 和 XML。AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准组合在一起使用的新方式。AJAX 可以在浏览器中向服务器发送异步请求…

flutter 弹窗之系列一

自定义不受Navigator影响的弹窗 class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title;overrideState<MyHomePage> createState() > _MyHomePageState(); }class _MyHomePageState extends State<MyH…

rabbitmq-c 程序实现客户端服务端

安装mq https://blog.csdn.net/zl_momomo/article/details/82986368 需要安裝rabbitmq-server 开启rabbitmq服务 systemctl start rabbitmq-server systemctl enable rabbitmq-server. 客户端 amqp_sendstring.c include <stdint.h> #include <stdio.h> #incl…

访问二维数组本质

先从一维数组讲起 int main() {int arr[5] { 1,2,3,4,5 };for (int i 0; i < 5; i) {printf("%d",arr[i]); //对数组进行访问}return 0; } 其实 arr [ i ] * (arr i) 这两个是完全相等的&#xff0c;在c语言指针&#xff08;1&#xff09;8.数组名与 …