tomcat/undertow替换为宝兰德

06-01 1497阅读

1、下载BES

这里给一个链接,吐槽一下,官方的下载地址是真难找

Spring Boot使用BESApplicationServer宝兰德替换内嵌Tomcat - 皮军旗 - 博客园

2、maven安装

mvn install:install-file -DgroupId=com.bes.appserv-web -DartifactId=bes-actuator-spring-boot-2.x-starter -Dversion=9.5.5.002 -Dpackaging=jar -Dfile=BES-AppServer-SpringBoot-2.x-9.5.5.002/bes-actuator-spring-boot-2.x-starter-9.5.5.002.jar
mvn install:install-file -DgroupId=com.bes.appserv-web -DartifactId=bes-gmssl -Dversion=9.5.5.002 -Dpackaging=jar -Dfile=BES-AppServer-SpringBoot-2.x-9.5.5.002/bes-gmssl-9.5.5.002.jar
mvn install:install-file -DgroupId=com.bes.appserv-web -DartifactId=bes-jasper -Dversion=9.5.5.002 -Dpackaging=jar -Dfile=BES-AppServer-SpringBoot-2.x-9.5.5.002/bes-jasper-9.5.5.002.jar
mvn install:install-file -DgroupId=com.bes.appserv-web -DartifactId=bes-jdbcra -Dversion=9.5.5.002 -Dpackaging=jar -Dfile=BES-AppServer-SpringBoot-2.x-9.5.5.002/bes-jdbcra-9.5.5.002.jar
mvn install:install-file -DgroupId=com.bes.appserv-web -DartifactId=bes-jdbcra-spring-boot-starter -Dversion=9.5.5.002 -Dpackaging=jar -Dfile=BES-AppServer-SpringBoot-2.x-9.5.5.002/bes-jdbcra-spring-boot-starter-9.5.5.002.jar
mvn install:install-file -DgroupId=com.bes.appserv-web -DartifactId=bes-lite-spring-boot-2.x-starter -Dversion=9.5.5.002 -Dpackaging=jar -Dfile=BES-AppServer-SpringBoot-2.x-9.5.5.002/bes-lite-spring-boot-2.x-starter-9.5.5.002.jar
mvn install:install-file -DgroupId=com.bes.appserv-web -DartifactId=bes-webapp-compressor -Dversion=9.5.5.002 -Dpackaging=jar -Dfile=BES-AppServer-SpringBoot-2.x-9.5.5.002/bes-webapp-compressor-9.5.5.002.jar
mvn install:install-file -DgroupId=com.bes.appserv-web -DartifactId=bes-websocket -Dversion=9.5.5.002 -Dpackaging=jar -Dfile=BES-AppServer-SpringBoot-2.x-9.5.5.002/bes-websocket-9.5.5.002.jar

3、pom文件修改

(1)排除tomcat/undertow

  org.springframework.boot
  spring-boot-starter-undertow/tomcat

(2) 引入bes

  com.bes.appserv-web
  bes-lite-spring-boot-2.x-starter
  9.5.5.002


  com.bes.appserv-web
  bes-websocket
  9.5.5.002

至此,如果你的项目没有引入spring-websocket将正常启动。反之则可能报错No suitable default RequestUpgradeStrategy found,解决方案继续往下看。

4、重写AbstractHandshakeHandler

(1) 在你的项目目录下新建和spring同名包

包名:org.springframework.web.socket.server.support

(2)新建类AbstractHandshakeHandler

/*
 * Copyright 2002-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.web.socket.server.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.Lifecycle;
import org.springframework.core.log.LogFormatUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.SubProtocolCapable;
import org.springframework.web.socket.WebSocketExtension;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketHttpHeaders;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.server.HandshakeFailureException;
import org.springframework.web.socket.server.HandshakeHandler;
import org.springframework.web.socket.server.RequestUpgradeStrategy;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.*;
/**
 * A base class for {@link HandshakeHandler} implementations, independent of the Servlet API.
 *
 * 

Performs initial validation of the WebSocket handshake request - possibly rejecting it * through the appropriate HTTP status code - while also allowing its subclasses to override * various parts of the negotiation process (e.g. origin validation, sub-protocol negotiation, * extensions negotiation, etc). * *

If the negotiation succeeds, the actual upgrade is delegated to a server-specific * {@link RequestUpgradeStrategy}, which will update * the response as necessary and initialize the WebSocket. Currently, supported servers are * Jetty 9.0-9.3, Tomcat 7.0.47+ and 8.x, Undertow 1.0-1.3, GlassFish 4.1+, WebLogic 12.1.3+. * * @author Rossen Stoyanchev * @author Juergen Hoeller * @since 4.2 * @see org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy * @see org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy * @see org.springframework.web.socket.server.standard.UndertowRequestUpgradeStrategy * @see org.springframework.web.socket.server.standard.GlassFishRequestUpgradeStrategy * @see org.springframework.web.socket.server.standard.WebLogicRequestUpgradeStrategy */ public abstract class AbstractHandshakeHandler implements HandshakeHandler, Lifecycle { private static final boolean tomcatWsPresent; private static final boolean jettyWsPresent; private static final boolean jetty10WsPresent; private static final boolean undertowWsPresent; private static final boolean glassfishWsPresent; private static final boolean weblogicWsPresent; private static final boolean websphereWsPresent; private static final boolean besWsPresent; static { ClassLoader classLoader = AbstractHandshakeHandler.class.getClassLoader(); tomcatWsPresent = ClassUtils.isPresent( "org.apache.tomcat.websocket.server.WsHttpUpgradeHandler", classLoader); jetty10WsPresent = ClassUtils.isPresent( "org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer", classLoader); jettyWsPresent = ClassUtils.isPresent( "org.eclipse.jetty.websocket.server.WebSocketServerFactory", classLoader); undertowWsPresent = ClassUtils.isPresent( "io.undertow.websockets.jsr.ServerWebSocketContainer", classLoader); glassfishWsPresent = ClassUtils.isPresent( "org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler", classLoader); weblogicWsPresent = ClassUtils.isPresent( "weblogic.websocket.tyrus.TyrusServletWriter", classLoader); websphereWsPresent = ClassUtils.isPresent( "com.ibm.websphere.wsoc.WsWsocServerContainer", classLoader); besWsPresent = ClassUtils.isPresent( "com.bes.enterprise.web.websocket.server.WsHttpUpgradeHandler", classLoader); } protected final Log logger = LogFactory.getLog(getClass()); private final RequestUpgradeStrategy requestUpgradeStrategy; private final List supportedProtocols = new ArrayList(); private volatile boolean running; /** * Default constructor that auto-detects and instantiates a * {@link RequestUpgradeStrategy} suitable for the runtime container. * @throws IllegalStateException if no {@link RequestUpgradeStrategy} can be found. */ protected AbstractHandshakeHandler() { this(initRequestUpgradeStrategy()); } /** * A constructor that accepts a runtime-specific {@link RequestUpgradeStrategy}. * @param requestUpgradeStrategy the upgrade strategy to use */ protected AbstractHandshakeHandler(RequestUpgradeStrategy requestUpgradeStrategy) { Assert.notNull(requestUpgradeStrategy, "RequestUpgradeStrategy must not be null"); this.requestUpgradeStrategy = requestUpgradeStrategy; } private static RequestUpgradeStrategy initRequestUpgradeStrategy() { String className; if (tomcatWsPresent) { className = "org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy"; } else if (jettyWsPresent) { className = "org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy"; } else if (jetty10WsPresent) { className = "org.springframework.web.socket.server.jetty.Jetty10RequestUpgradeStrategy"; } else if (undertowWsPresent) { className = "org.springframework.web.socket.server.standard.UndertowRequestUpgradeStrategy"; } else if (glassfishWsPresent) { className = "org.springframework.web.socket.server.standard.GlassFishRequestUpgradeStrategy"; } else if (weblogicWsPresent) { className = "org.springframework.web.socket.server.standard.WebLogicRequestUpgradeStrategy"; } else if (websphereWsPresent) { className = "org.springframework.web.socket.server.standard.WebSphereRequestUpgradeStrategy"; } else if (besWsPresent) { className = "org.springframework.web.socket.server.standard.BesRequestUpgradeStrategy"; } else { throw new IllegalStateException("No suitable default RequestUpgradeStrategy found"); } try { Class clazz = ClassUtils.forName(className, AbstractHandshakeHandler.class.getClassLoader()); return (RequestUpgradeStrategy) ReflectionUtils.accessibleConstructor(clazz).newInstance(); } catch (Exception ex) { throw new IllegalStateException( "Failed to instantiate RequestUpgradeStrategy: " + className, ex); } } /** * Return the {@link RequestUpgradeStrategy} for WebSocket requests. */ public RequestUpgradeStrategy getRequestUpgradeStrategy() { return this.requestUpgradeStrategy; } /** * Use this property to configure the list of supported sub-protocols. * The first configured sub-protocol that matches a client-requested sub-protocol * is accepted. If there are no matches the response will not contain a * {@literal Sec-WebSocket-Protocol} header. *

Note that if the WebSocketHandler passed in at runtime is an instance of * {@link SubProtocolCapable} then there is no need to explicitly configure * this property. That is certainly the case with the built-in STOMP over * WebSocket support. Therefore, this property should be configured explicitly * only if the WebSocketHandler does not implement {@code SubProtocolCapable}. */ public void setSupportedProtocols(String... protocols) { this.supportedProtocols.clear(); for (String protocol : protocols) { this.supportedProtocols.add(protocol.toLowerCase()); } } /** * Return the list of supported sub-protocols. */ public String[] getSupportedProtocols() { return StringUtils.toStringArray(this.supportedProtocols); } @Override public void start() { if (!isRunning()) { this.running = true; doStart(); } } protected void doStart() { if (this.requestUpgradeStrategy instanceof Lifecycle) { ((Lifecycle) this.requestUpgradeStrategy).start(); } } @Override public void stop() { if (isRunning()) { this.running = false; doStop(); } } protected void doStop() { if (this.requestUpgradeStrategy instanceof Lifecycle) { ((Lifecycle) this.requestUpgradeStrategy).stop(); } } @Override public boolean isRunning() { return this.running; } @Override public final boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws HandshakeFailureException { WebSocketHttpHeaders headers = new WebSocketHttpHeaders(request.getHeaders()); if (logger.isTraceEnabled()) { logger.trace("Processing request " + request.getURI() + " with headers=" + headers); } try { if (HttpMethod.GET != request.getMethod()) { response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED); response.getHeaders().setAllow(Collections.singleton(HttpMethod.GET)); if (logger.isErrorEnabled()) { logger.error("Handshake failed due to unexpected HTTP method: " + request.getMethod()); } return false; } if (!"WebSocket".equalsIgnoreCase(headers.getUpgrade())) { handleInvalidUpgradeHeader(request, response); return false; } if (!headers.getConnection().contains("Upgrade") && !headers.getConnection().contains("upgrade")) { handleInvalidConnectHeader(request, response); return false; } if (!isWebSocketVersionSupported(headers)) { handleWebSocketVersionNotSupported(request, response); return false; } if (!isValidOrigin(request)) { response.setStatusCode(HttpStatus.FORBIDDEN); return false; } String wsKey = headers.getSecWebSocketKey(); if (wsKey == null) { if (logger.isErrorEnabled()) { logger.error("Missing \"Sec-WebSocket-Key\" header"); } response.setStatusCode(HttpStatus.BAD_REQUEST); return false; } } catch (IOException ex) { throw new HandshakeFailureException( "Response update failed during upgrade to WebSocket: " + request.getURI(), ex); } String subProtocol = selectProtocol(headers.getSecWebSocketProtocol(), wsHandler); List requested = headers.getSecWebSocketExtensions(); List supported = this.requestUpgradeStrategy.getSupportedExtensions(request); List extensions = filterRequestedExtensions(request, requested, supported); Principal user = determineUser(request, wsHandler, attributes); if (logger.isTraceEnabled()) { logger.trace("Upgrading to WebSocket, subProtocol=" + subProtocol + ", extensions=" + extensions); } this.requestUpgradeStrategy.upgrade(request, response, subProtocol, extensions, user, wsHandler, attributes); return true; } protected void handleInvalidUpgradeHeader(ServerHttpRequest request, ServerHttpResponse response) throws IOException { if (logger.isErrorEnabled()) { logger.error(LogFormatUtils.formatValue( "Handshake failed due to invalid Upgrade header: " + request.getHeaders().getUpgrade(), -1, true)); } response.setStatusCode(HttpStatus.BAD_REQUEST); response.getBody().write("Can \"Upgrade\" only to \"WebSocket\".".getBytes(StandardCharsets.UTF_8)); } protected void handleInvalidConnectHeader(ServerHttpRequest request, ServerHttpResponse response) throws IOException { if (logger.isErrorEnabled()) { logger.error(LogFormatUtils.formatValue( "Handshake failed due to invalid Connection header" + request.getHeaders().getConnection(), -1, true)); } response.setStatusCode(HttpStatus.BAD_REQUEST); response.getBody().write("\"Connection\" must be \"upgrade\".".getBytes(StandardCharsets.UTF_8)); } protected boolean isWebSocketVersionSupported(WebSocketHttpHeaders httpHeaders) { String version = httpHeaders.getSecWebSocketVersion(); String[] supportedVersions = getSupportedVersions(); for (String supportedVersion : supportedVersions) { if (supportedVersion.trim().equals(version)) { return true; } } return false; } protected String[] getSupportedVersions() { return this.requestUpgradeStrategy.getSupportedVersions(); } protected void handleWebSocketVersionNotSupported(ServerHttpRequest request, ServerHttpResponse response) { if (logger.isErrorEnabled()) { String version = request.getHeaders().getFirst("Sec-WebSocket-Version"); logger.error(LogFormatUtils.formatValue( "Handshake failed due to unsupported WebSocket version: " + version + ". Supported versions: " + Arrays.toString(getSupportedVersions()), -1, true)); } response.setStatusCode(HttpStatus.UPGRADE_REQUIRED); response.getHeaders().set(WebSocketHttpHeaders.SEC_WEBSOCKET_VERSION, StringUtils.arrayToCommaDelimitedString(getSupportedVersions())); } /** * Return whether the request {@code Origin} header value is valid or not. * By default, all origins as considered as valid. Consider using an * {@link OriginHandshakeInterceptor} for filtering origins if needed. */ protected boolean isValidOrigin(ServerHttpRequest request) { return true; } /** * Perform the sub-protocol negotiation based on requested and supported sub-protocols. * For the list of supported sub-protocols, this method first checks if the target * WebSocketHandler is a {@link SubProtocolCapable} and then also checks if any * sub-protocols have been explicitly configured with * {@link #setSupportedProtocols(String...)}. * @param requestedProtocols the requested sub-protocols * @param webSocketHandler the WebSocketHandler that will be used * @return the selected protocols or {@code null} * @see #determineHandlerSupportedProtocols(WebSocketHandler) */ @Nullable protected String selectProtocol(List requestedProtocols, WebSocketHandler webSocketHandler) { List handlerProtocols = determineHandlerSupportedProtocols(webSocketHandler); for (String protocol : requestedProtocols) { if (handlerProtocols.contains(protocol.toLowerCase())) { return protocol; } if (this.supportedProtocols.contains(protocol.toLowerCase())) { return protocol; } } return null; } /** * Determine the sub-protocols supported by the given WebSocketHandler by * checking whether it is an instance of {@link SubProtocolCapable}. * @param handler the handler to check * @return a list of supported protocols, or an empty list if none available */ protected final List determineHandlerSupportedProtocols(WebSocketHandler handler) { WebSocketHandler handlerToCheck = WebSocketHandlerDecorator.unwrap(handler); List subProtocols = null; if (handlerToCheck instanceof SubProtocolCapable) { subProtocols = ((SubProtocolCapable) handlerToCheck).getSubProtocols(); } return (subProtocols != null ? subProtocols : Collections.emptyList()); } /** * Filter the list of requested WebSocket extensions. *

As of 4.1, the default implementation of this method filters the list to * leave only extensions that are both requested and supported. * @param request the current request * @param requestedExtensions the list of extensions requested by the client * @param supportedExtensions the list of extensions supported by the server * @return the selected extensions or an empty list */ protected List filterRequestedExtensions(ServerHttpRequest request, List requestedExtensions, List supportedExtensions) { List result = new ArrayList(requestedExtensions.size()); for (WebSocketExtension extension : requestedExtensions) { if (supportedExtensions.contains(extension)) { result.add(extension); } } return result; } /** * A method that can be used to associate a user with the WebSocket session * in the process of being established. The default implementation calls * {@link ServerHttpRequest#getPrincipal()} *

Subclasses can provide custom logic for associating a user with a session, * for example for assigning a name to anonymous users (i.e. not fully authenticated). * @param request the handshake request * @param wsHandler the WebSocket handler that will handle messages * @param attributes handshake attributes to pass to the WebSocket session * @return the user for the WebSocket session, or {@code null} if not available */ @Nullable protected Principal determineUser( ServerHttpRequest request, WebSocketHandler wsHandler, Map attributes) { return request.getPrincipal(); } }

5、自定义socket握手类

(1)在上面新建包的上一层创建包

包名:org.springframework.web.socket.server.standard

(2)新建类BesRequestUpgradeStrategy

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.web.socket.server.standard;
import com.bes.enterprise.web.websocket.server.WsServerContainer;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.socket.server.HandshakeFailureException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.Endpoint;
import javax.websocket.Extension;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
//import org.apache.tomcat.websocket.server.WsServerContainer;
/**
 * A WebSocket {@code RequestUpgradeStrategy} for Apache Tomcat. Compatible with
 * all versions of Tomcat that support JSR-356, i.e. Tomcat 7.0.47+ and higher.
 *
 * 

To modify properties of the underlying {@link javax.websocket.server.ServerContainer} * you can use {@link ServletServerContainerFactoryBean} in XML configuration or, * when using Java configuration, access the container instance through the * "javax.websocket.server.ServerContainer" ServletContext attribute. * * @author Rossen Stoyanchev * @since 4.0 */ public class BesRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy { @Override public String[] getSupportedVersions() { return new String[]{"13"}; } @Override public void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response, @Nullable String selectedProtocol, List selectedExtensions, Endpoint endpoint) throws HandshakeFailureException { HttpServletRequest servletRequest = getHttpServletRequest(request); HttpServletResponse servletResponse = getHttpServletResponse(response); StringBuffer requestUrl = servletRequest.getRequestURL(); String path = servletRequest.getRequestURI(); // shouldn't matter Map pathParams = Collections.emptyMap(); ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(path, endpoint); endpointConfig.setSubprotocols(Collections.singletonList(selectedProtocol)); endpointConfig.setExtensions(selectedExtensions); try { getContainer(servletRequest).doUpgrade(servletRequest, servletResponse, endpointConfig, pathParams); } catch (ServletException ex) { throw new HandshakeFailureException( "Servlet request failed to upgrade to WebSocket: " + requestUrl, ex); } catch (IOException ex) { throw new HandshakeFailureException( "Response update failed during upgrade to WebSocket: " + requestUrl, ex); } } @Override public WsServerContainer getContainer(HttpServletRequest request) { return (WsServerContainer) super.getContainer(request); } }

大功告成!

tomcat/undertow替换为宝兰德
(图片来源网络,侵删)
tomcat/undertow替换为宝兰德
(图片来源网络,侵删)
tomcat/undertow替换为宝兰德
(图片来源网络,侵删)
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码