关于tomcat:Tomcat-下部署若依单体应用可观测最佳实践

实现目标采集指标信息采集链路信息采集日志信息采集 RUM 信息会话重放 即用户拜访前端的一系列过程的会话录制信息,包含点击某个按钮、操作界面、停留时间等,有助于客户真是用意、操作复现版本信息Tomcat (9.0.81)Springboot(2.6.2)JDK (>=8)DDTrace (>=1.0)特地阐明:如果是 Springboot 我的项目,Tomcat 大版本需与 Springboot 内置的 Tomcat 大版本统一,否则可能会存在启动异样。若依的单体利用下载源码若依的单体利用:https://gitee.com/y_project/RuoYi/tree/master git clone https://gitee.com/y_project/RuoYi.git移除外部 tomcat调整我的项目根目录的 pom.xml ...... <dependencyManagement> <dependencies> <!-- SpringBoot的依赖配置--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.5.15</version> <type>pom</type> <scope>import</scope> <!-- 移除外部 tomcat --> <exclusions> <exclusion> <artifactId>spring-boot-starter-tomcat</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency>......war 输入调整 ruoyi-admin 模块下的 pom.xml 文件 <packaging>war</packaging>调整日志在 ruoyi-admin/src/main/resources 新增 logback-spring.xml,原文如下: <?xml version="1.0" encoding="UTF-8"?><configuration> <!-- 日志寄存门路 --> <property name="log.path" value="/home/root/ruoyi/logs" /> <!-- 日志输入格局 --> <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - [%method,%line] %X{dd.service} %X{dd.trace_id} %X{dd.span_id} - %msg%n" /> <!-- 控制台输入 --> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${log.pattern}</pattern> </encoder> </appender> <!-- 系统日志输入 --> <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/sys-info.log</file> <!-- 循环政策:基于工夫创立日志文件 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志文件名格局 --> <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 日志最大的历史 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!-- 过滤的级别 --> <level>INFO</level> <!-- 匹配时的操作:接管(记录) --> <onMatch>ACCEPT</onMatch> <!-- 不匹配时的操作:回绝(不记录) --> <onMismatch>DENY</onMismatch> </filter> </appender> <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/sys-error.log</file> <!-- 循环政策:基于工夫创立日志文件 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志文件名格局 --> <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 日志最大的历史 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!-- 过滤的级别 --> <level>ERROR</level> <!-- 匹配时的操作:接管(记录) --> <onMatch>ACCEPT</onMatch> <!-- 不匹配时的操作:回绝(不记录) --> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 用户拜访日志输入 --> <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/sys-user.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滚 daily --> <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 日志最大的历史 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> </appender> <!-- 零碎模块日志级别管制 --> <logger name="com.ruoyi" level="info" /> <!-- Spring日志级别管制 --> <logger name="org.springframework" level="warn" /> <root level="info"> <appender-ref ref="console" /> </root> <!--零碎操作日志--> <root level="debug"> <appender-ref ref="file_info" /> <appender-ref ref="file_error" /> </root> <!--零碎用户操作日志--> <logger name="sys-user" level="info"> <appender-ref ref="sys-user"/> </logger></configuration> 编译进入我的项目根目录执行以下命令进行编译: ...

February 26, 2024 · 3 min · jiezi

关于tomcat:Tomcat目录结构-京东云技术团队

Tomcat目录结构图如下: 1、bin目录寄存一些可执行的二进制文件,.sh 结尾的为linux下执行命令,.bat 结尾的为windows下执行命令。 catalina.sh:真正启动tomcat文件,能够在外面设置jvm参数。startup.sh:启动tomcat(需当时配置好JAVA_HOME环境变量才可启动,该命令源码理论执行的为catalina.sh start)。shutdown.sh:敞开tomcat。version.sh:查看tomcat版本相干信息。2、conf目录寄存tomcat相干配置文件的。 2.1、catalina.policy我的项目平安文件,用来避免坑骗代码或JSP执行带有像System.exit(0)这样的命令,可能影响容器的毁坏。 只有当Tomcat用-security命令行参数启动时这个文件才会被应用,即启动tomcat时, startup.sh -security 。 2.2、catalina.proterties配置tomcat启动相干信息文件 2.3、context.xml监督并加载资源文件,当监督文件发生变化时,主动加载,通常不会去配置 2.4、jaspic-providers.xml和jaspic-providers.xsd不罕用文件 2.5、logging.propertiestomcat日志文件配置,包含输入格局、日志级别等。 2.6、server.xml外围配置文件:批改端口号,增加编码格局等 外围组件介绍: <1>Server:最顶层元素,而且惟一,代表整个tomcat容器。一个Server元素蕴含一个或者多个Service元素; <2>Service:对外提供服务的。一个Service元素蕴含多个Connector元素,然而只能蕴含一个Engine元素; <3>Connector:接管连贯申请,创立Request和Response对象用于和申请端替换数据;而后调配线程让Engine来解决这个申请,并把产生的Request和Response对象传给Engine <4>Engine:Engine组件在Service组件中有且只有一个;Engine是Service组件中的申请解决组件。Engine组件从一个或多个Connector中接管申请并解决,并将实现的响应返回给Connector,最终传递给客户端。 <5>Host:代表特定的虚拟主机。 <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">**name:**虚拟主机的主机名。比方 localhost 示意本机名称,理论利用时应该填写具体域名,比方 www.dog.com ,当然如果该虚拟主机是给内部人员拜访的,也能够间接填写服务器的 ip 地址,比方 192.168.1.101; **appBase:**设置 Web 应用程序组的门路。appBase 属性的值能够是绝对于 Tomcat 装置目录的相对路径,也能够是绝对路径,须要留神的是该门路必须是 Tomcat 有权限拜访的; **unpackWARs:**是否主动开展war压缩包再运行Web应用程序,默认值为true; **autoDeplay:**是否容许主动部署,默认值是 true,示意 Tomcat 会自动检测 appBase 目录上面的文件变动从而主动利用到正在运行的 Web 应用程序; **deployOnStartup:**为true时,示意Tomcat在启动时查看Web利用,且检测到的所有Web利用视作新利用; <6>Context:该元素代表在特定虚拟主机Host上运行的一个Web利用,它是Host的子容器,每个Host容器能够定义多个Context元素。动态部署Web利用时应用。 <Context path="/" docBase="E:\Resource\test.war" reloadable="true"/>**path:**浏览器拜访时的路径名,只有当主动部署齐全敞开(deployOnStartup和autoDeploy都为false)或docBase不在appBase中时,才能够设置path属性。 **docBase:**动态部署时,docBase能够在appBase目录下,也能够不在;本例中,不在appBase目录下。 **reloadable:**设定我的项目有改变时,从新加载该我的项目。 2.7、tomcat-users.xml和tomcat-users.xsdtomcat-users.xml:tomcat用户配置文件,配置用户名,明码,用户具备权限 tomcat默认没有配置任何用户,只有配置好用户后能力应用以下Tomcat Manager三个性能: <role rolename="manager-gui"/><role rolename="manager-script"/><user username="tomcat" password="tomcat" roles="manager-gui"/><user username="admin" password="123456" roles="manager-script"/>tomcat-users.xsd:对tomcat-users.xml文件的形容和束缚 2.8、web.xmlweb利用相干通用配置,能够做上面这些事件。 配置servlet增加过滤器,比方过滤敏感词汇设置session过期工夫,tomcat默认30分钟 注册了很多MIME类型,即文档类型。这些MIME类型是客户端与服务器之间阐明文档类型的,如用户申请一个html网页,那么服务器还会通知客户端浏览器响应的文档是text/html类型的,这就是一个MIME类型配置零碎欢送页 3、lib目录寄存tomcat依赖jar包的。 其中ecj-x.x.x.jar起到了将.java文件编译成.class字节码文件的作用。 4、logs目录寄存tomcat运行时产生的日志文件。 在windows环境中,日志文件输入到catalina.xxxx-xx-xx.log文件中。 在linux环境中,日志文件输入到catalina.out文件中。 大体有以下几类: catalina.xxxx-xx-xx.logwindows下日志文件输入内容host-manager.xxxx-xx-xx.log拜访webapps下host-manager我的项目日志localhost.xxxx-xx-xx.logtomcat启动时,本身拜访服务,只记录tomcat拜访日志,而非业务我的项目日志localhost\_access\_log.xxxx-xx-xx.txt示意拜访tomcat下所有我的项目日志记录manager.xxxx-xx-xx.log拜访webapps下manager我的项目日志5、temp目录用户寄存tomcat在运行过程中产生的临时文件(清空不会对tomcat运行带来影响)。 6、webapps目录用来寄存应用程序,能够以文件夹、war包、jar包的模式公布利用。当然也能够将应用程序放在磁盘的任意地位,在配置文件中映射好即可。 ...

September 27, 2023 · 1 min · jiezi

关于tomcat:请求在tomcat中的流转源码分析篇

Connector的初始化catalina解析server.xml是通过degister来实现的,degister解析到<Connector标签后做的事件如下代码所见 ConnectorCreateRule@Override public void begin(String namespace, String name, Attributes attributes) throws Exception { Service svc = (Service)digester.peek(); Executor ex = null; if ( attributes.getValue("executor")!=null ) { ex = svc.getExecutor(attributes.getValue("executor")); } Connector con = new Connector(attributes.getValue("protocol")); if (ex != null) { setExecutor(con, ex); } String sslImplementationName = attributes.getValue("sslImplementationName"); if (sslImplementationName != null) { setSSLImplementationName(con, sslImplementationName); } digester.push(con); }connector依据标签属性,拿到对应的protocol协定,拿到配在service标签外部的线程池,protocol的名称转化成Connector中ProtocolHandler类型的成员变量, 后续将以Http11NioProtocol来做解说 public Connector(String protocol) { setProtocol(protocol); // Instantiate protocol handler ProtocolHandler p = null; try { Class<?> clazz = Class.forName(protocolHandlerClassName); // 反射调用ProtocolHandler的构造方法的时候会做后续的初始化 p = (ProtocolHandler) clazz.getConstructor().newInstance(); } catch (Exception e) { log.error(sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"), e); } finally { this.protocolHandler = p; }ProtocolHandler的结构ProtocolHandler有其形象办法,Http11NioProtocol构造方法中的tcp实现由NioEndpoint来做,因而Connector结构起来的时候,对应的ProtocolHanlder、endpoint的关联关系曾经关联好 ...

August 31, 2023 · 6 min · jiezi

关于tomcat:一次请求在Tomcat源码中的轮转基础篇

前言Tomcat作为Java开发者接触过最重要的web容器,在启动和解决申请过程中做了海量的事件,高级开发者很少关怀,应用SpringMvc之类下层框架一带而过,然而这些局部是Java和网络集大成之作,笔者要带着大家走一遍一次申请,加深tomcat的认知。最好先调试好Tomcat源码 Tomcat基础架构BootStrap和CatalinaBootStrapBootStrap就是Tomcat的main函数所在位置,在应用过程中执行脚本catlina.sh或者bat文件即可执行java命令并调用BootStrap的main函数实现tomcat的启动 public static void main(String args[]) { if (daemon == null) { // Don't set daemon until init() has completed Bootstrap bootstrap = new Bootstrap(); try { bootstrap.init(); } catch (Throwable t) { handleThrowable(t); t.printStackTrace(); return; } daemon = bootstrap; } else { // When running as a service the call to stop will be on a new // thread so make sure the correct class loader is used to // prevent a range of class not found exceptions. Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); }......}CatalinaBootStrap是服务器的入口, 会通过start、stop、stopServer、stopServer等反射调用Catalina的对应办法 ...

August 28, 2023 · 1 min · jiezi

关于tomcat:springboot-http并发限制

并发限度取决于tomcat配置server.tomcat.max-connections 以后最大连接数server.tomcat.accept-count 最大期待连接数server.tomcat.max-threads 外部参数-最大线程数server.tomcat.min-spare-threads外部参数-最小线程数 初始值见spring-configuration-matadata.json 对于外界而言,同一时刻最大连接数 = 以后最大连接数+最大期待连接数。对于外部解决机制而言,request申请先应用最小连接数解决,最小连接数不够则创立线程,直到达到最大线程数。若仍有申请,则扔进线程池阻塞队列,期待线程闲暇时解决。 对于http申请客户端次要存在以下三步:1)建设连贯。有连贯超时工夫2)发送申请。即读超时工夫3)期待响应。即写超时工夫

August 20, 2023 · 1 min · jiezi

关于tomcat:聊聊springboot-tomcat的maxHttpFormPostSize

序本文次要钻研一下spring boot tomcat的maxHttpFormPostSize参数 parseParameterstomcat-embed-core-9.0.37-sources.jar!/org/apache/catalina/connector/Request.java /** * Parse request parameters. */ protected void parseParameters() { parametersParsed = true; Parameters parameters = coyoteRequest.getParameters(); boolean success = false; try { // Set this every time in case limit has been changed via JMX parameters.setLimit(getConnector().getMaxParameterCount()); // getCharacterEncoding() may have been overridden to search for // hidden form field containing request encoding Charset charset = getCharset(); boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI(); parameters.setCharset(charset); if (useBodyEncodingForURI) { parameters.setQueryStringCharset(charset); } // Note: If !useBodyEncodingForURI, the query string encoding is // that set towards the start of CoyoyeAdapter.service() parameters.handleQueryParameters(); if (usingInputStream || usingReader) { success = true; return; } String contentType = getContentType(); if (contentType == null) { contentType = ""; } int semicolon = contentType.indexOf(';'); if (semicolon >= 0) { contentType = contentType.substring(0, semicolon).trim(); } else { contentType = contentType.trim(); } if ("multipart/form-data".equals(contentType)) { parseParts(false); success = true; return; } if( !getConnector().isParseBodyMethod(getMethod()) ) { success = true; return; } if (!("application/x-www-form-urlencoded".equals(contentType))) { success = true; return; } int len = getContentLength(); if (len > 0) { int maxPostSize = connector.getMaxPostSize(); if ((maxPostSize >= 0) && (len > maxPostSize)) { Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.postTooLarge")); } checkSwallowInput(); parameters.setParseFailedReason(FailReason.POST_TOO_LARGE); return; } byte[] formData = null; if (len < CACHED_POST_LEN) { if (postData == null) { postData = new byte[CACHED_POST_LEN]; } formData = postData; } else { formData = new byte[len]; } try { if (readPostBody(formData, len) != len) { parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE); return; } } catch (IOException e) { // Client disconnect Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.parseParameters"), e); } parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT); return; } parameters.processParameters(formData, 0, len); } else if ("chunked".equalsIgnoreCase( coyoteRequest.getHeader("transfer-encoding"))) { byte[] formData = null; try { formData = readChunkedPostBody(); } catch (IllegalStateException ise) { // chunkedPostTooLarge error parameters.setParseFailedReason(FailReason.POST_TOO_LARGE); Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.parseParameters"), ise); } return; } catch (IOException e) { // Client disconnect parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT); Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.parseParameters"), e); } return; } if (formData != null) { parameters.processParameters(formData, 0, formData.length); } } success = true; } finally { if (!success) { parameters.setParseFailedReason(FailReason.UNKNOWN); } } }tomcat request解析表单参数maxPostSize次要是上面这段 ...

August 17, 2023 · 5 min · jiezi

关于tomcat:基于嵌入式Tomcat的War包启动器

前言最近针对java我的项目的部署形式进行整顿,jenkins/tomcat/windows工具/linux脚本/web部署平台等等 发现war包通过tomcat部署比拟繁琐,等待时间长,配置规定简单对于小白很不敌对,也难以接入到自定义的部署工具/平台中 之前开发的Jar包部署平台是servlet开发通过嵌入式tomcat部署,借此关上思路 是否基于嵌入式tomcat做一个war包启动器,通过代码的形式开启tomcat容器来部署war包 源码地址:https://gitee.com/code2roc/jar-manage/tree/master/waragent 借此启动器能够将war包部署集成到本人的工具平台中,将启动器的jar包按一般形式部署即可 计划tomcat启动个别须要几个根本参数设置 war包门路端口映射路由Tomcat tomcat = new Tomcat();tomcat.setPort(port);StandardContext ctx = (StandardContext) tomcat.addWebapp(contextPath, catalinaBase + File.separator + "webapps" + File.separator + name + ".war");tomcat9启动还须要指定cookie解决策略,否则无奈辨认 CookieProcessor cookieProcessor = new LegacyCookieProcessor();ctx.setCookieProcessor(cookieProcessor);后续理论应用中还波及到了启动jvm参数设置及jar包扫描跳过的配置 tomcat.getEngine().setJvmRoute(jvmStartCommand);StandardJarScanner jarScanner = new StandardJarScanner();StandardJarScanFilter jarScanFilter = new StandardJarScanFilter();jarScanFilter.setTldSkip(skipScan);jarScanFilter.setPluggabilitySkip(skipScan);jarScanner.setJarScanFilter(jarScanFilter);ctx.setJarScanner(jarScanner)打包原来料想把maven我的项目打到一个jar包不便调用,然而打包插件会把依赖jar包中的class文件进行合并 嵌入式tomcat依赖的jar包有雷同包名的,导致class文件笼罩,websocket相干内容报错 所以把依赖jar包打入到同级lib文件夹中,和waranaget.jar一起拷贝应用 <build> <finalName>${artifactId}</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.code2roc.waragent.Application</mainClass> </manifest> </archive> </configuration> </plugin> <!-- 拷贝依赖的jar包到lib目录 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory> ${project.build.directory}/lib </outputDirectory> </configuration> </execution> </executions> </plugin> </plugins> </build>应用java -jar waragent.jar "启动参数" ...

July 2, 2023 · 1 min · jiezi

关于tomcat:Tomcat处理http请求之源码分析-京东云技术团队

本文将从申请获取与包装解决、申请传递给Container、Container解决申请流程,这3局部来讲述一次http穿梭之旅。 1 申请包装解决tomcat组件Connector在启动的时候会监听端口。以JIoEndpoint为例,在其Acceptor类中: protected class Acceptor extends AbstractEndpoint.Acceptor { @Override public void run() { while (running) { …… try { //以后连接数 countUpOrAwaitConnection(); Socket socket = null; try { //取出队列中的连贯申请 socket = serverSocketFactory.acceptSocket(serverSocket); } catch (IOException ioe) { countDownConnection(); } if (running && !paused && setSocketOptions(socket)) { //解决申请 if (!processSocket(socket)) { countDownConnection(); closeSocket(socket); } } else { countDownConnection(); // Close socket right away closeSocket(socket); } } …… } }}在下面的代码中,socket = serverSocketFactory.acceptSocket(serverSocket);与客户端建设连贯,将连贯的socket交给processSocket(socket)来解决。在processSocket中,对socket进行包装一下交给线程池来解决: ...

May 29, 2023 · 2 min · jiezi

关于tomcat:玩转服务器之Java-Web篇手把手教你搭建Java-Web环境-京东云技术团队

前言Java Web我的项目,简略来说就是咱们在浏览器上能够看到的内容。就简略的Web来说,服务器上也同样须要有计算机上所须要的运行环境,如:java,tomcat,mysql 。Java Web环境能够用来开发和部署各种Web应用程序,例如网站、Web服务、Web后盾管理系统等。特点是跨平台、可靠性高、安全性强、开发效率低等。本篇文章会给你比拟具体的教程,从最根本的开始,循序渐进的深刻。 一、Java Web 环境介绍Java是一门面向对象的编程语言,是目前支流的开发语言之一。本文以轻量云主机(CenTOS 7.6零碎)为例,应用OpenJDK 和 Tomcat 8 演示 Java Web 环境的搭建。 二、前置筹备正式开始部署前,您需实现如下的筹备工作: 开明京东云账户,若您还未注册京东云账号,可在京东云官网进行注册;账户开明后,须要进行实名认证;购买一台或多台云主机或者轻量云主机产品;登录轻量云主机,复制上面步骤中的命令进行执行操作;上面操作步骤需主机凋谢8080端口,请在防火墙中配置端口凋谢策略。三、装置OpenJDK 8yum install java-1.8.0-openjdk装置结束显示如下: 四、装置tomcat下载tomcat,如果提醒没有certificate,请先下载证书。 wget https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.87/bin/apache-tomcat-8.5.87.tar.gz 解压tomcat tar -zxvf ./apache-tomcat-8.5.87.tar.gz解压实现后生成apache-tomcat-8.5.87目录 五、启动tomcat进入tomcat的bin目录执行startup.sh cd ./apache-tomcat-8.5.87/bin./startup.sh启动胜利显示如下: 通过curl测试是否启动胜利 curl http://localhost:8080 在浏览器中拜访形式ip:8080, 如下图所示。如果拜访失败,请查看防火墙策略是否开启了8080端口。 到此,咱们的Java Web环境,就曾经装置配置实现,前面咱们就能够进行开发啦。

May 8, 2023 · 1 min · jiezi

关于tomcat:请求量突增一下系统有效QPS为何下降很多

原创:扣钉日记(微信公众号ID:codelogs),欢送分享,转载请保留出处。简介最近我察看到一个景象,当服务的申请量突发的增长一下时,服务的无效QPS会降落很多,有时甚至会降到0,这种景象网上也偶有提到,但少有解释得分明的,所以这里来分享一下问题成因及解决方案。 队列提早目前的Web服务器,如Tomcat,申请处理过程大略都相似如下: 这是Tomcat申请解决的过程,如下: Acceptor线程:线程名相似http-nio-8080-Acceptor-0,此线程用于接管新的TCP连贯,并将TCP连贯注册到NIO事件中。Poller线程:线程名相似http-nio-8080-ClientPoller-0,此线程个别有CPU核数个,用于轮询已连贯的Socket,接管新到来的Socket事件(如调用端发申请数据了),并将沉闷Socket放入exec线程池的申请队列中。exec线程:线程名相似http-nio-8080-exec-0,此线程从申请队列中取出沉闷Socket,并读出申请数据,最初执行申请的API逻辑。这里不必太关怀Acceptor与Poller线程,这是nio编程时常见的线程模型,咱们将重点放在exec线程池上,尽管Tomcat做了一些优化,但它还是从Java原生线程池扩大进去的,即有一个工作队列与一组线程。 当申请量突发增长时,会产生如下的状况: 当申请量不大时,工作队列根本是空的,每个申请都能失去及时的解决。但当申请量突发时,工作队列中就会有很多申请,这时排在队列前面的申请,就会被解决得越晚,因此申请的整体耗时就会变长,甚至十分长。可是,exec线程们还是在一刻不停歇的解决着申请的呀,按理说服务QPS是不会缩小的呀! 简略想想的确如此,但调用端个别是有超时工夫设置的,不会有限期待上来,当客户端期待超时的时候,这个申请实际上Tomcat就不必再解决了,因为就算解决了,客户端也不会再去读响应数据的。 因而,当队列比拟长时,队列前面的申请,基本上都是不必再解决的,但exec线程池不晓得啊,它还是会判若两人地解决这些申请。 当exec线程执行这些已超时的申请时,若又有新申请进来,它们也会排在队尾,这导致这些新申请也会超时,所以在流量突发的这段时间内,申请的无效QPS会降落很多,甚至会降到0。 这种超时也叫做队列提早,但队列在软件系统中利用得太宽泛了,比方操作系统调度器保护了线程队列,TCP中有backlog连贯队列,锁中保护了期待队列等等。 因而,很多零碎也会存在这种景象,平时响应工夫挺稳固的,但偶然耗时很高,这种状况有很多都是队列提早导致的。 优化队列提早晓得了问题产生的起因,要优化它就比较简单了,咱们只须要让队列中那些长时间未解决的申请临时让路,让线程去执行那些等待时间不长的申请即可,毕竟这些长时间未解决的申请,让它们再等等也无防,因为客户端可能曾经超时了而不须要申请后果了,尽管这毁坏了队列的公平性,但这是咱们须要的。 对于Tomcat,在springboot中,咱们能够如下批改: 应用WebServerFactoryCustomizer自定义Tomcat的线程池,如下: @Componentpublic class TomcatExecutorCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Resource ServerProperties serverProperties; @Override public void customize(TomcatServletWebServerFactory factory) { TomcatConnectorCustomizer tomcatConnectorCustomizer = connector -> { ServerProperties.Tomcat.Threads threads = serverProperties.getTomcat().getThreads(); TaskQueue taskqueue = new SlowDelayTaskQueue(1000); ThreadPoolExecutor executor = new org.apache.tomcat.util.threads.ThreadPoolExecutor( threads.getMinSpare(), threads.getMax(), 60L, TimeUnit.SECONDS, taskqueue, new CustomizableThreadFactory("http-nio-8080-exec-")); taskqueue.setParent(executor); ProtocolHandler handler = connector.getProtocolHandler(); if (handler instanceof AbstractProtocol) { AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler; protocol.setExecutor(executor); } }; factory.addConnectorCustomizers(tomcatConnectorCustomizer); }}留神,这里还是应用的Tomcat实现的线程池,只是将工作队列TaskQueue扩大为了SlowDelayTaskQueue,它的作用是将长时间未解决的工作移到另一个慢队列中,待以后队列中无工作时,再把慢队列中的工作移回来。 ...

January 16, 2023 · 3 min · jiezi

关于tomcat:tomcat的启动过程和原理

 1、背景 SpringBoot是一个框架,一种全新的编程标准,他的产生简化了框架的应用,同时也提供了很多便捷的性能,比方内置tomcat就是其中一项,他让咱们省去了搭建tomcat容器,生成war,部署,启动tomcat。因为内置了启动容器,应用程序能够间接通过Maven命令将我的项目编译成可执行的jar包,通过java-jar命令间接启动,不须要再像以前一样,打包成War包,而后部署在Tomcat中,那么内置tomcat是如何实现的呢? 2、tomcat启动过程及原理 2.1、下载一个springboot我的项目 在这里下载一个我的项目https://start.spring.io/也能够在idea新建SpringBoot-Web工程。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 点击pom.xml会有tomcat依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.1.2.RELEASE</version> <scope>compile</scope> </dependency> 2.2、从启动入口开始一步步摸索 点击进入run办法 public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return run(new Class<?>[] { primarySource }, args); } //持续点击进入run办法 public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { return new SpringApplication(primarySources).run(args); } 进入到这个run办法之后就能够看到,咱们意识的一些初始化事件。次要的过程也是在这里实现的。 2.3、源码代码流程大抵是这样 /** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. * @param args the application arguments (usually passed from a Java main method) * @return a running {@link ApplicationContext} */ public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); /**1、配置零碎属性*/ configureHeadlessProperty(); /**2.获取监听器*/ SpringApplicationRunListeners listeners = getRunListeners(args); /**公布利用开始启动事件 */ listeners.starting(); try { /** 3.初始化参数 */ ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); /** 4.配置环境*/ ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); /**5.创立利用上下文*/ context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); /**6.预处理上下文*/ prepareContext(context, environment, listeners, applicationArguments, printedBanner); /**6.刷新上下文*/ refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } /** 8.公布利用曾经启动事件 */ listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { /** 9.公布利用曾经启动实现的监听事件 */ listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; } 代码中次要就是通过switch语句,依据webApplicationType的类型来创立不同的ApplicationContext: ...

December 22, 2022 · 3 min · jiezi

关于tomcat:Bug解决思路Tomcat返回不安全的响应头

背景概述公司平安测试要求接口的申请办法只能是GET, POST,并且响应头也只能为GET, POST. 问题形容在理解到这个需要后,我在过滤器对所有进入服务的申请对立设置响应头: @WebFilter(urlPatterns = "/*", filterName = "GlobalFilter")public class GlobalFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException { log.info(">>>>>>>>>>>>>>>>>>>> doFilter <<<<<<<<<<<<<<<<<<<<"); HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS"); response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers")); filterChain.doFilter(servletRequest, response); }}写这段代码是因为我下意识地认为只有设置一个全局的响应头,将 Access-Control-Allow-Methods 设置为GET,POST 就能够轻松实现测试提出的,响应头只能为GET, POST的需要. 这段代码帮我解决了大部分问题,我在自测时“GET,HEAD,POST,PUT,DELETE,OPTIONS”它们的响应头都胜利返回了 GET、POST。贴一张 OPTIONS 申请的截图,他的Allow-Methos胜利的返回了 GET,POST. 到这你是不是感觉问题就曾经解决了? 并没有,事件没这么简略,测试很快就让我打脸了,请看下图,当 uri 改为 * 时,Allow 的返回值让我不敢相信本人的眼睛。 问题剖析在应用 burpsuite 复现问题时,我发现服务的过滤器并没有拦挡到 options * 申请,也就是说申请在进入过滤器前就曾经被解决并响应了。 ...

November 1, 2022 · 1 min · jiezi

关于tomcat:tomcat-端口-8005-被-windows-系统服务占用导致启动闪退的问题

我的 tomcat 装置在这个目录下:C:\app\tomcat-9.0.56 执行 bin 文件夹下的 startup.bat 时,遇到闪退的问题。 查看 logs 文件夹下的日志文件 catalina.2022-10-29.log: 遇到如下谬误音讯: HostConfig.deployDirectory Deployment of web application directory [C:\app\tomcat-9.0.56\webapps\ROOT] has finished in [37] ms29-Oct-2022 17:21:47.262 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]29-Oct-2022 17:21:47.951 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [2830] milliseconds29-Oct-2022 17:21:47.963 SEVERE [main] org.apache.catalina.core.StandardServer.await Failed to create server shutdown socket on address [localhost] and port [8005] (base port [8005] and offset [0])java.net.BindException: Address already in use: NET_Bind at java.base/java.net.PlainSocketImpl.bind0(Native Method) at java.base/java.net.PlainSocketImpl.socketBind(PlainSocketImpl.java:132) at java.base/java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:452) ...

October 31, 2022 · 1 min · jiezi

关于tomcat:88tomcat-指定目录部署的配置完整的serverxml

<?xml version="1.0" encoding="UTF-8"?><!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You 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 http://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.--><!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html --><Server port="8102" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" /> --> <!--APR library loader. Documentation at /docs/apr.html --> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <!-- Prevent memory leaks due to use of particular java/javax APIs--> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html --> <GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html --> <Service name="Catalina"> <!--The connectors can use a shared executor, you can define one or more named thread pools--> <!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/> --> <!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080 --> <Connector port="8002" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <!-- A "Connector" using the shared thread pool--> <!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> --> <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation. The default SSLImplementation will depend on the presence of the APR/native library and the useOpenSSL attribute of the AprLifecycleListener. Either JSSE or OpenSSL style configuration may be used regardless of the SSLImplementation selected. JSSE style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true"> <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2 This connector uses the APR/native implementation which always uses OpenSSL for TLS. Either JSSE or OpenSSL style configuration may be used. OpenSSL style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol" maxThreads="150" SSLEnabled="true" > <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig> <Certificate certificateKeyFile="conf/localhost-rsa-key.pem" certificateFile="conf/localhost-rsa-cert.pem" certificateChainFile="conf/localhost-rsa-chain.pem" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8202" protocol="AJP/1.3" redirectPort="8443" /> <!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --> <!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"> --> <Engine name="Catalina" defaultHost="localhost"> <!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --> <!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> --> <!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="127.0.0.1" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Alias>s114.tomcat</Alias> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /> </Host> <Host name="localhost" appBase="_empty" unpackWARs="true" autoDeploy="true"> </Host> <Host name="js.homlin.com" appBase="_empty" unpackWARs="true" autoDeploy="true"> <Context path="" docBase="E:\webapps\js.homlin.com\webapp" sessionCookiePath="/" /> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="js.homlin.com/access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /> </Host> </Engine> </Service></Server>

October 20, 2022 · 4 min · jiezi

关于tomcat:startupbat一闪而过

这次关上tomcat。startup.bat又一闪而过了,我想了想难道是前两天的没弄好么,不对啊,我记得曾经好了,我过来看了看,发现之前改的配置还在,那证实不是上次的问题,接下来找找问题。 一、问题解决样再startup.bat前面加上pause,在窗口上发现环境变量已启动。 startup.bat启动tomcat时流程是:startup->catalina->setclasspath->catalina 为了更具体的看到信息,咱们找到call "%EXECUTABLE%" start %CMD_LINE_ARGS% 把外面的start替换为run。发现起因是server.xml文件找不到了,果然我关上conf文件夹发现server.xml文件,发现没有server.xml文件,可能是改文件的时候不晓得弄哪去了,加上了就好了。 二、error occurred during initialization of vm could not reserve enough space for object heap could not create the java virtual machine当呈现这个谬误是,这是咱们须要设置tomcat利用内存了。 剖析起因:因为程序初始化时申请不到足够的内存,导致vm程序退出 解决办法: 设置tomcat的利用内存,在catalina.bat中 找到Execute The Requested Command上面的set JAVA_OPTS把这一句替换为 set JAVA_OPTS=  -Xms800m -Xmx800m 或者 set JAVA_OPTS= -server -Xms800m -Xmx800m -XX:MaxNewSize=256m  阐明: - Xms为tomcat启动初始内存 - Xmx为tomcat最大占用内存,以上两个参数关系到tomcat接受的拜访性能,但也要依据服务器理论内存状况设定。

September 29, 2022 · 1 min · jiezi

关于tomcat:tomcatThis-environment-variable-is-needed-to-run-this-program

明天应用皕杰平台启动tomcat时,startup.bat一闪而过,咱们在startup.bat外面end前面加上pause,这是咱们就会发现报This environment variable is needed to run this program这个错,这是JAVA_HOME的环境变量配置出错,而后我去查看了环境变量,奇怪配置的没有错。   个别通过startup.bat启动tomcat时流程是:startup->catalina->setclasspath->catalina,最初找到解决方案如下。 进入cmd命令行窗口,cd进入到Tomcat的bin文件夹,在bin下输出startup.bat,运行tomcat,报如下谬误: The JRE_HOME environment variable is not defined correctly This environment variable is needed to run this program 首先咱们检测本人电脑jdk有没有装好:进行cmd命令行窗口,输出javac等指令都能够,如果没问题的话,那就是少了上面配置 1.用记事本关上tomcat/bin/setclasspath.bat 2.在最后面增加代码,jdk根目录,相当于间接给出JAVA_HOME和JRE_HOME门路 eg: set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_202 只设置JAVA_HOME就行,JRE_HOME 当初不须要了,如下图第一行所示,上面那个jre不必写了 接下来保留,启动胜利。

September 26, 2022 · 1 min · jiezi

关于tomcat:tomcat的webapps目录下的应用删除部署

1.tomcat9的webapps下利用的拜访tomcat9的server.xml文件中 <Host>下须要加一段: <Context docBase="/xxx/tomcat9/webapps/xxx" path="/" reloadable="true"></Context>改完后大抵为: <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context docBase="/xxx/tomcat9/webapps/xxx" path="/" reloadable="true"></Context>留神: path="/" 意思是,相当于指定此利用作为和默认时ROOT的拜访形式-->根目录拜访localhost 能够改为具体的域名,比方 www.niewj.com,具体理论看你的域名2. 进一步:删除webapps下所有目录,只留本人利用2.1 删除阐明docs、examples和ROOT这几个文件夹是能够间接删除的;host-manager和manager删除后会有日志告警,要打消,须要做如下操作2.2 须要删除的内容tomcat/conf/logging.properties 删除局部配置: [1] handlers删除两项: 3manager.org.apache.juli.AsyncFileHandler, 4host-manager.org.apache.juli.AsyncFileHandler,[2] 上面该两项相干的也都删掉(注掉即可): # 3manager.org.apache.juli.AsyncFileHandler.level = FINE# 3manager.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs# 3manager.org.apache.juli.AsyncFileHandler.prefix = manager.# 3manager.org.apache.juli.AsyncFileHandler.maxDays = 90# 3manager.org.apache.juli.AsyncFileHandler.encoding = UTF-8# 4host-manager.org.apache.juli.AsyncFileHandler.level = FINE# 4host-manager.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs# 4host-manager.org.apache.juli.AsyncFileHandler.prefix = host-manager.# 4host-manager.org.apache.juli.AsyncFileHandler.maxDays = 90# 4host-manager.org.apache.juli.AsyncFileHandler.encoding = UTF-83. 小结而后,webapps 下所有都删掉,只保留本人业务相干的利用即可,而且配合第一点,间接localhost:8080/拜访就是本人的利用。 参考:https://blog.csdn.net/flyinga...

September 8, 2022 · 1 min · jiezi

关于tomcat:Tomcat原理剖析tomcat介绍和源码idea构建

一、Tomcat 介绍1.1 什么是TomcatTomcat 服务器是一个开源的轻量级Web应用服务器,在中小型零碎和并发量小的场合下被广泛应用,是开发和调试Servlet、JSP 程序的首选。简直所有Java程序员初期都会应用它,明天咱们就带着大家深刻Tomcat底层原理。除了tomcat服务器,咱们还能够应用其余的web服务器,那常见还还有以下这些: Undertow:是一个采纳 Java 开发的灵便的高性能 Web 服务器,提供包含阻塞和基于 NIO 的非梗塞机制。JBoss:JBoss公司的,大型的JavaEE服务器,反对所有的JavaEE标准,免费的。WebLogic:Oracle公司,大型的JavaEE服务器,反对所有的JavaEE标准,免费的。WebSphere:IBM公司,大型的JavaEE服务器,反对所有的JavaEE标准,免费的。 历史沿革 Tomcat 最后由Sun公司的软件架构师 James Duncan Davidson 开发,名称为 “JavaWebServer”。1999年,在 Davidson 的帮忙下,该我的项目于 1999 年于apache 软件基金会旗下的 JServ 我的项目合并,并公布第一个版本(3.x), 即是当初的Tomcat,该版本实现了Servlet2.2 和 JSP 1.1 标准 。2001年,公布4.0版本,作为里程碑式的版本,Tomcat 齐全从新设计了其架构,并实现了 Servlet2.3 和 JSP1.2标准。2003年,公布5.0版本,实现 Servlet 2.4 和 JSP2.0标准。2007年,公布6.0版本,实现 Servlet 2.5 、JSP2.1 标准。反对EL1.1标准。2011年,公布7.0版本,实现 Servlet 3.0 和 JSP2.2标准。反对EL2.2标准。退出了WebSocket规范。2014年,公布8.0版本,实现 Servlet 3.1 和 JSP2.3标准。反对EL3.0标准。2016年,公布8.5版本,实现 Servlet 3.1 和 JSP2.3标准。反对HTTP/2,OpenSSL,TLS虚拟主机和JASPIC1.1。2018年,公布9.0版本,实现 Servlet 4.0 标准。目前 Tomcat 曾经更新到 10.0.x版本 , 然而目前企业中的Tomcat服务器, 支流版本是8.5 , 所以本课程是基于 8.5 版本进行解说。 ...

August 10, 2022 · 1 min · jiezi

关于tomcat:Linux系统安装Tomcat

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 我的项目中的一个外围我的项目,由Apache、Sun 和其余一些公司及集体共同开发而成。因为有了Sun 的参加和反对,最新的Servlet 和JSP 标准总是能在Tomcat 中失去体现,Tomcat 5反对最新的Servlet 2.4 和JSP 2.0 标准。因为Tomcat 技术先进、性能稳固,而且收费,因此深受Java 爱好者的青睐并失去了局部软件开发商的认可,成为比拟风行的Web 应用服务器。 1、首先去官网下载安装包https://tomcat.apache.org/dow...Tomcat须要在jdk的环境下,能够参考之前的文件装置 2、解压安装包 tar zxvf apache-tomcat-8.5.16.tar.gz -C /opt/ 3、挪动文件夹并命名为tomcat mv apache-tomcat-8.5.16 /usr/local/tomcat8 4、敞开防火墙systemctl stop firewalld.service 5、启动Tomcat/usr/local/tomcat8/bin/startup.sh 6、监听端口,看是否胜利,而后到浏览器输出ip:8080拜访页面netstat -ntap | grep 8080 我的试验环境是租的服务器,他们的价格便宜而且带宽高,不便做试验

August 3, 2022 · 1 min · jiezi

关于tomcat:问题记录TomcatTomcat启动报错Possiblefor-Xss-and-illegal

Tomcat启动报错:Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies错误代码如下: Caused by: java.lang.IllegalStateException: Unable to complete the scan for annotations for web application [] due to a StackOverflowError. Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies. The class hierarchy being processed was [org.bouncycastle.asn1.ASN1Boolean->org.bouncycastle.asn1.DERBoolean->org.bouncycastle.asn1.ASN1Boolean] at org.apache.catalina.startup.ContextConfig.checkHandlesTypes(ContextConfig.java:2139) at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2083) at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:2029) at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1999) at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1952) at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1156) at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:765) at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:299) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4989) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ... 42 more网上给的答案都是调整Xss参数,其实不是正确的做法, ...

July 29, 2022 · 1 min · jiezi

关于tomcat:tomcat如何调试源码

目录构造先看下整体的目录构造是什么样子,以及每个内容的作用,而后前面讲怎么失去这些内容。 下载源码去官网下载2个货色 一个是源码我的项目,一个是作为工作目录。 目录构造是怎么来的?先创立一个根目录,作为我的项目根目录。 而后把方才下载的2个货色,解压之后,复制到根目录。 最初,手动创立2个pom文件: 1.我的项目根目录 <?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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>gxf</groupId> <artifactId>apache-tomcat-9</artifactId> <name>apache-tomcat-9-source</name> <version>1.0</version> <packaging>pom</packaging> <modules> <module>apache-tomcat-8.5.81-src</module> </modules> </project>2.源码我的项目目录 <?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>org.apache.tomcat</groupId> <artifactId>Tomcat9.0</artifactId> <name>Tomcat9.0</name> <version>9.0</version> <build> <finalName>Tomcat9.0</finalName> <sourceDirectory>java</sourceDirectory> <testSourceDirectory>test</testSourceDirectory> <resources> <resource> <directory>java</directory> </resource> </resources> <testResources> <testResource> <directory>test</directory> </testResource> </testResources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <encoding>UTF-8</encoding> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>ant</groupId> <artifactId>ant</artifactId> <version>1.7.0</version> </dependency> <dependency> <groupId>ant</groupId> <artifactId>ant-apache-log4j</artifactId> <version>1.6.5</version> </dependency> <dependency> <groupId>ant</groupId> <artifactId>ant-commons-logging</artifactId> <version>1.6.5</version> </dependency> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>1.6.2</version> </dependency> <dependency> <groupId>javax.xml.rpc</groupId> <artifactId>javax.xml.rpc-api</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.eclipse.jdt.core.compiler</groupId> <artifactId>ecj</artifactId> <version>4.6.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.easymock/easymock --> <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <version>4.3</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.unboundid/unboundid-ldapsdk --> <dependency> <groupId>com.unboundid</groupId> <artifactId>unboundid-ldapsdk</artifactId> <version>5.1.4</version> <scope>test</scope> </dependency> </dependencies></project>idea配置筹备好内容之后,导入idea(导入之后,就是目录构造里展现的那样),而后须要配置一些货色。 ...

July 19, 2022 · 1 min · jiezi

关于tomcat:tomcat源码分析如何接收连接如何读数据

外围流程脑图 监听端口外围步骤 1.创立服务器套接字 2.监听端口 接管连贯外围步骤:接管客户端连贯。 总结 接管客户端连贯,是一个专门的线程。说白了,就是这个线程,专门干这个事件:只接管客户端连贯。从客户端读数据是读线程池解决。 监听读事件外围步骤 1.监听都事件 一直轮询读事件 2.获取读事件 3.解决读事件 即读数据,最终是交给读线程池读数据 轮询读事件 解决读事件 具体是交给读线程池解决读数据 总结 1.监听事件线程 监听事件是一个独立的线程,专门用于监听事件,实质是一直轮询事件。 2.读数据线程池 最终的读数据是交给读数据线程池去执行。为什么?因为读数据比较慢。 读数据外围步骤:读数据。 读数据:调用servlet类的service办法 架构图流程图 读线程池在哪里创立?在监听端口的时候,就曾经创立了。 真正创立读线程池的中央 读线程池配置(最小10,最大200-这里就是tomcat默认200的起源)。

July 11, 2022 · 1 min · jiezi

关于tomcat:tomcat源码分析

https://blog.csdn.net/nmjhehe...

May 12, 2022 · 1 min · jiezi

关于tomcat:Tomcat改jar

Tomcat改jar插件批改<!-- <plugin>--><!-- <groupId>org.apache.maven.plugins</groupId>--><!-- <artifactId>maven-war-plugin</artifactId>--><!-- <version>3.1.0</version>--><!-- <configuration>--><!-- <resourceEncoding>UTF-8</resourceEncoding>--><!-- </configuration>--><!-- </plugin>--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>HuanProviderApplication</mainClass> </configuration> </plugin>主类批改package com;import com.fedtech.commons.util.SpringContextUtils;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;import org.springframework.boot.builder.SpringApplicationBuilder;import org.springframework.boot.web.support.SpringBootServletInitializer;import org.springframework.context.annotation.Bean;import org.springframework.scheduling.annotation.EnableScheduling;@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})@EnableSchedulingpublic class HuanProviderApplication extends SpringBootServletInitializer { public static void main(String[] args) { System.setProperty("spring.devtools.restart.enabled", "false"); SpringApplication.run(HuanProviderApplication.class, args); } @Bean public SpringContextUtils springContextUtils(){ return new SpringContextUtils(); }// @Override// protected SpringApplicationBuilder configure(SpringApplicationBuilder application){// return application.sources(HuanProviderApplication.class);// }} 打包形式批改<artifactId>huan-provider</artifactId><!-- <packaging>war</packaging>--><packaging>jar</packaging><dependencies>

May 11, 2022 · 1 min · jiezi

关于tomcat:关于本地Tomcat服务器的内网穿透

相干TomcatTomcat服务器是一个开源的轻量级Web应用服务器下载地址Apache Tomcat® - Welcome!网云穿内网穿透工具,大略作用就是把本地的服务器的我的项目公布到外网下载地址网云穿内网穿透 (xiaomy.net) 步骤1.进入网云穿的官网后点击登录注册,新用户能够支付一条收费隧道2.支付完隧道之后,会跳转到控制台让咱们配置隧道信息,输出相干信息即可3.ipv4的查问:win+r输出cmd关上命令提示符,输出ipconfig能够查问到本机IP地址如图: 4.绑定Tomcat的端口,Tomcat服务器的默认端口为8080,Apache服务器的默认端口为80,也能够本人更改服务器的端口号,到服务器的配置文件,在conf目录上面关上server.xml文件 <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />批改8080后保留重启服务即可 启动下载网云穿客户端,启动隧道 协定+映射地址+服务,公网上拜访即可

February 25, 2022 · 1 min · jiezi

关于tomcat:深入源码了解Tomcat加载servlet的过程

Tomcat加载servlet过程有人活了大半辈子还不晓得servlet是啥?它在tomcat中又是怎么生存的呢?来,安顿上~~ 让咱们把回顾拉回到很久很久以前,呃,就是 springboot 启动的工夫点,找到 ServletWebServerApplicationContext#refresh() 这个办法,走上来,是 onRefresh() 办法里的createWebServer() 办法,点开它: 这里以 dispatcherServlet 的加载为例,待会就盯着她。点开getSelfInitializer()办法,在要害中央打个断点: 能够看到,这里通过getServletContextInitializerBeans()办法,获取到所有的 ServletContextInitializer进行遍历,调用各自的 onStartup()。在遍历到 DispatcherServletRegistrationBean的时候,进入 onStartup()办法看看: 曾经看到dispatcherServlet了,感觉离胜利不远啰~ 点 register(description, servletContext)进去: 再点 addRegistration()进入,拼上最初一口气,追到这里,看要害代码: private ServletRegistration.Dynamic addServlet(String servletName, String servletClass, Servlet servlet, Map<String,String> initParams) throws IllegalStateException { …… // 查找context里是否有该servlet(这里的context是TomcatEmbeddedContext, // servletName是 dispatcherServlet) Wrapper wrapper = (Wrapper) context.findChild(servletName); // 查找不到,则创立一个增加到context中。Wrappe 封装了servlet if (wrapper == null) { wrapper = context.createWrapper(); wrapper.setName(servletName); context.addChild(wrapper); } ……… // 持续设置wrapper的servlet属性 wrapper.setServletClass(servlet.getClass().getName()); wrapper.setServlet(servlet); …… // 构建 ApplicationServletRegistration返回 ServletRegistration.Dynamic registration = new ApplicationServletRegistration(wrapper, context); return registration; }啰啰嗦嗦了半天,一句话概括就是:把servlet注册到context里 ...

December 14, 2021 · 1 min · jiezi

关于tomcat:Tomcat体系结构

Tomcat的体系结构1.Tomcat是实现了Servlet标准的web容器,可能解决http/https协定2.Tomcat由多个组件形成,Server,Service,Engine,Connector,Host,Context,不同组件负责不同的性能3.Tomcat通过Catalina将server.xml解析并实例化Server实例4.一个Server实例蕴含多个Service容器实例,Service由多个连接器Connector和一个Engine形成5.Connector负责解决客户端发动的申请协定,Connector将连贯信息封装成为Request申请对象和Response响应对象,并通过适配器Adaptor转换成容器能够解决的对象6.Connector与Engine容器进行通信,一个Engine容器由多个Host虚拟主机对象形成7.每个Host中能够配置多个Context对象,即部署多个我的项目。8.一个Context蕴含多个Wrapper通过解析web.xml将Servlet封装到Wrapper容器中。8.浏览器收回的申请信息,通过Mapper映射器找到对应的Wrapper容器,并将定义的filter一起组成FilterChain执行Servlet中的Service办法,最初将信息封装成Response返回给客户端

December 13, 2021 · 1 min · jiezi

关于tomcat:深入源码了解-Tomcat-的构造

Tomcat外部原理Tomcat 大家始终都在用,也用了好多年了,然而 Tomcat 到底是啥,外部是咋样的,不晓得~来,我从源码角度,给大家揭开它的面纱~ 1. Tomcat架构 这个是tomcat的架构图,专治密集恐惧症患者~~虚线的代表同一多个Server:代表一个运行的tomcat实例,蕴含一个或多个service子容器Service: 代表tomcat中一组解决申请,提供服务的组件,蕴含多个Connector和一个ContainerConnector: 在指定IP、端口、协定下监听客户端申请,创立Request 、Response 给 Engine,从Engine取得响应给客户端。Connector是通过ProtocolHandler 来解决申请的,ProtocolHandler蕴含三个部件:Endpoint、Processor、Adapter Endpoint: 解决底层socket 网络连接。Acceptor 监听申请,Handler解决接管到的socket, AsyncTimeout 查看异步Request的超时Processor: 将Endpoint 接管到的Socket 封装成RequestAdapter: 将Request 交给Container 解决Container: 容器的父接口,用于封装和治理 Servlet,采纳责任链设计模式,蕴含四个组件 Engine: 可运行的servlet 引擎实例,一个服务中只有一个。次要性能是将申请委托给适当虚拟主机解决。Host: Engine的子容器,一个Host代表一个虚拟主机,一个虚拟主机能够部署一个或多个Web App,每个Web App对应一个ContextContext: 代表Servlet 的Context,是Servlet的根本运行环境,示意web利用自身。它最重要性能是治理外面的servletWrapper: 示意一个独自的Servlet,是Context的子容器,也是最底层的容器,没有子容器了。治理 Servlet的装载、初始化、执行和资源回收2. Tomcat源码咱们来追踪 SpringBoot启动过程,看一下它是怎么创立Tomcat的。 跟到 ServletWebServerApplicationContext#refresh()办法,如图: 点开 createWebServer()办法: 进入TomcatServletWebServerFactory#getWebServer(): 一步步来看tomcat的构建过程。 设置运行门路 File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");tomcat.setBaseDir(baseDir.getAbsolutePath());增加 Connector Connector connector = new Connector(this.protocol);connector.setThrowOnFailure(true);tomcat.getService().addConnector(connector);先点getService()进去看下: public Service getService() { return getServer().findServices()[0];}再点getServer()看看: ...

December 9, 2021 · 2 min · jiezi

关于tomcat:Tomcat技术原理浅析

前言依照常规,厘清利用之间的关系,使学习自身造成一个体系框架。Tomcat、常见的一个Web应用服务器(临时以此称说,下文会有分类辨析),旨在总结学习过程中的重点,相应常识不清晰时能够有一个绝对清朗的概念,底层原理倡议从专业书籍中获取。 辨析Web服务器、应用程序服务器与Web容器随着技术的逐步倒退,各个服务器的性能都在逐步扩大,界线也越来越含糊,以至于初听到这些名词的时候,感觉不能了解。最好的了解应该是在特定的利用场景下对具体的技术深刻理解,而后再做体系的学习。先介绍三个概念,再简略对服务器作一个划分。 Web服务器:基本功能是提供Web信息浏览服务,存储、解决和传递网页给客户端,应用HTTP协定进行传输,不波及非动态资源的获取。其波及到的功能模块次要如下: TCP监听模块:服务器监听某个端口(个别是8080端口),以建设与客户端之间的连贯预处理:此处次要做三件事:1. 从TCP报文中获取HTTP申请报文。 2. 依据和用户代理的协商进行解密,解压,平安解决等。3. 依据服务器本身的配置进行平安解决,建设会话状态等URI路由:解析URL字符串和动作以确定用户代理申请的资源,依据匹配规定(通常依据正则表达式+后缀)路由到动态资源解决模块或动静资源解决模块动态资源解决模块:负责找到动态资源,比方HTML/Javascript/CSS文件/图片/图像,确定内容是字符流或者字节流,并确定对应MIME,比方HTML生成MIME为text/html的字符流,mpeg视频文件生成MIME为video/mpeg的字节流动静资源解决模块:运行业务解决逻辑,我了解是调用其余程序对应的服务解决信息。后处理:依据和客户端协商的协定进行加密,压缩,平安解决等资源输出模块:把解决好的内容和类型封装成HTTP报文,发送到TCP连贯的另一端应用程序服务器:作为应用程序服务器,它通过各种协定(包含HTTP协定),把商业逻辑裸露给(expose)客户端应用程序。Web服务器次要是解决向浏览器发送HTML以供浏览,而应用程序服务器提供拜访商业逻辑的路径以供客户端应用程序应用。应用程序应用此商业逻辑就象你调用对象的一个办法(或过程语言中的一个函数)一样。 在大多数情景下,应用程序服务器是通过组件(component)的利用程序接口(API)把商业逻辑裸露(expose)(给客户端应用程序)的,例如基于J2EE(Java 2 Platform, Enterprise Edition)应用程序服务器的EJB(Enterprise JavaBean)组件模型。此外,应用程序服务器能够治理本人的资源,例如看大门的工作(gate-keeping duties)包含平安(security),事务处理(transaction processing),资源池(resource pooling), 和音讯(messaging)。就象Web服务器一样,应用程序服务器配置了多种可扩大(scalability)和容错(fault tolerance)技术。 Web容器:能够了解为加强Web服务器动静获取资源的能力,以下是代表性的动静获取资源技术: 技术名词特点CGI 专用网关接口以独立过程运行,能够用多种语言开发,比方C,C++,VB,Perl,灵便但效率低,保护简单PHP服务器端嵌入HTML脚本,开源,功能强大,扩展性较差JSP服务器端嵌入HTML脚本,跨平台,部署前需编译,次要毛病是编写JSP比较复杂,需相熟JAVA及相干技术ASP服务器端嵌入HTML脚本,开发简略,功能强大,只能在windows下运行开发一个Web程序开发框架,蕴含运行环境(比方解释执行JSP、Php等),解决鲁捧性、可靠性,提供疾速开发接口,开发人员专一于业务实现,框架也提供定制和扩大,这个框架也称为Web容器。相比拟于,减少的次要功能模块为: 调配线程池资源:容器为每个申请调配一个线程进行解决,通常采取线程池的形式高效理由CPU算资源封装Request/Response上下文:一个申请对应一个上下文,Request申请包含URL、Http申请、以及构建的Session、Cookie等对象URl路由动静资源解决模块:比方Java的Servlet回收资源:回收线程资源,个别都以线程池形式实现,所以将线程返回线程池一些支流服务器 名词Web服务器Web容器应用程序服务器反向代理反对IIS✅✅ ✅Nginx✅ ✅Apache✅ ✅Tomcat✅✅✅ Jetty✅✅✅ WebSphere✅✅✅ WebLogic✅✅✅ 能够见到 Web服务器:IIS、Nginx、Apache 应用程序服务器:WebSphere、WebLogic 至于Tomcat、Jetty,其提供了动态资源服务器的性能,也扩大了应用程序服务器的一些性能。所以其个别称为Web容器,也有叫做轻量级应用程序服务器,其余叫法依我看是不太精确的。 还有一个观点,既然Tomcat蕴含了动态服务器的性能,兼具应用程序服务器的某些个性,那只用Tomcat、Jetty就行了??emmm模棱两可,实际上个别在Tomcat这些Web容器前流量会走一层Nginx做代理,同时解决动态资源。 最初赘述一点,Jetty与Tomcat同为ServletWeb容器,次要解决HTTP;Netty是一个高性能、异步事件驱动的 NIO 框架,它提供了对 TCP、UDP 和文件传输的反对。 Tomcat底层Tomcat的架构核心内容是Connector和Container组件 一个Server服务器中可能有多个Service,Service能够临时了解为“服务”。Server负责管理Service的生命周期,让外界可能拜访,Service将Connector和Container分割在一起。 Connector:负责创立Request和Response对象 Container EngineHost:虚拟主机Context:所属Web利用的上下文Wrapper:针对每一个具体的Servlet本想着具体介绍一点,这部分材料很多,不仅反复且不迭别人优良,能够联合Tomcat的配置文件了解一下其架构。

October 16, 2021 · 1 min · jiezi

关于tomcat:锁屏面试题百日百刷tomcat优化相关

锁屏面试题百日百刷,每个工作日保持更新面试题。锁屏面试题app、小程序现已上线,官网地址:https://www.demosoftware.cc/#/introductionPage。已收录了每日更新的面试题的所有内容,还蕴含特色的解锁屏幕温习面试题、每日编程题目邮件推送等性能。让你在面试中后人一步,吊打面试官!接下来的是今日的面试题: ====tomcat优化教训?优化连贯配置.这里以tomcat7的参数配置为例,须要批改conf/server.xml文件,批改连接数,敞开客 户端dns查问。 参数解释: URIEncoding=”UTF-8″ :使得tomcat能够解析含有中文名的文件的url,真不便,不像apache里还有搞 个mod_encoding,还要手工编译 maxSpareThreads : 如果闲暇状态的线程数多于设置的数目,则将这些线程停止,缩小这个池中的线程总 数。minSpareThreads : 最小备用线程数,tomcat启动时的初始化的线程数。 enableLookups : 这个效用和Apache中的HostnameLookups一样,设为敞开。 connectionTimeout : connectionTimeout为网络连接超时工夫毫秒数。 maxThreads : maxThreads Tomcat应用线程来解决接管的每个申请。这个值示意Tomcat可创立的最大 的线程数,即最大并发数。 acceptCount : acceptCount是当线程数达到maxThreads后,后续申请会被放入一个期待队列,这个 acceptCount是这个队列的大小,如果这个队列也满了,就间接refuse connection maxProcessors与minProcessors : 在 Java中线程是程序运行时的门路,是在一个程序中与其它管制 线程无关的、可能独立运行的代码段。它们共享雷同的地址空间。多线程帮忙程序员写出CPU最 大利用率的高 效程序,使闲暇工夫放弃最低,从而承受更多的申请。 通常Windows是1000个左右,Linux是2000个左右。 useURIValidationHack: 咱们来看一下tomcat中的一段源码:【security】 if (connector.getUseURIValidationHack()) { String uri = validate(request.getRequestURI()); if (uri == null) { res.setStatus(400); res.setMessage(“Invalid URI”);throw new IOException(“Invalid URI”); } else { req.requestURI().setString(uri); // Redoing the URI decoding req.decodedURI().duplicate(req.requestURI()); req.getURLDecoder().convert(req.decodedURI(), true); 能够看到如果把useURIValidationHack设成”false”,能够缩小它对一些url的不必要的查看从而减省开 销。enableLookups=”false” : 为了打消DNS查问对性能的影响咱们能够敞开DNS查问,形式是批改 server.xml文件中的enableLookups参数值。 disableUploadTimeout :相似于Apache中的keeyalive一样 给Tomcat配置gzip压缩(HTTP压缩)性能 compression=”on” compressionMinSize=”2048″ compressableMimeType=”text/html,text/xml,text/JavaScript,text/css,text/plain” HTTP 压缩能够大大提高浏览网站的速度,它的原理是,在客户端申请网页后,从服务器端将网页文件压缩, 再下载到客户端,由客户端的浏览器负责解压缩并浏览。绝对于一般的浏览过程HTML,CSS,javascript , Text ,它能够节俭40%左右的流量。更为重要的是,它能够对动静生成的,包含CGI、PHP , JSP , ASP , Servlet,SHTML等输入的网页也能进行压缩,压缩效率惊人。 1)compression=”on” 关上压缩性能 2)compressionMinSize=”2048″ 启用压缩的输入内容大小,这外面默认为2KB 3)noCompressionUserAgents=”gozilla, traviata” 对于以下的浏览器,不启用压缩 4)compressableMimeType=”text/html,text/xml” 压缩类型 最初不要忘了把8443端口的中央也加上同样的配置,因为如果咱们走https协定的话,咱们将会用到8443端 口这个段的配置:<!–enable tomcat ssl–> <Connector port=”8443″ protocol=”HTTP/1.1″ URIEncoding=”UTF-8″ minSpareThreads=”25″ maxSpareThreads=”75″ enableLookups=”false” disableUploadTimeout=”true” connectionTimeout=”20000″ acceptCount=”300″ maxThreads=”300″ maxProcessors=”1000″ minProcessors=”5″ useURIValidationHack=”false” compression=”on” compressionMinSize=”2048″ compressableMimeType=”text/html,text/xml,text/javascript,text/css,text/plain”SSLEnabled=”true” scheme=”https” secure=”true” clientAuth=”false” sslProtocol=”TLS” keystoreFile=”d:/tomcat2/conf/shnlap93.jks” keystorePass=”aaaaaa”/> ...

July 23, 2021 · 2 min · jiezi

关于tomcat:Tomcat端口地址已在使用-Bind-failed

环境 Linux/Ubuntu20.04LTSIntelliJ IDEA Community Editon 2021.1java-11-openjdk-amd64apache-tomcat-7.0.109异样 tomcat服务端口被占用! 重大: Failed to initialize end point associated with ProtocolHandler ["http-bio-8087"]java.net.BindException: 地址已在应用 (Bind failed) <null>:80877月 14, 2021 9:45:36 下午 org.apache.catalina.core.StandardServer await重大: StandardServer.await: create[localhost:8005]: 起因 端口地址已在应用,端口地址抵触上次运行服务没有及时敞开,服务仍在运行,故造成端口抵触计划 端口抵触,间接批改配置文件里的端口号后,从新运行我的项目 服务未及时敞开造成,敞开上次运行的服务,关上tomcat目录所在文件,间接敞开服务,执行 $ ./shutdown.shlauiji@lauiji-IdeaPad-15sIML-2020:/usr/local/apache-tomcat-7.0.109/bin$ ./shutdown.sh从新运行我的项目即可 阐明 【遇上旱季,吃定彩虹】 --Layuji由集体整顿公布,编写过程不免有所脱漏或谬误,恳请指出,免得误导大家!

July 14, 2021 · 1 min · jiezi

关于tomcat:Tomcat-基础及配置

一、原理1. 浏览器拜访服务器流程用户输出申请到浏览器浏览器发送TCP连贯申请服务器接管到(疏忽Nginx等状况)申请并三次握手建设连贯浏览器生成HTTP的数据包并发送服务器收到并解析服务器执行申请并封装后果发送浏览器收到HTTP格局数据包并解析渲染2. Tomcat申请解决流程首先,Tomcat是一个HTTP服务器 Tomcat中的HTTP服务器(Connectot组件)在接管到申请之后把申请交给Servlet容器(Conntainer组件)来解决(解耦),Servlet容器通过Servlet接口调用业务类,Servlet容器这一套内容叫做Servlet标准 3. Servlet容器解决流程HTTP服务器把申请信息应用ServletRequest对象封装依据配置,找到url和Servlet的映射, 调用Servlet容器中的某个具体Servlet如果Servlet还没有加载,就用反射机制创立这个Servlet,并调用Servlet的init办法来实现初始化调用这个Servlet的service办法解决申请,处理结果用ServletResponse对象封装ServletResponse 对象返回给HTTP服务器,HTTP服务器把响应发给客户端二、组件1. 连接器组件Coyote客户端通过Coyote与服务器建设连贯,发送并响应申请 Coyote 封装底层网络通信(Socket申请及响应解决)Coyote 使 Catalina容器(容器组件)与具体的申请及I/O操作解耦Coyote 将Socket 输出封装Request对象,容器解决后,Catelina通过Response对象将后果写入输入流Coyote 去负责具体应用层协定和传输层io相干内容 ### 2. Servlet 容器 Catalina Tomcat由一系列可配置(server.xml)的组件形成的web容器,Catalina是它的Servlet容器。某种方面说,Tomcat就是一个Servlet容器,Catalina是它的外围组件。 三、外围配置配置文件server.xml <?xml version="1.0" encoding="UTF-8"?><!-- 根元素,定义一个Server实例,本人标签:Listener、GlobalNamingResources、Service--><!-- 监听8005,状态为敞开状态 这里不须要改--><Server port="8005" shutdown="SHUTDOWN"> <!-- 定义监听器 以下都无需更改--> <!-- 打印JVM、操作系统相干日志 无需更改 --> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <!-- 加载销毁Apr 无需更改 --> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <!-- 防止JRE内存溢出 --> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <!-- 加载和进行全局命名服务 --> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <!-- 在Context进行时重建 Executor 池中的线程,防止 ThreadLocal 相干的内存透露 --> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <!-- 定义全局JNDI资源 个别无需批改--> <GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <!-- 定义service服务容器,一个server能够有很多service --> <Service name="Catalina"> <!--The connectors can use a shared executor, you can define one or more named thread pools--> <!-- 配置Service共享线程池 --> <!-- 默认状况下,Service 并未增加共享线程池配置。 如果咱们想增加一个线程池, 能够在 <Service> 下增加如下配置: name: 线程池名称,用于 Connector中指定 namePrefix: 所创立的每个线程的名称前缀,一个独自的线程名称为 namePrefix+threadNumber maxThreads: 池中最大线程数 minSpareThreads: 沉闷线程数,也就是外围池线程数,这些线程不会被销毁,会始终存在 maxIdleTime: 线程闲暇工夫,超过该工夫后,闲暇线程会被销毁,默认值为6000(1分钟),单位毫秒 maxQueueSize: 在被执行前最大线程排队数目,默认为Int的最大值,也就是狭义的有限。除非非凡状况,这个值 不须要更改,否则会有申请不会被解决的状况产生 prestartminSpareThreads: 启动线程池时是否启动 minSpareThreads局部线程。默认值为false,即不启动 threadPriority: 线程池中线程优先级,默认值为5,值从1到10 className: 线程池实现类,未指定状况下,默认实现类为org.apache.catalina.core.StandardThreadExecutor。如果想应用自定义线程池首先须要实现 org.apache.catalina.Executor接口 --> <Executor name="commonThreadPool" namePrefix="thread-exec-" maxThreads="200" minSpareThreads="100" maxIdleTime="60000" maxQueueSize="Integer.MAX_VALUE" prestartminSpareThreads="false" threadPriority="5" className="org.apache.catalina.core.StandardThreadExecutor" /> <!-- 一个Service容器能够有多个连接器,每个连贯启动一个线程 --> <!-- port: 端口号,Connector 用于创立服务端Socket 并进行监听,以期待客户端申请链接。如果该属性设置为0,Tomcat将会随机抉择一个可用的端口号给以后Connector应用 protocol: 以后Connector 反对的拜访协定。默认为 HTTP/1.1,并采纳主动切换机制抉择一个基于 JAVA NIO的链接器或者基于本地APR的链接器依据本地是否含有Tomcat的本地库断定) connectionTimeOut: Connector 接管链接后的期待超时工夫, 单位为毫秒。 -1 示意不超时。 redirectPort: 以后Connector不反对SSL申请,接管到了一个申请,并且也合乎security-constraint束缚,须要SSL传输,Catalina主动将申请重定向到指定的端口。 executor: 指定共享线程池的名称, 也能够通过maxThreads、minSpareThreads 等属性配置外部线程池。 URIEncoding: 用于指定编码URI的字符编码, Tomcat8.x版本默认的编码为 UTF-8 , Tomcat7.x版本默认为ISO-8859-1 --> <!--org.apache.coyote.http11.Http11NioProtocol , 非阻塞式 Java NIO 链接器--> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> <!-- 应用共享线程池,不明确线程池就会有本人保护的线程池,造成资源节约 --> <!-- <Connector port="8080" protocol="HTTP/1.1" executor="commonThreadPool" maxThreads="1000" minSpareThreads="100" acceptCount="1000" maxConnections="1000" connectionTimeout="20000" compression="on" compressionMinSize="2048" disableUploadTimeout="true" redirectPort="8443" URIEncoding="UTF-8" /> --> <!-- A "Connector" using the shared thread pool--> <!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> --> <!-- Servlet引擎 --> <!-- name: 用于指定Engine的名称, 默认为Catalina defaultHost: 默认应用的虚拟主机名称,当客户端申请指向下边配置Host的主机有效时,将交由默认的虚拟主机解决,默认为localhost --> <Engine name="Catalina" defaultHost="localhost"> <!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --> <!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> --> <!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <!-- Host标签用于配置虚拟主机 --> <!-- 默认解决 ,appbase是相对路径,unpackWARs解压war包,autoDeploy主动部署--> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- 拜访申请日志的 阀 ,寄存门路为相对路径--> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /> </Host> <!-- 监听 www.abc.com:8080 --> <Host name="www.abc.com" appBase="webapps1" unpackWARs="true" autoDeploy="true"> <!-- docBase:Web利用目录或者War包的部署门路。能够是绝对路径,也能够是绝对于 Host appBase的 相对路径。 path:Web利用的Context 门路。如果咱们Host名为localhost, 则该web利用拜访的根门路为: http://localhost:8080/web_demo。 --> <Context docBase="/Users/yingdian/web_demo" path="/web3"></Context> <!-- 拜访申请日志的 阀 ,寄存门路为相对路径--> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /> </Host> </Engine> </Service></Server>

June 25, 2021 · 2 min · jiezi

关于tomcat:解决-无法启动组件StandardEngineCatalinaStandardHostlocalhost

前言最近在搭建环境,发现每个工程启动基本上都会报这个谬误 看了一下 大略意思就是指定了一个filter 而后呢并没有找到这个filter的类信息 不影响工程的失常运行,改bug之余明天跟进了一下 终于解决了: 首先找到/usr/local/oneaccess/bim/tomcat/webapps/manager/WEB-INF/(请对号入座这是我线上的地址) 找到web.xml文件 编辑之: 搜寻报错信息中提醒的filter的名称 csrf 发现csrf对应的filter信息被正文了 间接把正文的内容放开或者把这两段信息都删掉即可 相干材料web.xml文件详解

June 9, 2021 · 1 min · jiezi

关于tomcat:centos7中tomcat的systemctl启动方式启动停止重启开机启动

指标:在centos7中配置tomcat的systemctl启动形式(启动、进行、重启、开机启动) 剖析:1.解压文件;2.挪动解压文件至 /usr/local/下,并改名tomcat;3.配置startup.sh、shutdown.sh、catalina.sh 环境;4.配置启动脚本tomcat.service ;5.设置脚本开机启动;6.测试。 操作流程:源码装置 #解压源码tar zxvf apache-tomcat-8.5.23.tar.gz #文件到挪动/usr/local/下,并改名tomcatmv apache-tomcat-8.5.23 /usr/local/tomcat配置文件配置:将以下内容增加到startup.sh、shutdown.sh、catalina.sh 当中 留神批改你的java门路 export JAVA_HOME=/usr/local/java #jdk门路export TOMCAT_HOME=/usr/local/tomcat #tomcat门路export CATALINA_HOME=/usr/local/tomcat #tomcat门路export CLASS_PATH=$JAVA_HOME/bin/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tool.jarexport PATH=$PATH:/usr/local/java/bin:/usr/local/tomcat/bin开机启动设置1.进入/lib/systemd/systemcd /lib/systemd/system2.创立tomcat.servicevi /lib/systemd/system/tomcat.service3.tomcat.service中增加配置信息 [Unit]Description=tomcatAfter=network.target [Service]Type=oneshotExecStart=/usr/local/tomcat/bin/startup.shExecStop=/usr/local/tomcat/bin/shutdown.shExecReload=/bin/kill -s HUP $MAINPIDRemainAfterExit=yes [Install]WantedBy=multi-user.target保留 退出 systemctl enable tomcat.service (设置开机自启动)4.操作命令 systemctl status tomcat.service (查看服务以后状态)systemctl start tomcat.service (启动tomcat服务)systemctl stop tomcat.service (进行tomcat服务)systemctl restart tomcat.service (重新启动服务)systemctl reload tomcat.service (从新加载配置)systemctl enable tomcat.service (设置开机自启动)systemctl disable tomcat.service (进行开机自启动)systemctl list-units --type=service (查看所有已启动的服务)例:查看服务启动状态(已启动状态) 例:Tomcat 拜访页面测试地址:http://192.168.157.130:8080/ 5.参考命令 systemctl start *.service #启动服务systemctl stop *.service #进行服务systemctl restart *.service #重启服务systemctl reload *.service #从新加载服务配置文件systemctl status *.service #查问服务运行状态systemctl enable *.service #开机运行服务systemctl disable *.service #勾销开机运行systemctl --failed #显示启动失败的服务systemctl is-enabled servicename.service #查问服务是否开机启动

May 26, 2021 · 1 min · jiezi

关于tomcat:Tomcat安装配置

Tomcat下载Tomcat下载地址 个别不下载新进去的版本,下载较为稳固的版本比拟好,我这里下载Tomcat 9 点击右边download下的tomcat 9进入下载页面 Mirros能够更换镜像源,如果太慢能够换一个,然而文件自身不大,就10多MCore 中抉择相应的版本即可 ,64为windows就抉择 64bit-Windows zip即可,tar为linux版本Source Code 上面还有源码文件另外,download上面还有archive(文档),外面有各个版本的目录,进入bin目录下载即可 而后下载解压到指定目录即可 Tomcat配置tomcat 由java编写,须要jvm运行,所以须要配置JDK,如果不配置好上面的环境,会闪退 新建零碎变量JAVA_HOME --------> 你的jdk装置目录(如:D:\DevEvironment\openjdk-11.0.2) 点击path,新建输出:%JAVA_HOME%/bin 开启:而后进入tomcat 9解压目录下的bin目录,点击startup.bat批处理文件,呈现启动工夫,即可开启tomcat 进入浏览器输出:http://localhost:8080 或 http://127.0.0.1:8080进行关上... 敞开: 间接点击控制台敞开即可,或者进入bin目录,点击shutdown.dat 另外控制台乱码状况 点击控制台标题栏、属性,能够看到是GBK编码,而tomcat控制台为UTF-8编码,所以会呈现乱码 你能够抉择去注册表更改控制台的编码,也能够去改tomcat的编码方式 这我采纳更改tomcat编码: 进入tomcat装置目录/conf/logging.properties,用记事本关上,ctrl + f 搜寻java.util.logging.ConsoleHandler.encoding = UTF-8 ,更改为GBK编码即可,再重新启动tomcat Tomcat 目录介绍bin 次要寄存二进制可执行文件和脚本。conf 次要寄存各种配置文件。lib 次要用来寄存Tomcat运行须要加载的jar包。logs 次要寄存Tomcat在运行过程中产生的日志文件。temp 次要寄存Tomcat在运行过程中产生的临时文件。webapps 次要寄存应用程序,当Tomcat启动时会去加载该目录下的应用程序。work 次要寄存tomcat在运行时的编译后文件,例如JSP编译后的文件。-------后续再更新-----

May 5, 2021 · 1 min · jiezi

关于tomcat:Tomcat源码学习第4篇-Servlet请求分析

前段时间家里有事忙,停更了好长一段时间,这里跟期待更新的小伙伴们说一声道歉,没能提前阐明一下,让小伙伴们等了这么久,真的不好意思!后面说完了Tomcat的初始化和启动步骤,那么接下来就要进入重头戏了!在本篇文章中,我会跟后面一样,通过图文的形式来带着小伙伴们理解一个 Servlet是如何被tomcat解决的,具体的解决链路都有哪些。 一、申请剖析在《Tomcat源码学习第2篇》中备注了各个组件的阐明。 当一个servlet申请到来的时候,首先通过的是connector组件,它是用来接管申请的。 该组件接管到申请之后,会把相干申请进行封装,而后传递到engine组件中。 紧跟着,engine组件会锁定对应的host,context以及wrapper,一层层的传递上来,找到最终解决申请的servlet实例。 二、深刻摸索不晓得大家还有没有印象,在后面的文章中,咱们在NioEndpoint类中,启动Accepter线程的入口处上方还有着一个线程组在启动运行,然而却没有解说该线程是用来干嘛的~ NioEndpoint.startInternal() 点击跳转到该类过去,咱们能够看到他实现了Runnable接口,那么咱们间接查看他的run()办法,看看它的运行逻辑。 Poller.run() 通过正文咱们能够晓得,该线程次要用于轮询已连贯的套接字,查看是否触发了事件,并在事件产生时将关联的套接字移交给对应的处理器。在源码中咱们能够看到keyCount变量记录着待处理申请数,提供给前面做相应判断。 持续往下走,通过keyCount判断是否有申请须要进行解决,需要的话则通过selector.selectedKeys()拿到须要被解决的channel汇合,进行循环解决。在while循环中咱们看到,所有就绪的通道都调用的是processKey(sk, socketWrapper)办法进行解决。 点击跳转过来该办法,在这里能够看到他对该sk做了读写判断,既然是申请进来,那必定是做读操作,咱们先进读相干的办法看一下。 NioEndpoint.processKey() 进来之后咱们能够看到它首先在缓存池中尝试去获取一个解决线程,当缓存池中没有线程时,就创立一个新的线程,如果有的话就间接应用。 AbstractEndpoint.processSocket() 既然是线程了,那么咱们就关怀线程的外围办法即可。点击SocketProcessorBase跳转查看run()办法。 SocketProcessorBase.run() 在doRun()处打上断点,单击下一步,跳转到NioEndpoint.doRun()办法中。Poller线程移交到这边的线程进行解决,在该线程中须要失去以后的socket,做进一步的解决。 进入该办法之后,咱们能够看到它首先对wrapper进行判断,不为空再取出socket,而后尝试着在connections中去获取对应的processor,如果获取不到,再尝试获取曾经解决过连贯,然而尚未销毁的processor中去获取,还获取不到才进行创立。这样能够防止频繁的创立和销毁对象。 AbstractProtocol.process() 失去processor之后,调用process办法对报文进行解析。 进入该办法之后,咱们能够看到这外面是对socketEvent的状态进行判断,咱们以后申请次要是读状态,在此处打上断点,跳到该办法进来看一下。 AbstractProcessorLight.process() 这里咱们能够看到是进入到了 http11类中,在该类外面对报文进行解析,封装原生的request和response对象。这里的response因为咱们还没有到返回的步骤,所以只是做个初步的参数设置。后续要传入Adapter进行下一步操作。 Http11Processor.service() 在这里对原生的request和response进行转换,失去HttpServletRequest和HttpServletResponse。而后依据申请信息找到可能解决以后申请的host,context,wrapper。 CoyoteAdapter.service() 在这办法能够看到它会通过getMapper()办法去匹配可能解决以后申请的 host,context,wrapper。到这里可能有的小伙伴会奇怪,为什么是从mapper中去匹配呢?这个问题留给你们去摸索一下,等下篇再给你们解答。 CoyoteAdapter.postParseRequest() 上一办法中,通过connector获取service之后再获得对应的mapper,可是进来之后却没有看到对该mapper对象的构建,那该对象是哪里来的呢? Mapper.map() 不晓得大家还记不记得在第二篇中,在StandardService类中initInternal()和startInternal()办法中有mapperListener办法的初始化和启动。 在该办法中查找到对应的host, context, wrapper。 Mapper.internalMap() 回到CoyoteAdapter.postParseRequest(),通过Evaluste咱们能够看到以后申请对应的host, context, wrapper以及实例的映射均已找到。 接下来要做的就是依据链路组件进行一级级的调用,直至最初取出servlet执行。 CoyoteAdapter.service() 先失去host,在通过host持续调用下一级组件 StandardEngineValve.invoke() AbstractAccessLogValve.invoke() ErrorReportValve.invoke() 这里拿到context,持续invoke()。 StandardHostValve.invoke() AuthenticatorBase.invoke() StandardContextValve.invoke() 拿到wrapper之后,持续向下执行,从wrapper容器中失去servlet对象。 StandardWrapperValve.invoke() ...

May 4, 2021 · 1 min · jiezi

关于docker:使用-Docker-运行-Tomcat-容器

# 搜寻tomcat镜像docker search tomcat# 拉取tomcat镜像docker pull tomcat# 查看所有镜像docker images# 运行nginx容器,-d 后盾运行容器并打印出容器ID,-p 将容器的8080端口映射到主机的3355端口docker run -d -p 3355:8080 --name tomcat01 tomcat# 进入容器docker exec -it tomcat01 /bin/bash# 进入容器拷贝文件cd /usr/local/tomcat/cp -r webapps.dist/* webapps/exit在浏览器中拜访并显示 tomcat 的默认页: http://localhost:3355查看所有运行中的容器: docker ps通过容器名称进行容器: docker container stop tomcat01通过容器名称移除容器: docker container rm tomcat01

April 12, 2021 · 1 min · jiezi

关于tomcat:安装配置Tomcat

下载,装置配置Tomcat1.下载 下载地址:http://tomcat.apache.org/依据本人的电脑抉择32位或者64位能够下载免安装版(zip),或者安装版(.exe)2.装置 如果下载免安装版,下载后间接解压即可启动:找到bin目录下的startup.bat,点击启动tomcat敞开:找到bin目录下的shutdown.bat,点击敞开tomcat3.配置 配置环境变量1.右下角搜寻环境变量2.点击环境变量 3.在零碎变量中增加一条新的变量变量名为TOMCAT_HOME变量值为Tomcat装置目录 4.在path变量中增加新的值值为%TOMCAT_HOME%\bin4.测试是否装置胜利 1.启动Tomcat2.关上浏览器键入 http://localhost:8080 进入如下页面则示意装置胜利。注:如果启动tomcat时呈现闪退 1.在命令行下启动Tomcat,会显示失败起因,个别是没有配置JAVA_HOME和JRE_HOME两个环境变量cd 是切换文件夹 2.配置JAVA_HOME和JRE_HOME (1).首先在零碎变量中增加JAVA_HOME 变量名为JAVA_HOME,变量值为jdk的装置门路 命令行下输出java -version能够查看是否装置jdk 输出java -verbose能够查看jre装置门路 默认门路为 C:\Program Files\Java\jre1.8.0_241 (2).增加JRE_HOME

April 9, 2021 · 1 min · jiezi

关于tomcat:IDEA里Tomcat-Console日志中文乱码问题解决

IDEA内Tomcat中文乱码Ctrl+Alt+S关上设置,而后Editor->File Encodings,将圈出的都改成UTF-8 IDEA菜单->help->Edit Custom VM Options,最初一行增加-Dfile.encoding=UTF-8 重启Tomcat后失效,发现Console日志外面都是失常的中文了,如果没失效,请重启IDEA,多期待一会,才会失效

March 23, 2021 · 1 min · jiezi

关于centos7:CentOS7安装tomcat

1 查看tomcat状态如果没有tomcat会报错。 systemctl status tomcat.service//或者 systemctl status tomcat2 装置tomcat腾讯云的镜像没有tomcat,须要手动下载,我选的第二种计划。 yum install tomcat//或者 -y代表所有的询问都选yyum -y install tomcattomcat的装置目录在 /usr/share/tomcat,能够cd进去查看是否有文件。 3 启动tomcatsystemctl start tomcat.service//或者 systemctl start tomcat此时,cd到tomcat 的 webapps 目录,用ls查看目录之后会发现是空的,这证实须要装置tomcat的治理界面。 4 装置tomcat的治理界面yum install tomcat-webapps tomcat-admin-webapps5 增加用户回到 tomcat 装置目录(/usr/share/tomcat),进入 conf 目录,关上 tomcat-users.xml 文件,在 <tomcat-users> 标签下,增加如下配置:(username和password最好简单!!!) <role rolename="manager-gui"/><user username="root" password="root" roles="manager-gui"/>6 重启服务。systemctl restart tomcat.service//或者 systemctl restart tomcat7 tomcat其余重要命令进行 tomcat 服务 systemctl stop tomcat.service//或者 systemctl stop tomcat开机自启动 tomcat systemctl enable tomcat

March 22, 2021 · 1 min · jiezi

关于tomcat:tomcat8-日志路径乱码自动分割-问题解决

日志乱码vim catalina.sh在如图所示处 增加 -Dfile.encoding=UTF-8JAVA_OPTS="$JAVA_OPTS -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dfile.encoding=UTF-8" 日志门路vim catalina.sh在如图所示批改 CATALINA_OUT=if [ -z "$CATALINA_OUT" ] ; then #CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out CATALINA_OUT=/data/WEBLOG/uat-ecommerce-app/catalina.outfi日志主动宰割[root@tomcat-uata_20 conf]# vim logging.properties1catalina.org.apache.juli.AsyncFileHandler.level = FINE1catalina.org.apache.juli.AsyncFileHandler.directory = /data/WEBLOG/uat-ecommerce-app1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.1catalina.org.apache.juli.AsyncFileHandler.encoding = UTF-82localhost.org.apache.juli.AsyncFileHandler.level = FINE2localhost.org.apache.juli.AsyncFileHandler.directory = /data/WEBLOG/uat-ecommerce-app2localhost.org.apache.juli.AsyncFileHandler.prefix = localhost.2localhost.org.apache.juli.AsyncFileHandler.encoding = UTF-83manager.org.apache.juli.AsyncFileHandler.level = FINE3manager.org.apache.juli.AsyncFileHandler.directory = /data/WEBLOG/uat-ecommerce-app3manager.org.apache.juli.AsyncFileHandler.prefix = manager.3manager.org.apache.juli.AsyncFileHandler.encoding = UTF-84host-manager.org.apache.juli.AsyncFileHandler.level = FINE4host-manager.org.apache.juli.AsyncFileHandler.directory = /data/WEBLOG/uat-ecommerce-app4host-manager.org.apache.juli.AsyncFileHandler.prefix = host-manager.4host-manager.org.apache.juli.AsyncFileHandler.encoding = UTF-8java.util.logging.ConsoleHandler.level = FINEjava.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatterjava.util.logging.ConsoleHandler.encoding = UTF-8

March 16, 2021 · 1 min · jiezi

关于tomcat:DEBUG系列Windows上Tomcat日志乱码

1. 产生乱码起因Windows上idea+tomcat乱码问题的根本原因,编码字符集不一样。乱码日志产生过程:tomcat依照某种字符集编码产生日志文件,给IDEA,依照某种字符集解析,展现在本人的控制台里;windows上的IDEA,在本人的控制台展现日志默认应用操作系统GBK的编码格局。Tomcat的各种日志文件绝大多数默认是UTF-8;将他们的编码格局设置对立即可,GBK是国家标准,UTF-8是国内编码。对立设置成UTF-8通用性更好。2. 解决方案设置IDEA控制台显示日志时所用的字符集 Help->Edit Costum Vm Option ->增加一行 -Dfile.encoding=UTF-8  重启失效。/tomcat/conf/logging.properties,该文件配置tomcat日志编码格局。# 对应IDEA 中Srever中的日志编码格局,其余的各自对应。java.util.logging.ConsoleHandler.encoding = UTF-8

March 9, 2021 · 1 min · jiezi

关于tomcat:Docker安装Tomcat

1、搜寻镜像 docker search tomcat2、下载镜像 docker pull tomcat3、查看镜像 docker images tomcat4、运行镜像 docker run -d -p 8080:8080 --name tomcat tomcat:latest5、拷贝镜像到须要映射的目录 docker cp tomcat:/usr/local/tomcat/conf /usr/app/tomcat/confdocker cp tomcat:/usr/local/tomcat/logs /usr/app/tomcat/logs6、应用映射的目录运行tomcat docker run -d -p 8080:8080 --name tomcat -v /usr/app/tomcat/webapps:/usr/local/tomcat/webapps -v /usr/app/tomcat/conf:/usr/local/tomcat/conf -v /usr/app/tomcat/logs:/usr/local/tomcat/logs --restart=always tomcat:latest

February 28, 2021 · 1 min · jiezi

关于tomcat:IDEATomcat下http状态404的原因

从php转型java后刚接触tomcat就遇到了这个问题 始终认为是tomcat配置呈现了问题重复调试 重装了之后也没能解决 然而黑框中startup后能够在浏览器失常拜访 最初苦苦百度排查出居然是idea自带了个莫名其妙的欢送页面一样的货色 他还找不到了!!!

February 12, 2021 · 1 min · jiezi

关于tomcat:服务器Tomcat你会安装了吗

Tomcat 是一个合乎 JavaEE WEB 规范的最小的 WEB 容器,所有的 JSP 程序肯定要有 WEB 容器的反对能力运行,而且在给定的 WEB 容器外面都会反对事务处理操作。 Tomcat 是由 Apache 提供的(www.apache.org),能够用安装版和解压版,安装版能够在服务中呈现一 Tomcat 的服务,免装置没有,开发中应用免安装版。 Tomcat 简略的说就是一个运行 Java 的网络服务器,底层是 Socket 的一个程序,它也是 JSP 和 Servlet 的一个容器。Tomcat 是 Apache 软件基金会(Apache Software Foundation)的 Jakarta 我的项目中的一个外围我的项目,由 Apache、Sun和其余一些公司及集体共同开发而成。 因为有了 Sun 的参加和反对,最新的 Servlet 和 JSP 标准总是能在 Tomcat 中失去体现。因为 Tomcat 技术先进、性能稳固,而且收费,因此深受 Java 爱好者的青睐并失去了局部软件开发商的认可,成为目前比拟风行的 Web 应用服务器。 Tomcat 服务器是一个收费的凋谢源代码的 Web 应用服务器,属于轻量级应用服务器,在中小型零碎和并发拜访用户不是很多的场合下被广泛应用,是开发和调试 JSP 程序的首选。 对于一个初学者来说,能够这样认为,当在一台机器上配置好 Apache 服务器,可利用它响应 HTML(规范通用标记语言下的一个利用)页面的拜访申请。实际上 Tomcat 局部是 Apache 服务器的扩大,但它是独立运行的,所以当你运行 tomcat 时,它实际上作为一个与 Apache 独立的过程独自运行的。 ...

December 14, 2020 · 1 min · jiezi

关于tomcat:使用Tomcat-Native提升Tomcat-IO效率

简介IO有很多种,从最开始的Block IO,到nonblocking IO,再到IO多路复用和异步IO,一步一步的将IO的性能晋升做到极致。 明天咱们要介绍一下怎么应用Tomcat Native来晋升Tomcat IO的效率。 Tomcat的连贯形式Tomcat中应用连接器来解决与内部客户端的通信。Connecter次要用来承受内部客户端的申请,并转交给解决引擎解决。 在Tomcat中有两种Connector。一种是 HTTP connector, 一种是AJP connector。 HTTP connector大家应该很好了解,它也是tomcat默认应用的连接器。 还有一个连接器叫做AJP,AJP次要是用来和web服务器进行通信用的,因为AJP协定的速度要比HTTP的快,所以AJP除了用来和其余webserver进行通信之外,还能够通过AJP来构建tomcat集群。 这两种形式都反对4中协定,别离是BIO,NIO,NIO2和APR。 #以下四种Connector实现都是间接解决来自客户端Http申请org.apache.coyote.http11.Http11Protocol : 反对HTTP/1.1 协定的连接器。org.apache.coyote.http11.Http11NioProtocol : 反对HTTP/1.1 协定+New IO的连接器。org.apache.coyote.http11.Http11Nio2Protocol : 反对HTTP/1.1 协定+New IO2的连接器。org.apache.coyote.http11.Http11AprProtocol : 应用APR(Apache portable runtime)技术的连接器,利用Native#以下四种实现办法则是与web server打交道org.apache.coyote.ajp.AjpProtocol:应用AJP协定的连接器,实现与web server(如Apache httpd)之间的通信org.apache.coyote.ajp.AjpNioProtocol:SJP协定+ New IOorg.apache.coyote.ajp.AjpNio2Protocol:SJP协定+ New IO2org.apache.coyote.ajp.AjpAprProtocol:AJP + APR讲下他们的区别,BIO就是block IO是最最根底的IO形式, 咱们通过这样来配置: <Connector port=”8080” protocol=”HTTP/1.1” maxThreads=”150” connectionTimeout=”20000” redirectPort=”8443” />Tomcat7以下版本在默认状况下是以bio模式运行的。自Tomcat 8.5 版本开始,Tomcat就移除了对BIO的反对。 New IO是基于java.nio包及其子包的一种IO形式。能提供非阻塞IO形式,比传统的BIO领有与更加高效的运行效率。 咱们这样配置New IO: <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"connectionTimeout="20000"redirectPort="8443" />New IO和New IO2有什么区别呢? New IO2是tomcat8中引入的IO形式,咱们能够这样配置: <Connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol"connectionTimeout="20000"redirectPort="8443" />apr这种形式就高级了,这个是咱们明天要解说的tomcat native的次要作用。 APR和Tomcat Nativeapr的全称是Apache Portable Runtime,它是一个高度可移植的库,它是Apache HTTP Server 2.x的外围。 APR有许多用处,包含拜访高级IO性能(例如sendfile,epoll和OpenSSL),操作系统级别的性能(生成随机数,零碎状态等)和本机过程解决(共享内存,NT管道和Unix套接字)。 ...

December 11, 2020 · 1 min · jiezi

关于tomcat:初学Tomcat遇到的一些问题

tomcat装置配置首先须要配置JAVA_HOME和JRE_HOME的环境变量,地址就是java根目录门路,如F:\Java在tomcat官网下载免安装版的压缩包。解压后dos窗口进入bin文件下,而后跑去服务startup如之后就会开启一个服务窗口能够拜访Tomcat根目录的webapps文件夹下的资源文件,首先在webapps文件夹下新建一个文件夹,名为Test,在Test文件夹下放入一个1.jpg的图片。浏览器拜访http://localhost:8080/Test/1.jpg,,就能够看到这张图片了。个别默认端口号时8080敞开服务就在dos窗口输出shutdown,服务窗口主动敞开。bin目录次要是用来寄存tomcat的命令,次要有两大类,一类是以.sh结尾的(linux命令),另一类是以.bat结尾的(windows命令)。 tomcat目录构造(参考网上)bin目录次要是用来批改环境变量,设置JDK门路、tomcat门路startup 用来启动tomcatshutdown 用来敞开tomcat批改catalina能够设置tomcat的内存 conf目录次要是用来寄存tomcat的一些配置文件server.xml能够设置端口号、设置域名或IP、默认加载的我的项目、申请编码web.xml能够设置tomcat反对的文件类型context.xml能够用来配置数据源之类的tomcat-users.xml用来配置管理tomcat的用户与权限在Catalina目录下能够设置默认加载的我的项目lib目录次要用来寄存tomcat运行须要加载的jar包例如,像连贯数据库的jdbc的包咱们能够退出到lib目录中来。logs目录用来寄存tomcat在运行过程中产生的日志文件在windows环境中,控制台的输入日志在catalina.xxxx-xx-xx.log文件中在linux环境中,控制台的输入日志在catalina.out文件中temp目录用户寄存tomcat在运行过程中产生的临时文件 webapps目录用来寄存应用程序当tomcat启动时会去加载webapps目录下的应用程序。能够以文件夹、war包、jar包的模式公布利用。当然,你也能够把应用程序搁置在磁盘的任意地位,在配置文件中映射好就行。work目录用来寄存tomcat在运行时的编译后文件例如JSP编译后的文件。清空work目录,而后重启tomcat,能够达到革除缓存的作用。 idea配置tomcat导航栏run->配置编辑增加新配置->抉择Tomcat Server->local写好名称,这里两个端口号主动生成,确认留神一旦端口号被占用,服务跑不起来会出错 之后点击idea左下的绿色加号,run服务就跑起来了 tomcat服务run报错port out of range:-1解决办法:批改tomcat根目录的的conf文件夹下的server.xml,将<Server port="-1" shutdown="SHUTDOWN">改成<Server port="1-65535之间的任意一个整数" shutdown="SHUTDOWN">, tomcat乱码这就很烦。。。。 解决办法:找到Tomcat根目录的conf文件夹下的logging.properties文件关上后在开端加上 java.util.logging.ConsoleHandler.encoding = GBK~~~~ok,胜利了!

November 20, 2020 · 1 min · jiezi

关于tomcat:数据库连接池连接耗尽导致tomcat请求无响应呈现出假死状态

最艰难的事件就是意识本人!集体网站 ,欢送拜访! 前言:最近,测试部门的共事找到我,说他们测试时,没一会就发现服务接口申请始终无响应,Tomcat跟死掉了一样,也没有返回任何的谬误响应,说让我连忙排查下;听完后,我霎时激灵了下,妹的,最近老是出问题,领导都要给我开批评大会了。哈哈,开玩笑的,像我这么英俊的人,领导怎么会忍心批评我呢,哼,我把这个问题马上解决掉,都不会让领导晓得的!简略说下程序部署状况:tomcat + oracle 排查过程:排查时,能够应用命令进行排查,也能够应用可视化监控工具;例如应用应用JDK自带的 jvisualvm.exe 监控工具。命令排查过程:1、申请服务无响应,首先看看tomcat是否是真的挂掉了:命令: ps -ef | grep tomcat 通过下面的命令查看tomcat运行着;执行后果如下: 留神: 如果此服务器中运行着多个tomcat,须要查看下图中画框的中央运行的tomcat地址是否正确; 通过命令查看发现,tomcat失常运行着,那么这就是处于假死状态,上面接着排查。 2、查看http申请是否达到了tomcat:通过查看 tomcat 的 logs 目录下的 localhost_access_log 日志文件中 申请记录; 命令: tail -100f localhost_access_log 通过下面的命令查看实时的日志,执行完下面的查看日志的命令后,而后再次申请下程序,在日志中并没有发现申请记录,阐明tomcat处于一种假死状态,上面接着排查。 3、查看tomcat的JVM的GC状况:查看GC状况,是否因为频繁的GC,长时间的GC,导致程序呈现长时间的卡顿,最终导致申请来不及解决,进入队列中进行期待,调用方长时间得不到响应,造成tomcat假死状态; 命令:jstat -gc pid time count 例如: jstat -gc 71129 1000 5 监控 71129 这个过程JVM的GC状况,每隔1000ms 输入一次,共输入5次; 命令执行后果参数解析: 通过下面命令查看GC状况,发现垃圾回收也不频繁,并且进行GC的工夫也不长,应该不是GC的起因。 4、查看tomcat的JVM的堆状况:查看堆内存的状况,是否存在堆内存溢出 导致tomcat假死,无奈为新申请调配堆内存资源; 命令 : jmap -heap pid 例子: jmap -heap 71129 71129是正在运行tomcat的过程号 ; 通过命令执行后果得悉,堆内存中可应用内存还很大,不会呈现内存溢出的问题,所以也不是堆内存过小导致的tomcat假死。 5、查看tomcat的 JVM线程状况:①、应用 jstack 命令导出以后JVM的线程dump快照,而后看看dump中线程都在干什么? ...

October 18, 2020 · 2 min · jiezi

关于tomcat:Tomcat的下载和配置

September 21, 2020 · 0 min · jiezi

关于tomcat:tomcat的常规优化措施

1、调整jvm启动参数 JAVA_OPT="-server -Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=512M XX:MaxMetaspaceSize=1024M -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:+DisableExplicitGC -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError" 2、批改server.xml a.批改应用连接池形式 b.将默认的bio模式,批改成反对NIO的类型 批改办法: 将“HTTP/1.1”改为“org.apache.coyote.http11.Http11Nio2Protocol” c.tomcat日志级别将DEBUG改为INFO(tomcat日志级别没有ERROR) d.批改war包中的:/webapps/getway-server/WEB-INF/classes/logback.xml 日志级别为ERROR 补充:也可将运行形式改为APR模式,是在Tomcat上运行高并发利用的首选模式,能进一步提高性能,从操作系统层面解决异步的IO问题,对动态文件的解决能力也大幅提高,但配置较繁琐 批改运行模式为apr的具体方法(所需的文件包详见tomcat-apr.zip) 装置依赖库yum -y install gcc gcc-c++ libtool* autoconf automake expat-devel perl perl-devel 2、装置apr-1.6.5 [root@APR apr-1.6.5]# vim configure 默认值: 在第30392行 RM='$RM' 批改为: 在第30392行 RM='$RM -f' [root@APR apr-1.6.5]# ./configure --prefix=/usr/local/apr && make && make install 3、装置apr-iconv ./configure --prefix=/usr/local/apr-iconv --with-apr=/usr/local/apr && make && make install ...

September 17, 2020 · 1 min · jiezi

关于tomcat:tomcat通过添加日志文件排查启动错误

问题启动报错 java.lang.NoClassDefFoundError: io/netty/util/concurrent/DefaultPromise$2 at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:589) at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:397) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:155) at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) at java.lang.Thread.run(Unknown Source)这个不是真正的谬误,真正的谬误是其余谬误。因为日志不全,所以看不到,解决办法?增加日志文件。具体方法:https://juejin.im/post/686596... 真正的谬误 INFO: No Spring WebApplicationInitializer types detected on classpathSep 10, 2020 3:00:20 PM org.apache.catalina.core.StandardContext listenerStartSEVERE: Exception sending context initialized event to listener instance of class kalvan.log.logback.web.LogbackConfigListenerjava.lang.ClassCastException: org.slf4j.impl.Log4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext //转换异样 at kalvan.log.logback.web.LogbackConfigListener.contextInitialized(LogbackConfigListener.java:103) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4994) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5492) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649) at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1081) at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1877) at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)Sep 10, 2020 3:00:20 PM org.apache.catalina.core.ApplicationContext logSLF4J: Class path contains multiple SLF4J bindings. //这里才是真正的谬误起因,即同一个类,有多个jar蕴含SLF4J: Found binding in [jar:file:/Users/gongzhihao/IdeaProjects-ys/qrcode/qrcode-server-pool/target/qrcode-server-pool-1.0.0-SNAPSHOT/WEB-INF/lib/activemq-all-5.8.0.jar!/org/slf4j/impl/StaticLoggerBinder.class] //排除这个jarSLF4J: Found binding in [jar:file:/Users/gongzhihao/IdeaProjects-ys/qrcode/qrcode-server-pool/target/qrcode-server-pool-1.0.0-SNAPSHOT/WEB-INF/lib/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class] //只保留这个jarSLF4J: Found binding in [jar:file:/Users/gongzhihao/IdeaProjects-ys/qrcode/qrcode-server-pool/target/qrcode-server-pool-1.0.0-SNAPSHOT/WEB-INF/lib/slf4j-jdk14-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class] //排除这个jarSLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory] //有3个,最终用这个解决办法:排除其余的,只留下一个。 ...

September 10, 2020 · 1 min · jiezi

关于tomcat:tomcatSEVERE-Error-listenerStart和startup-failed-due

问题启动tomcat报错 org.apache.catalina.core.StandardContext startInternal SEVERE: Error listenerStart //报错org.apache.catalina.core.StandardContext startInternal SEVERE: Context [/******] startup failed due to previous errors //报错启动胜利报错 //实际上,在这之前,就曾经失败了启动失败,看到的报错,不是真正的谬误,实质谬误没有打印进去。 起因因为在报错之前,实际上就曾经报错了其余谬误,然而没有打印进去。 解决办法在tomcat部署目录下的我的项目classes目录新建文件 handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler org.apache.juli.FileHandler.level = FINE org.apache.juli.FileHandler.directory = ${catalina.base}/logs org.apache.juli.FileHandler.prefix = error-debug. java.util.logging.ConsoleHandler.level = FINE java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter完了之后,就会看到真正的谬误起因。

August 28, 2020 · 1 min · jiezi

关于tomcat:TomcatHTTP总结1

Tomcat、HTTP总结1服务器概述什么是服务器?服务器分为服务器硬件和服务器软件。在硬件服务器上安装了服务器软件,能力对外提供服务。 服务器硬件:在互联网上具备独立ip地址的计算机服务器软件:就是计算机上的一个程序,比方tomcat服务器软件,mysql服务器软件等。同时服务器软件的分类有很多种:web服务器软件,数据可服务器软件,邮件服务软件等。 什么是web服务器?web服务器是指驻留在互联网上的某种类型的计算机程序,当浏览器向服务器发送申请时,服务器就会接管来自浏览器的申请并解决,并响应浏览器,并会附带一些信息通知浏览器如何查看该文件。web服务器是一个能够向“发送申请的浏览器提供文档”的程序。咱们在拜访网页的时候,就是在拜访他们的服务器。tomcat就是一个web服务器软件。Tomcat的下载、装置、配置tomcat的下载地址:https://tomcat.apache.org/download-80.cgi tomcat的应用须要jdk的反对tomcat5 须要jdk4以上反对tomcat6 须要jdk5以上反对tomcat7 须要jdk6以上反对tomcat8 须要jdk7以上反对解压后须要配置jdk的环境,指定运行的jdk版本最初测试拜访:http://localhost:8080 tomcat批改默认端口:为了不便能够把8080端口设置为80端口,因为80端口能够默认不写。找到解压tomcat的目录中[*tomcat/config/server.xml] <Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443"/>把port批改为80即可。 如果在应用tomcat中遇到server port ... are already ues能够点击tomcat/bin/shutdown.bin 敞开服务器之后重启。 虚拟主机虚拟主机就是tomcat服务器中配置的一个站点,在tomcat服务器中默认配置了一个localhost虚拟主机,这个主机的公布目录是webapps目录;这就是说,Web利用应该放在webapps目录下。webapps目录的构造:webapps --其余目录, --WEB—INF目录: --classes目录:编译后的class文件 --lib目录:用于寄存web利用所以来的jar包 --web.xml文件,用于寄存和web利用相干的一些配置配置WEB利用的主页在web利用的WEB-INF/web.xml文件中退出一下代码:<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <welcome-file-list> <welcome-file>/hello.html</welcome-file> <welcome-file>/hello1.html</welcome-file> <welcome-file>/hello2.html</welcome-file> </welcome-file-list></web-app>把web利用打成war包选中应用程序,压缩成zip之后把zip后缀改成war即可。

August 27, 2020 · 1 min · jiezi

关于tomcat:Tomcat优化你值得拥有

最艰难的事件就是意识本人!集体网站,欢送拜访!前言:Tomcat作为Web利用的服务器,目前绝大多数公司都是用其作为应用服务器的;应用服务器的执行效率会影响零碎执行,这里会讲Tomcat怎么进行配置能进步解决性能;除此之外也必然会提到对应的JVM参数的优化的一些教训。本文为 转载文章 ,原文地址:系统优化怎么做-Tomcat优化 Tomcat的运行模式:运行模式分3种模式: bio:默认的模式,效率比拟低nio:优化时应用的模式apr:对系统配置有一些比拟高的要求确认Tomcat运行模式:查找配置文件 server.xml , 在tomcat下的门路:conf 目录下;Executor 为自定义配置 Tomcat 线程池: <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="1024" minSpareThreads="512" prestartminSpareThreads="true" />要害配置:maxThreads:最大线程数,默认是200minSpareThread:最小沉闷线程数,默认是25maxQueueSize:最大的期待队列个数,超过则申请回绝默认值是Integer.MAX_VALUE ,个别不扭转。在某些紧急状态修复问题须要调整连接器(Connector):Connector是连接器,负责接管客户的申请,以及向客户端回送响应的音讯。所以Connector的优化是重要局部。默认状况下 Tomcat只反对200线程拜访,超过这个数量的连贯将被期待甚至超时放弃,所以咱们须要进步这方面的解决能力。nio 配置:配置文件 server.xml<!-- 运行模式为 nio --><Connector port="14081" protocol="org.apache.coyote.http11.Http11NioProtocol"connectionTimeout="20000"<!-- 连接器中连贯解决 应用下面自定义的 线程池中的线程 -->executor="tomcatThreadPool" URIEncoding="UTF-8" compression="on" useBodyEncodingForURI="true" enableLookups="false" redirectPort="14443" />影响性能的配置:protocol:org.apache.coyote.http11.Http11Protocol - 阻塞式的Java连接器org.apache.coyote.http11.Http11NioProtocol - 不阻塞Java连接器org.apache.coyote.http11.Http11AprProtocol - APR / native 连接器抉择不阻塞Java连接器enableLookups:若是你想request.getRemoteHost()的调用履行,以便返回的短途客户端的理论主机名的DNS查问,则设置为true。设置为false时跳过DNS查找,并返回字符串的IP地址(从而进步性能)。 默认场景下,禁用DNS查找 。compression:设置成on,开启压缩禁用AJP链接器:应用Nginx+tomcat的架构,用不着AJP协定,所以把AJP连接器禁用server.xml正文掉以下配置: <Connector port="8019" protocol="AJP/1.3" redirectPort="8443" />优化 JVM:优化地位:/bin/catalina.sh批改 JAVA_OPTS 参数,这里须要参照 机器配置 ,对JVM进行参数优化 。 JDK1.7:JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms512m -Xmx1024m -XX:NewSize=512m -XX:MaxNewSize=1024M -XX:PermSize=1024m -XX:MaxPermSize=1024m -XX:+DisableExplicitGC"JDK1.8:JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:NewSize=512m -XX:MaxNewSize=1024M -XX:+DisableExplicitGC"留神:1.8 中曾经没有 永恒代了,所以也就没有 没有PermSize、MaxPermSize ;Java8 中将永恒代改为了 元空间 了,JAVA8里对metaspace能够在小范畴主动扩大永生代防止溢出。 ...

August 25, 2020 · 2 min · jiezi

关于tomcat:部署tomcat项目

mac上间接启动tomcat切到目录apache-tomcat-8.5.32/bin执行命令sh startup.sh启动胜利terminal上能够看到Tomcat started. 拜访http://localhost:8080/ bingo 敞开tomcat的时候执行命令sh shutdown.sh 跑一个tomcat目录下的我的项目apache-tomcat-8.5.32/webapps 比方这个目录下有一个manager我的项目,外面提供了一个index.jsp 拜访http://localhost:8080/manager/index.jsp 比方examples中配置的web.xml中有一条 <servlet-mapping> <servlet-name>HelloWorldExample</servlet-name> <url-pattern>/servlets/servlet/HelloWorldExample</url-pattern> </servlet-mapping>拜访http://localhost:8080/examples/servlets/servlet/HelloWorldExample idea 只含一个servlet的tomcat web新建一个java web我的项目new project -> java enterprise -> 抉择tomcat作为application server -> 勾选create project from template 创立一个servlet,在web.xml 中配置相应的servlet配置 配置tomcat (配置过程省略),配置Deployment的时候Application context配置成和我的项目一样的名字 启动tomcat,拜访http://localhost:8080/selfjavawebproj/myservlet selfjavawebproj是web application的名字,myservet须要是在web.xml中配置的门路 tomcat的容器层级tomcat的Servlet容器分为了四层,Engine->Host->Context->Wrapper最内层的Wapper示意一个Servlet,Context示意一个应用程序,一个应用程序中会蕴含多个servlet,Host示意一个站点,一个站点下能够有多个应用程序,Engine示意引擎,用来治理多个站点。在tomcat中的conf/server.xml中,能够配置多个service以我的配置文件为例 <server> <Service name="Catalina"> //一个service下能够有多个connector,一个engine <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/> <Engine name="Catalina" defaultHost="localhost">//蕴含多个host <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> </Engine> </service> <service> </service></server>tomcat实现容器的时候定义了Container,外面定义了parent child这种角色,通过组合模式组装每一层级的容器 public interface Container extends Lifecycle { public void setName(String name); public Container getParent(); public void setParent(Container container); public void addChild(Container child); public void removeChild(Container child); public Container findChild(String name);}http://localhost:8080/selfjavawebproj/myservlet当收回这个申请时,1 首先依据协定和端口号抉择service和Engine,对应下面的配置,只有一个service且连接器反对HTTP1.1,端口8080,所以找到了name为Catalina的service和name为Catalina的Engine2 依据拜访的域名 localhost找到对应的host3 依据url找到context,所以在后面配置的时候Application context配置的也是利用名称,在这里context就是selfjavawebproj4 依据url找到Wrapper,即依据配置的门路在web.xml中找到对应的servlet实现类 ...

August 15, 2020 · 1 min · jiezi

关于tomcat:部署tomcat项目

mac上间接启动tomcat切到目录apache-tomcat-8.5.32/bin执行命令sh startup.sh启动胜利terminal上能够看到Tomcat started. 拜访http://localhost:8080/ bingo 敞开tomcat的时候执行命令sh shutdown.sh 跑一个tomcat目录下的我的项目apache-tomcat-8.5.32/webapps 比方这个目录下有一个manager我的项目,外面提供了一个index.jsp 拜访http://localhost:8080/manager/index.jsp 比方examples中配置的web.xml中有一条 <servlet-mapping> <servlet-name>HelloWorldExample</servlet-name> <url-pattern>/servlets/servlet/HelloWorldExample</url-pattern> </servlet-mapping>拜访http://localhost:8080/examples/servlets/servlet/HelloWorldExample idea 只含一个servlet的tomcat web新建一个java web我的项目new project -> java enterprise -> 抉择tomcat作为application server -> 勾选create project from template 创立一个servlet,在web.xml 中配置相应的servlet配置 配置tomcat (配置过程省略),配置Deployment的时候Application context配置成和我的项目一样的名字 启动tomcat,拜访http://localhost:8080/selfjavawebproj/myservlet selfjavawebproj是web application的名字,myservet须要是在web.xml中配置的门路

August 15, 2020 · 1 min · jiezi

关于tomcat:Tomcat-架构原理解析到架构设计借鉴

Tomcat 倒退这么多年,曾经比拟成熟稳固。在现在『追新求快』的时代,Tomcat 作为 Java Web 开发必备的工具仿佛变成了『相熟的陌生人』,难道说现在就没有必要深刻学习它了么?学习它咱们又有什么播种呢?静下心来,细细品味经典的开源作品 。晋升咱们的「内功」,具体来说就是学习大牛们如何设计、架构一个中间件零碎,并且让这些教训为我所用。 美妙的事物往往是整洁而优雅的。但这并不等于简略,而是要将简单的零碎分解成一个个小模块,并且各个模块的职责划分也要清晰正当。 与此相反的是凌乱无序,比方你看到城中村一堆相互纠缠在一起的电线,可能会感到不适。保护的代码一个类几千行、一个办法好几百行。办法之间互相耦合糅杂在一起,你可能会说 what the f*k! 学习目标把握 Tomcat 架构设计与原理进步内功宏观上看 Tomcat 作为一个 「Http 服务器 + Servlet 容器」,对咱们屏蔽了应用层协定和网络通信细节,给咱们的是规范的 Request 和 Response 对象;对于具体的业务逻辑则作为变动点,交给咱们来实现。咱们应用了SpringMVC 之类的框架,可是却从来不须要思考 TCP 连贯、 Http 协定的数据处理与响应。就是因为 Tomcat 曾经为咱们做好了这些,咱们只须要关注每个申请的具体业务逻辑。 宏观上看 Tomcat 外部也隔离了变动点与不变点,应用了组件化设计,目标就是为了实现「俄罗斯套娃式」的高度定制化(组合模式),而每个组件的生命周期治理又有一些共性的货色,则被提取进去成为接口和抽象类,让具体子类实现变动点,也就是模板办法设计模式。 当今风行的微服务也是这个思路,依照性能将单体利用拆成「微服务」,拆分过程要将共性提取进去,而这些共性就会成为外围的根底服务或者通用库。「中台」思维亦是如此。 设计模式往往就是封装变动的一把利器,正当的使用设计模式能让咱们的代码与零碎设计变得优雅且整洁。 这就是学习优良开源软件能取得的「内功」,从不会过期,其中的设计思维与哲学才是基本之道。从中借鉴设计教训,正当使用设计模式封装变与不变,更能从它们的源码中吸取教训,晋升本人的零碎设计能力。 宏观了解一个申请如何与 Spring 分割起来在工作过程中,咱们对 Java 语法曾经很相熟了,甚至「背」过一些设计模式,用过很多 Web 框架,然而很少有机会将他们用到理论我的项目中,让本人独立设计一个零碎仿佛也是依据需要一个个 Service 实现而已。脑子里仿佛没有一张 Java Web 开发全景图,比方我并不知道浏览器的申请是怎么跟 Spring 中的代码分割起来的。 为了冲破这个瓶颈,为何不站在伟人的肩膀上学习优良的开源零碎,看大牛们是如何思考这些问题。 学习 Tomcat 的原理,我发现 Servlet 技术是 Web 开发的原点,简直所有的 Java Web 框架(比方 Spring)都是基于 Servlet 的封装,Spring 利用自身就是一个 Servlet(DispatchSevlet),而 Tomcat 和 Jetty 这样的 Web 容器,负责加载和运行 Servlet。如图所示: ...

August 2, 2020 · 11 min · jiezi

关于tomcat:Trainee0727第二个任务在办公机启动一个项目part2

需要part2:启动我的项目、批改某些配置文件。 实习一周多问题汇总办公机曾经装置过两个Tomcat服务器,加上这次的就会有三个版本的Tomcat,启动时不出所料地error。如何从零开始通过war包启动一个我的项目?第一次启动Spring Boot我的项目下载工夫长的问题。IDEA创立新我的项目时maven库不是本机指定的目录。问题解决多版本Tomcat问题批改环境变量:变量名本人定,然而不能是CATALINA_HOME。因为这个变量名曾经被之前版本用了。前面在批改.bat文件时本人能辨别变量名就好。Path中也要批改为:%CATALINA_HOME70104%\bin,考究个对应。 而后进入Tomcat门路下bin文件夹,找到startup.bat,右键抉择编辑: 外面所有的CATALINA_HOME改为本人定的名字,比方这里我的CATALINA_HOME70104:还是这个文件夹,找到catalina.bat文件,右键编辑,编辑办法同startup.bat。 上一步防止了Tomcat启动时版本的抵触,上面解决启动时端口的抵触:进入Tomcat门路下conf文件夹,找到server.xml,有三处须要进行端口的批改: 通过war包启动我的项目进入Tomcat目录,找到其中的webapps文件夹,将我的项目的war包以及须要的文件、文件夹之类放入其中,回到Tomcat门路的bin文件夹,双击startup.bat启动我的项目,war文件会被主动解压。 第一次启动Spring Boot我的项目下载工夫长因为maven从外网下载,国内拜访速度慢,能够更改为阿里云镜像。找到本人装置门路下的settings.xml文件(比方我的在D:\Developer\Maven\apache-maven-3.6.3\conf中),编辑:首先在<mirrors></mirrors>节点中增加子节点: <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror>改为而后批改本地仓库地址<localRepository>本人的repository门路</localRepository> 改为IDEA每次创立新我的项目时都须要手动指定本机maven库首先,我是IDEA2020.1版本。找到File➡New Projects Settings➡Settings for New Projects... 批改如下选项为本人的Maven库

July 30, 2020 · 1 min · jiezi

关于tomcat:Trainee0727第二个任务在办公机启动一个项目part1

需要老大写好的我的项目打成war包,须要在我这台办公机启动。 part1:办公机的环境须要配置;part2:启动我的项目、批改某些配置文件;配置环境前提常识war包 war包个别是在进行Web开发时,通常是一个网站Project下的所有源码的汇合,外面蕴含前台HTML/CSS/JS的代码,也蕴含Java的代码。当开发人员在本人的开发机器上调试所有代码并通过后,为了交给测试人员测试和将来进行产品公布,都须要将开发人员的源码打包成War进行公布。 War包能够放在Tomcat下的webapps或者word目录下,随着tomcat服务器的启动,它能够主动被解压 Tomcat服务器 Tomcat服务器是一个收费的凋谢源代码的Web应用服务器,属于轻量级应用服务器,在中小型零碎和并发拜访用户不是很多的场合下被广泛应用,是开发和调试JSP程序的首选,最新的Servlet和JSP标准总是能在Tomcat中失去体现。Redis Redis是一款内存高速缓存数据库,全称为Remote Dictionary Server,即近程字典服务,是一个开源的应用ANSI C语言编写、反对网络、可基于内存亦可长久化的日志型、Key-Value(键值)数据库,并提供多种语言的API。AvtiveMQ 用处:用来解决音讯,也就是解决JMS的。音讯队列在大型电子商务类网站,如京东、淘宝、去哪儿等网站有着深刻的利用,队列的次要作用是打消高并发拜访顶峰,放慢网站的响应速度。 JMS即Java音讯服务(Java Message Service)利用程序接口,是一个Java平台中对于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送音讯,进行异步通信。音讯队列(Message Queue/MQ):在音讯的传输过程中保留音讯的容器。在不应用音讯队列的状况下,用户的申请数据间接写入数据库,高发的状况下,会对数据库造成微小的压力,同时也使得零碎响应提早加剧,但应用队列后,用户的申请发给队列后立刻返回。 例如:购物app不能间接给用户提醒订单提交胜利,app会提醒:“您提交了订单,请期待零碎确认”,再由音讯队列的消费者过程从音讯队列中获取数据,异步写入数据库。因为音讯队列的服务处理速度远快于数据库,因而用户的响应提早可失去无效改善。ElasticSearch 应用JAVA开发、基于Lucene搜索引擎库的全文搜寻工具,通过RESTful API(一种接口设计规范,让接口更易懂)暗藏了Lucene本来的复杂性。实现了日志数据的分布式、实时剖析,并且能够进行搜寻补全与纠错等性能,是ELK最外围的组件。相比MySQL库和表的概念,在ES中把库叫做索引。Tomcat1、下载资源进入官方网站下载页面,下载Tomcat 7.x版本服务器: 下载后解压缩到本人想要的门路中,比方:D:\tomcat\apache-tomcat-7.0.104。 2、设置Tomcat环境变量此电脑 ➡ 属性 ➡ 高级零碎设置 ➡ 环境变量 新建一个环境变量:变量名:TOMCAT_HOME变量值:你的tomcat解压后的目录,如D:\tomcat\apache-tomcat-7.0.104。 在零碎变量中的Path增加:%TOMCAT_HOME%\bin; 3、验证Tomcat环境变量的配置是否胜利运行Tomcat解压目录下的bin\startup.bat,启动Tomcat服务器。 在浏览器拜访http://localhost:8080,如果界面显示如下,则阐明Tomcat的环境变量配置胜利。 Tomcat目录 -> bin文件夹下 startup.bat启动tomcat服务器;shutdown.bat敞开tomcat服务器。插曲:Tomcat命令行窗口中文乱码问题问题剖析: 家喻户晓,绝大多数的中文乱码问题都是因为:字节流解码为字符串时,应用了谬误(和编码所用字符集不统一)的字符集。解决方案:Tomcat目录 -> conf文件夹,找到logging.properties,关上并编辑: 找到如下配置项:java.util.logging.ConsoleHandler.encoding = UTF-8将 UTF-8 批改为 GBK:java.util.logging.ConsoleHandler.encoding = GBK 重启Tomcat: Redis1、下载资源Redis官网:https://redis.io/download,然而这里下载的是Linux版本的Redis,Windows须要在Microsoft凋谢技术小组中下载。 2、装置和配置Redis倡议勾选,性能是增加Redis目录到环境变量PATH中,这样不便零碎自动识别Redis执行文件在哪里。 端口号可放弃默认的6379,并抉择防火墙例外,从而保障内部能够失常拜访Redis服务。 设定最大值为100M。作为试验和学习,100M足够了。 上面进行配置: 因为是采纳msi文件装置的办法,不须要再装置和注册redis到window服务,默认曾经启动。启动服务命令:redis-server.exe  --service-start敞开服务命令:redis-server.exe  --service-stop也能够在windows的利用:服务中开启/敞开。 启动测试: redis-server.exe redis.windows.conf命令: 3、一些设定工作为了平安还须要给redis设置明码,默认装置后是没有明码的: 关上Redis服务配置文件:redis.windows-service.conf。找到requirepass行加上本人的明码即可,如下图所示,批改后须要重启redis服务。 设置明码的办法:删除正文(#),foobared改为本人的明码。 验证明码是否胜利、Redis是否失常工作:首先,设置明码后重启服务。其次,进入redis目录,执行redis-cli,启动客户端程序。而后,输出auth 明码进行验证。最初,通过set、get命令测试性能。 ActiveMQ1、下载资源进入官网下载页面,抉择本人须要的版本下载。 这里因为我的项目须要ActiveMQ 5.11.0 Release,所以能够进入past release找到须要的版本并下载。2、装置相似Tomcat,zip文件解压后间接能够应用,无需装置。 ...

July 29, 2020 · 1 min · jiezi

Tomcat下载与配置

Tomcat介绍Tomcat是Apache组织的一个开源收费的容器,用来治理web开发我的项目,能够用来治理JSP、Servlet本篇文章下载的是Tomcat9版本的 下载到apache官网下载,网址如下:www.apache.org进入之后拉到最上面的APACHE PRODUCT LIST选中Tomcat,抉择Tomcat9我的电脑是windows64位的,所以抉择Core中64位的版本,如果是Linux零碎的,抉择tar.gz版本。如果想要看源码的下载Source Code下的版本,windows版本用zip,Linux版本的用tar.gz。 Tomcat文件介绍下载的Tomcat文件夹下有如下几个文件夹 bin文件夹:和服务器启动相干的文件conf文件夹:和配置文件相干的,该文件夹下有两个比拟重要的 web.xml:是和申请相干的server.xml:和服务器本身的信息相干的,比方端口号lib文件夹:寄存jar包logs文件夹:日志信息temp文件夹:寄存临时文件webapps文件夹:用来寄存部署在容器内的我的项目资源work文件夹:用来寄存解析JSP后造成的java文件Tomcat配置下载实现之后,我这里用的是IDEA 2019编译器运行Tomcat。 关上IDEA,新建一个我的项目,抉择JAVA EE下的web Application 抉择IDEA上的RUN--->Edit Configuration 点击左上角的加号,之后抉择Tomcat的Local版本如果没看到Tomcat可能是没有装置Tomcat插件,点击菜单栏的File-->settings-->plugins-->找到Tomcat选中-->点击Apply,就能够了,而后再反复第二步 进入到第二步的图片所示的地位,点击图片右侧Server下的ConfigureTomcat Home中抉择下载的Tomcat的地位,之后base directory会呈现和Tomcat Home一样的地位,点击OK就行 默认浏览器应用的是谷歌,如果选中After launch,默认是服务器运行之后本人关上默认的浏览器 运行Tomcat容器后在控制台应该会呈现乱码的问题,解决方案如下 点击Run--->Edit Configuration,在VM options中输出-Dfile.encoding=UTF-8 点击Help---->Edit Custom VM options,在最初一行增加-Dfile.encoding=UTF-8(留神:如果是到IDEA目录下批改编译器配置的可能不好用,我之前就是这样没有成果)这样配置完应该就能失常应用了 运行这里咱们简略运行一个网页界面,在web文件夹下创立一个html文件运行后果如下: 留神:如果创立的html文件不是叫index,服务器会运行index.jsp,如果web文件夹下没有index.html或者index.jsp,默认关上的话会找不到资源,因为服务器运行之后默认关上网站时,Tomcat配置文件下默认的资源名称是index。如果想要拜访不是以index为名称的资源就在URL网址前面加上资源名称比方我把index.jsp文件删掉,而后再把index.html的名称改为hello.html,重启服务器,后果如下:在URL前面增加具体资源名称后,后果如下: 如果没有抉择默认开启,就关上一个浏览器在浏览器里输出网址,网址是:http://localhost:8080/项目名称/具体资源名称

July 17, 2020 · 1 min · jiezi

Tomcat类加载机制浅析

前言Tomcat 是后端服务最常见的web容器,关于 Tomcat 一个重要的话题就是它的类加载机制,本文就基于 9.0.16 版本浅析一下 Tomcat 的类加载机制 有几个类加载器?在Tomcat的启动类 org.apache.catalina.startup.Bootstrap 里定义了三个 ClassLoader 类型的属性 ClassLoader commonLoader = null;ClassLoader catalinaLoader = null;ClassLoader sharedLoader = null;在 Bootstrap 的 main 方法里会先 new 一个 Bootstrap 对象,然后调用 Bootstrap#init 方法,并在 init 方法里调用其 initClassLoaders 方法来初始化这三个属性。 private void initClassLoaders() { try { commonLoader = createClassLoader("common", null); if( commonLoader == null ) { // no config file, default to this loader - we might be in a 'single' env. commonLoader=this.getClass().getClassLoader(); } catalinaLoader = createClassLoader("server", commonLoader); sharedLoader = createClassLoader("shared", commonLoader); } catch (Throwable t) { …… }}private ClassLoader createClassLoader(String name, ClassLoader parent) throws Exception { String value = CatalinaProperties.getProperty(name + ".loader"); if ((value == null) || (value.equals(""))) return parent; …… return ClassLoaderFactory.createClassLoader(repositories, parent);}最后一句的 ClassLoaderFactory.createClassLoader 返回的是一个 URLClassLoader 对象。 ...

July 7, 2020 · 6 min · jiezi

一个Tomcat-如何部署多个项目附多种解决方案及详细步骤

此文源自一次多年前面试的面试题,民工哥将它总结出来分享给大家,希望对大家有所帮助,或者今后的面试中说不定会用的上。 首先,我们了解一下常见的Java Web服务器。 Tomcat:由Apache组织提供的一种Web服务器,提供对jsp和Servlet的支持。它是一种轻量级的javaWeb容器(服务器),也是当前应用最广的JavaWeb服务器(免费)。Jboss:是一个遵从JavaEE规范的、开放源代码的、纯Java的EJB服务器,它支持所有的JavaEE规范(免费)。GlassFish:由Oracle公司开发的一款JavaWeb服务器,是一款强健的商业服务器,达到产品级质量(应用很少,收费)。Resin:是CAUCHO公司的产品,是一个非常流行的应用服务器,对servlet和JSP提供了良好的支持,性能也比较优良,resin自身采用JAVA语言开发(收费,应用比较多)。WebLogic:是Oracle公司的产品,是目前应用最广泛的Web服务器,支持JavaEE规范,而且不断的完善以适应新的开发要求,适合大型项目(收费,用的不多,适合大公司)。Tomcat就是实际环境中最常见的,很多时候,特别是像在平时的测试环境,经常会遇到多个项目同时测试的情况,所以,今天民工哥与大家来聊一聊如何在一个Tomcat服务下,同时部署多个应用项目。 1、不修改端口 大家都知道,应用项目是直接放在Tomcat webapps目录下面 [root@CentOS7-1 tomcat]# cd webapps/[root@CentOS7-1 webapps]# lltotal 4drwxr-x--- 16 root root 4096 Jun  4 03:07 docsdrwxr-x---  6 root root   83 Jun  4 03:07 examplesdrwxr-x---  5 root root   87 Jun  4 03:07 host-managerdrwxr-x---  5 root root  103 Jun  4 03:07 managerdrwxr-x---  3 root root  283 Jun  4 03:07 ROOT所以,我们在不修改端口的情况下,可以直接在此目录下新增多个项目目录,也可以直接将war包放在此目录下,由于测试环境,我们直接模拟war解压后的目录,用添加目录来替代。 [root@CentOS7-1 webapps]# mkdir test java[root@CentOS7-1 webapps]# lsdocs examples host-manager java manager ROOT test准备测试的首页文件 [root@CentOS7-1 webapps]# echo "this is a test" >test/test.html[root@CentOS7-1 webapps]# echo "this is a java" >java/java.html[root@CentOS7-1 webapps]# cat test/test.htmlthis is a test[root@CentOS7-1 webapps]# cat java/java.htmlthis is a java修改配置文件 <!-- test -->    <Context path="test/" docBase="test" reloadable="true" />  <Context path="java/" docBase="java" reloadable="true" /> #增加上两行配置即可     </Host>    </Engine>  </Service></Server>"../conf/server.xml" 173L, 7744CdocBase属性: 指定Web应用的文件路径,可以是绝对路径,也可以给定相对路径path属性: 指定访问该Web应用的URL入口。 reloadable属性: 若这个属性为true,tomcat服务器在运行状态下会监视WEB-INF/classes和WEB-INF/lib目录下class文件的改动,如果监测到class文件被更新,服务器会自动重新加载Web应用。 重启Tomcat服务,测试访问,结果如下: 部署成功。 注:配置文件中增加的配置步骤可以不做,直接跳过,不是必须要做的步骤。2、修改端口 第二种修改端口的方法,其实是基于第一种方法做出的改良,在tomcat目录下创建多个webapps目录。 删除webapps目录下的java项目,并删除webapps1目录下test项目即可。 修改配置文件 server.xml已有第一个项目的配置信息,现在需要新增第二个项目的配置,在Server节点下,新增一个Service节点,第2个Service节点直接复制第1个Service内容修改即可。 <Service name="Catalina1"> <!--The connectors can use a shared executor, you can define one or more named thread pools--> <Connector port="8081" protocol="HTTP/1.1"                connectionTimeout="20000"                redirectPort="8443" /> <!-- A "Connector" using the shared thread pool--> <Engine name="Catalina1" defaultHost="localhost"> <!-- Use the LockOutRealm to prevent attempts to guess user passwords            via a brute-force attack --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI              resources under the key "UserDatabase". Any edits              that are performed against this UserDatabase are immediately              available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm"                resourceName="UserDatabase"/> </Realm> <Host name="localhost"  appBase="webapps1"             unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"                prefix="localhost_access_log" suffix=".txt"                pattern="%h %l %u %t &quot;%r&quot; %s %b" /> </Host> </Engine> </Service>只需要注意修改几个配置即可,不太熟悉的读者,可以利用代码工具比较一下,就会发现两段配置的不同,这里就不多解释了。 ...

June 9, 2020 · 2 min · jiezi

Tomcat9配置HTTP2

1 概述Tomcat从Tomcat8的一些较新版本就支持HTTP/2了,Tomcat9直接支持,本文首先讲述了相关HTTP/2的特性,接着利用一个简单的开源工具mkcert生成证书并利用该证书配置HTTP/2。 2 HTTP/2特性首先介绍一下HTTP/2特性,这也从另一方面解释了为什么需要使用HTTP/2。 2.1 二进制分帧HTTP/2在应用层与传输层增加了一个二进制分帧,能够达到“在不改动HTTP语义,HTTP方法,状态码,URI及首部字段的情况下,突破HTTP/1.1的性能限制,改进传输性能,实现低延迟和高吞吐量。” 2.2 压缩头部HTTP/2对消息头采用了HPACK进行压缩传输,能够节省消息头占用的网络流量,而HTTP/1.x每次请求都会携带大量的冗余头信息,浪费了很多带宽资源。 2.3 多路复用简单地说就是所有的请求都通过一个TCP连接并发完成。HTTP/1.x虽然能利用一个连接完成多次请求,但是多个请求之间是有先后顺序的,后面发送的请求必须等待上一个请求返回才能发送响应,很容易导致后面的请求被阻塞。而HTTP/2做到了真正的并发请求。HTTP/2将消息分解为帧,为每帧分配一个流标识符,然后在一个TCP连接上独立发送,HTTP/2将请求帧与响应帧交织在一起,能够让所有请求与响应都在一个套接字上发生,所有请求或响应都无法相互阻塞,减少了延迟,提高了页面加载速度,消除了对HTTP/1.1工具的需求。 2.4 流优先及流控制消息帧通过对流进行发送,每个流分配了一个优先级,用于确定处理顺序以及收到的资源量,优先级可以是0-256之间的数字,可以定义依赖关系,允许在一个资源之前加载另一个资源。流控制管理数据的传输,允许接收者停止或减少发送的数据量,比如观看视频暂停时,客户端会通知服务器停止发送视频数据。 2.5 服务器推送一般情况下需要客户端请求服务器才会响应,HTTP/2中能够先于客户端检测将要请求的资源,提前通知客户端,但是不发送资源只发送URL,客户端收到后会进行验证缓存,发现需要则正式发起请求。 2.6 应用层协商协议客户端与服务器都升级才能支持HTTP/2,但是有可能存在HTTP/1与HTTP/2并存的情况,如果都使用80端口,需要选择其中一个协议通信。APLN(Application Layer Protocol Negotiation)就是为了解决这个问题,通过协商选择协议: 首先客户端发起请求,如果支持HTTP/2则带upgrade头部若服务器不支持则拒绝升级通过HTTP/1.1返回响应若服务器支持则接受升级,切换到新分帧使用HTTP/2通信更多请查看RFC7540 官方文档。 3 使用mkcert生成证书网上大部分的教程都是使用OpenSSL生成根证书,客户端证书以及服务端证书的,一堆参数配置非常复杂,因此这里使用一个简单的一键生成本地证书的开源工具mkcert,无需任何配置。 3.1 安装mkcert3.1.1 MacOSbrew install mkcertbrew install nss # 如果使用火狐使用MacPorts: sudo port selftupdatesudo port install mkcertsudo port install css # 如果使用火狐3.1.2 Linux需要先安装certutil: #Debian/Ubuntusudo apt install libnss3-tools#Red Hat/Fedora/CentOSsudo yum install nss-tools#Arch/Manjarosudo pacman -S nss#SUSEsudo zypper install mozilla-nss-tools使用LinuxBrew安装: brew install mkcert安装LinuxBrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"Arch/Manjaro可以使用pacman安装: ...

June 8, 2020 · 1 min · jiezi

IntelliJ-IDEA创建完整的Spring-Boot项目

使用IntelliJ IDEA创建一个完整的Spring Boot项目流程以IntelliJ IDEA2019.3为例 准备工作 本地安装好JDK电脑已经联网IDEA已经安装IDEA配置好了Maven环境1.打开IDEA开发工具,点击Create New Project创建一个新项目 2.左侧选择Spring Initializr,右侧选择连接https://start.spring.io ,点击next 3.此过程等待加载 4.选择新建项目的相关信息参考如下 Group公司或者组织域名的倒序Artifact 项目或者模块名Type:maven部署方式(一般不更改)packaging:打包方式(一般不更改)Java Version:Java版本(如果你的电脑上有多个JDK版本,请选择)Version:项目或者模块版本(一般不更改)Name:项目名Description:项目描述package:包名(根据需求设置)注意:所有的内容都必须是小写字母,否则IDEA不予通过! 设置完成后,点击Next 5.选择模块和Spring Boot的版本版本建议选择稳定版模块根据需要选择,我这里选择web,Mybatis,MySQL等右边可以看到选择的模块项目 6.填写项目名和项目路径Project name:项目名Project location:存放路径选择好之后,点击Finish. 7.等待Maven部署项目,最好不要乱动项目结构 8.运行项目运行项目方式 左下角的Terminal终端输入命令:mvn spring-boot:run运行运行主程序入口main方法直接运行Spring Boot项目 9.配置数据源运行项目之后,发现有错误,是因为添加了数据库的模块,但是没有配置数据源 数据源配置在项目中依次找到src/main/resources/application.properties文件,将下面的配置信息复制进去,修改为自己的版本 #配置数据库的项目信息(MySQL数据库)#配置数据库的驱动spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# 旧版使用的驱动#spring.datasource.driver-class-name=com.mysql.jdbc.Driver#配置数据库连接URLspring.datasource.url=jdbc:mysql://127.0.0.1:3306/cms?characterEncoding=utf8&serverTimezone=UTC#配置数据库额度用户名spring.datasource.username=lele#配置数据库的密码spring.datasource.password=lele# 配置服务器的相关信息# 配置服务器的端口server.port=80注:数据库的驱动在不同的版本上不同,注意区分版本,因为还添加了web模块,可能存在服务器端口占用问题,我这里顺便将端口改成了80 10.配置完成后,再次运行项目使用命令:mvn spring-boot:run 运行之后光标闪烁,程序正常启动

November 13, 2019 · 1 min · jiezi

android通过web与后台数据库交互

@[toc] 1.背景开发一个app与后台数据库交互,基于mysql+jdbc+tomcat,没有使用DBUtils或jdbc框架,纯粹底层jdbc实现.以后逐步改用Spring框架,优化mysql,进一步部署tomcat等等,现在项目刚刚起步,还有很多不懂的东西,得慢慢来......这几天踩了很多坑,说得夸张点真是踩到我没有知觉,希望能帮助别人少踩坑... 2.开发环境系统 : win10IDE : Android Studio 3.5.1,IntelliJ IDEA 2019.02DBMS : Mysql 8.0.17web服务器: tomcat93.相关资源1.相关jar包:mysqlV8.0.17驱动(注意这个要与自己的mysql版本对应)java-servlet-api-V4.0.1其他版本可以来这里搜索下载Maven仓库2.github这是源码地址,包括前后端与建表等所有代码.(欢迎star) 3.码云这也是源码地址 4.配置开发环境IDE就不说了,重点说一下mysql与tomcat9的安装 一. 安装Mysql8.0.17这个是目前比较新的mysql版本. 服务器系统是centos其他系统安装看这里 win10ubuntufedroareahatcentos使用yum命令安装(参考链接) (1) 下载mysqlsudo yum localinstall https://repo.mysql.com//mysql80-community-release-el7-1.noarch.rpm(2) 安装mysqlsudo yum install mysql-community-server(3) 启动服务sudo service mysqld start(4) 查看初始化密码,用于下一步设置自己的root密码sudo grep 'temporary password' /var/log/mysqld.log(5) 本地使用root登录mysql -u root -p输入上一步看到的密码 (6) 更改密码alter mysql.user 'root'@'localhost' identified by 'password';注意新版本的mysql不能使用太弱的密码如果出现如下提示则说明密码太弱了,请使用一个更高强度的密码 (7) 允许外部访问use mysql;update user set host='%' where user='root';这个可以根据自己的需要去修改,host='%'表明允许所有的ip登录,也可以设置特定的ip,若使用host='%'的话建议新建一个用户配置相应的权限. (8) 配置防火墙(可选)由于作者使用的是阿里云的服务器,没配置防火墙的话远程连接不上,因此需要手动配置,如图 其中授权对象可以根据自己的需要更改,0.0.0.0/0表示允许所有的ip. 二.安装tomcat9(1) 先去官网下载,下载后上传文件到服务器作者使用的是scp命令,不会的可以看这里 scp apache-tomcat-xxxx.tar.gz username@xx.xx.xx.xx:/改成自己的用户名和ip (2) 连接到服务器,解压压缩包mkdir /usr/local/tomcatmv apache-tomcat-xxxx.tar.gz /usr/local/tomcattar -xzvf apache-tomcat-xxx.tar.gz(3) 修改tomcat默认端口(可选)修改conf/server.xml文件,一般只需修改 ...

October 14, 2019 · 5 min · jiezi

SpringBoot2xSpringBoot-Web开发中ThymeleafWebTomcat以及Favicon

github:https://github.com/Ccww-lx/Sp... 模块:spring-boot-starter-base-web Web开发是开发中至关重要的一部分, Web开发的核心内容主要包括内嵌Servlet容器和Spring MVC。更重要的是,Spring Boot`为web开发提供了快捷便利的方式进行开发,使用依赖jar:spring-boot-starter-web,提供了嵌入式服务器Tomcat以及Spring MVC的依赖,且自动配置web相关配置,可查看org.springframework.boot.autoconfigure.web`。 Web相关的核心功能: Thymeleaf模板引擎Web相关配置Tomcat配置Favicon配置1.模板配置1.1原理以及源码分析 Spring Boot提供了大量模板引擎, 包含括FreeMarker、Groovy、 Thymeleaf、 Velocity和Mustache, Spring Boot中推荐使用Thymeleaf作为模板引擎, 因为Thymeleaf提供了完美的Spring MVC的支持。 在Spring Boot的org.springframework.boot.autoconfigure.thymeleaf包下实现自动配置,如下所示: ThymeleafAutoConfiguration源码: @Configuration@EnableConfigurationProperties(ThymeleafProperties.class)@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })public class ThymeleafAutoConfiguration { //配置TemplateResolver @Configuration @ConditionalOnMissingBean(name = "defaultTemplateResolver") static class DefaultTemplateResolverConfiguration { ... } //配置TemplateEngine @Configuration protected static class ThymeleafDefaultConfiguration { ... } //配置SpringWebFluxTemplateEngine @Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true) static class ThymeleafWebMvcConfiguration { ... } //配置thymeleafViewResolver @Configuration @ConditionalOnWebApplication(type = Type.REACTIVE) @ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true) static class ThymeleafWebFluxConfiguration { ... } ...} ThymeleafAutoConfiguration自动加载Web所需的TemplateResolver、TemplateEngine、SpringWebFluxTemplateEngine以及thymeleafViewResolver,并通过ThymeleafProperties进行Thymeleaf属性配置。详细细节查看官方源码。 ...

October 6, 2019 · 3 min · jiezi

有的线程它死了于是它变成一道面试题

有些线程它活着,但它躺在池中碌碌无为;有的线程它死了,于是它变成一道面试题。 这次的文章,要从一次阿里的面试说起。 我记得那天是周一,刚刚经历过周末过的放松,干劲十足的我正在键盘上疯狂的输出。这时,我的手机响了起来,拿起一看,是来自杭州的电话,心想这次是要给我推荐股票呢还是要让我贷款呢。我接起了电话,准备“调戏一番”。那边响起一个声音:"你好,请问是xxx吗?这边是杭州阿里巴巴,现在有时间进行电话面试吗?"。说实在的,听完这句话后,我感觉我已经身在杭州,干劲十足的在杭州的阿里的工位上"修福报"。但是我现在正在疯狂输出,没有时间,于是我说:"不好意思,现在没有时间,可以约在今天晚上8点钟吗?". 晚上如约接到了电话。我们直奔主题,在你来我往中进行了友好的技术交流。具体的面试过程就不详述了,后面有机会整理一份面试分享。整个面试过程中,有这么一道题给我留下了深刻的印象: 一个线程池中的线程异常了,那么线程池会怎么处理这个线程?需要说明一下,文中讨论的线程池都是Executors线程池。 对于Executors线程池我可以说是烂熟于心,因为工作中用的比较的多,阅读过其源码。也是我作为面试官时必问的几个范围之一,比如以下问题: 了解JDK Executors线程池吗?知道JDK提供了哪些默认的实现吗?看过阿里巴巴java开发手册吗?知道为啥不允许使用默认的实现吗?你们没有用默认的吧?那来介绍一下你们自定义线程池的几个常用参数呗?你这个几个参数的值是怎么得来的呀?算出来的?怎么算出来的?线程池里面的任务是IO密集型的还是计算密集型的呢?好,现在我们有一个自定义线程池了,来说一下你这个线程池的工作流程呗?那你这个线程池满了怎么办呀?拒绝?咋拒绝?有哪些拒绝策略呢?别紧张,随便说两个就行。......回到开始说的阿里巴巴java开发手册不允许使用默认实现,你回答说可能会引起OOM,那我们聊聊JVM吧...... 阿里巴巴java开发手册关于线程池创建的建议 这一系列关于线程池的连环炮,就是我作为面试官时必问的几个问题。别问为什么,因为我们的招聘JD上明确写了:熟悉多线程编程。而这些问题,我觉得是熟悉多线程编程的基础。这里我也不解答了,这种文章网上还是挺多的,可以去了解一下。 这块真的很重要,我也多次给我的小伙伴强调: 来吧,一起分析一波好了现在回到阿里的面试官问我的这道面试题: 一个线程池中的线程异常了,那么线程池会怎么处理这个线程?先说说我当时的回答,因为心里没底,我的回答很犹豫也很烂!如下: 我的回答总结起来三句话: 1.抛出堆栈异常 ---这句话对了一半!2.不影响其他线程任务 ---这句话全对!3.这个线程会被放回线程池 ---这句话全错!测试用例写起来抛出堆栈异常为啥对了一半?先让程序跑起来,我们用事实说话:从执行结果我们看出 当执行方式是execute时,可以看到堆栈异常的输出。当执行方式是submit时,堆栈异常没有输出。那么我们怎么拿到submit执行方式的堆栈异常呢,看图说话:所以,现在知道为什么回答:抛出堆栈异常只对了一半吧。execute方法执行时,会抛出(打印)堆栈异常。submit方法执行时,返回结果封装在future中,如果调用future.get()方法则必须进行异常捕获,从而可以抛出(打印)堆栈异常。你以为这一部分写到这里就完事了?那不行啊,你心里没有一个疑问吗?为啥execute直接抛出异常,submit没有直接抛出异常呢? 源码之下无秘密:当执行方式是executes时:在java.util.concurrent.ThreadPoolExecutor#runWorker中抛出了异常:在_java.lang.ThreadGroup#uncaughtException_进行了异常处理:这个uncaughtException是何许人也,看java doc上咋说的:这个方法是JVM调用的,我们只需要指定我们想要的处理方式即可。那我们怎么指定呢: //直接new Thread()的时候Thread t=newThread();t.setUncaughtExceptionHandler(newThread.UncaughtExceptionHandler(){publicvoiduncaughtException(Thread t, Throwable e){//根据业务场景,做你想做的 }});//线程池的时候:ExecutorService threadPool = Executors.newFixedThreadPool(1, thread -> {Thread t =newThread(thread);t.setUncaughtExceptionHandler((t1, e) ->System.out.println("根据业务场景,做你想做的:"+ e.getMessage()));returnt;}); 当执行方式是submit时: 其本质也是调用了execute方法,所以它还是回到_java.util.concurrent.ThreadPoolExecutor#runWorker_方法:向前,继续跟进去看看:_java.util.concurrent.FutureTask#setException_干啥了啊,瞅一眼:深呼吸,整理好思路,我们马上走向最终的真相:好了,第一个议题【抛出堆栈异常为啥对了一半?】讨论完毕。在源码里面走了一趟,现在我们可以给出这一部分的满分答案了。 不影响其他线程任务,回答正确这一部分我们直接上代码,运行起来看结果吧:代码和运行结果是不会骗人的:线程池中一个线程异常了后,不影响其他线程任务大家注意线程名称这个细节:1,2,3,4,6。魔鬼都在细节里啊,这个点我下面会讲,先在这里把问题抛出来:我就纳闷了,怎么没有5啊?! 这个线程会被放回线程池为啥全错了?我们去源码里面寻找答案:让源码给出答案:5号线程去哪里了?new Worker()方法会告诉你:5去哪里了。再配上这张由我这个灵魂画师亲自操刀画的图,一起食用,味道更佳: 现在知道为啥:我回答这个线程会被放回线程池为啥全错了吧。还附带送你一个线程名称变化的细节,不客气。 总结一下当一个线程池里面的线程异常后:当执行方式是execute时,可以看到堆栈异常的输出。当执行方式是submit时,堆栈异常没有输出。但是调用Future.get()方法时,可以捕获到异常。不会影响线程池里面其他线程的正常执行。线程池会把这个线程移除掉,并创建一个新的线程放到线程池中。不要背答案,要理解,要深入,上面说完后记得在问问面试官,需要我从源码的角度讲一讲吗?这逼装的,礼貌而不失风度。以上,我关于《一个线程池中的线程异常了,那么线程池会怎么处理这个线程?》这个问题的见解就表达完毕,仅代表个人观点,欢迎有不同意见的小伙伴,一起讨论,一起进步。 最后说一点这篇文章是我上周五推完上一篇文章之后就在构思并且着手准备了。大部分内容都是思考于晚上睡觉前的半小时,写于周末和工作日的早上早起的一小时。其实想到写什么内容并不难,难的是你对内容的把控。关于技术性的语言,我是反复推敲,查阅大量文章来进行证伪,总之慎言慎言再慎言,毕竟做技术,我认为是一件非常严谨的事情,我常常想象自己就是在故宫修文物的工匠,在工匠精神的认知上,目前我可能和他们还差的有点远,但是我时常以工匠精神要求自己。就像我在群里表达的:对于技术文章(因为我偶尔也会荒腔走板的聊一聊生活,写一写书评,影评),我尽量保证周推,全力保证质量。最后,再感叹一次: 有些线程它活着,但它躺在池中碌碌无为;有些线程也活着,但它一刻不停忙到飞起;有的线程它死了,被抛弃,被回收,但是它无怨无悔, 因为它是死在执行任务的路上,它凭借自己最后的一声呐喊“为了新兄弟,移除我吧!”最后,变成一道面试题。 我还没答上来。 欢迎关注公众号【why技术】。在这里我会分享一些技术相关的东西,主攻java方向,用匠心敲代码,对每一行代码负责。偶尔也会荒腔走板的聊一聊生活,写一写书评,影评。愿你我共同进步。

September 19, 2019 · 1 min · jiezi

Linux服务器-下载并安装JDK

⭐ 我的网站: www.mengyingjie.com ⭐ 与这篇文章相关的操作:Linux服务器上下载并安装tomcat首先是jdk8u211的下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 1检查并卸载OpenJDK第一步检查系统是否自带了OpenJDK以及相关安装包,如果有的话则应先将其卸载。 检查命令: java -versionrpm -qa | grep java如果发现有安装好的OpenJDK以及安装包的话那么首先依次执行卸载。 卸载命令: rpm -e --nodeps tzdata-java-2012c-1.el6.noarchrpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-1.45.1.11.1.el6.x86_642解压安装(如何向服务器里上传下载文件)将安装文件上传到linux服务器后,进入到该目录执行解压安装: tar -zxvf jdk-7u75-linux-x64.tar.gz 解压完成后创建一个新的java目录并将刚刚解压的jdk目录移动到我们创建的目录: mkdir /wocloudmv ./jdk1.8.0_211 /wocloud3配置环境变量(不太熟悉vi操作的可以去学习下)安装完成后需要配置一下环境变量,编辑/etc/profile文件: vi /etc/profile在文件尾部添加如下配置: export JAVA_HOME=/wocloud/jdk1.8.0_211export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarexport PATH=$PATH:$JAVA_HOME/bin截图如下: 编辑完成后按esc后输入:wq保存退出,最后一步就是通过source命令重新加载/etc/profile文件,使得修改后的内容在当前shell窗口有效: source /etc/profile4测试输入java -version查看一下jdk版本信息: 如下图图所示正常显示了jdk版本,到此为止就已经安装成功了。 遇到此类问题,但看了文章还是未解决,评论或加 QQ:781378815

September 8, 2019 · 1 min · jiezi

Http-历险记之-NginxTomcat上

转自:码农翻身(微信号:coderising) 第一章 Nginx大厦汽车终于到站, 我带着保险柜从车上下来, 我想这应该是目的地了, 这是一个叫mytaobao.com的大厦,上面有两个入口 “80号通道” 和 “443号通道”。 从浏览器村出发的时候, 老IE就告诉过我, 找到这个大厦, 走安全通道进去, 自然有人接待。 哪个是安全通道? 我看到这两个通道都有很多人进进出出,有点犯嘀咕了, 正琢磨着呢, 里边出来一个保安, 用很鄙视的语气对我说:“还愣着干嘛, 还不赶紧进443通道”“为啥啊?”“你没看运你来的车吗? 上面写着HTTPS :443 端口” 奥,我确实是没有注意到, 赶紧进去吧。 进入443通道, 果然如老IE所说, 里边马上就迎过来一个人, 穿着服务员的衣服, 很热情的说:“我是4号长工, 很高兴为您服务”“长工? 你们这儿还是封建社会啊?”“是啊, 我们这儿还有地主呢,时不时给我们4个长工发号施令,对我们压榨的很厉害啊, 你看前面这么多人,这么多活, 就我们4个长工干” 我往前一看, 可不是, 前面的大厅熙熙攘攘, 但是穿服务员衣服的,我只看到4个人 。 "我和你们老IE的连接很早就建立了, 你怎么才来啊“ 4号长工问我。 "唉, 这一路实在是太远了, 先是坐着驴车从浏览器村出发, 然后坐汽车, 然后坐飞机, 中间还在几个路由器中转了好几次, 这才来到这里。 " 4号长工有个办公桌, 已经围了不少人, 七嘴八舌的问他:"我的那个图片取出来没有, 我都等了半边了”“我的javascript文件呢?”“我的css的呢?”“我的html呢?” 要是我估计头都炸了, 但是4号长工见怪不怪, 淡定的统一回复:“对不起, 再等等吧, 数据取出来了会通知我的”。 听到这句话, 我的脑子立刻亮了, 我看过《Node.js 我只需要一个店小二》, 看来这些长工们干活的方式和Node.js一样啊, 一人应付所有客户, 都是事件驱动, 怪不得他们4个长工能服务这么多人。 ...

September 7, 2019 · 1 min · jiezi

好物分享

好物分享去年做了一个“帮我记”。帮我记录了很多事情,从此很少错过重要的时刻。 这一年,工作一直比较忙,很多时候来不及打开“帮我记”记下需要提醒我的事情,有时忙一周下来已经忘了周一周二都干了啥,甚至会突然想不起接下来要做什么。周报都是到deadline时被提醒才想起来,内容也要想半天去总结。 一直在思考怎么提高个人效率(生活,工作等),所以上周末两天又开发了一个网站(https://www.qbian.me/efficient),按照项目和日常两种纬度去创建任务,可设置定时任务提醒,可自定义时间范围统计已完成任务,可自定义任务清单推送时间,实现自动发日报、周报。 使用了一周,每天要做的事一目了然,重要的事没有错过,周报也被定时发送。 欢迎大家体验,多提建议;

September 7, 2019 · 1 min · jiezi

我叫Tomcat一款web服务器

Tomcat,从这里开始如何将我们的 Java 代码,运行在网络上,初学时,首先接触到的一般都是Servlet以及Jsp(或略过Jsp)而 Tomcat 就是这两者的容器,帮你处理动态网页部分(一) 从哪来,到哪去?(1) Tomcat和它的小伙伴JBoss:Redhat 红帽,支持所有的 JavaEE 规则,适合大型项目,收费 Weblogic:Orcale,支持所有 JavaEE 规则,适合大型项目,收费 Websphere:IBM,支持所有 JavaEE 规则,适合大型项目,收费 Resin:Caucho,支持 所有 JavaEE 规则,应用趋于广泛 而我,我叫汤姆猫(Tomcat),来自Apache基金组织,可能因为我开源且免费,算是应用比较广泛的web服务器了,不过天下没有白吃的午餐,我仅仅支持少量的 javaEE规范 (Servlet/Jsp等)所以中小型项目,在我这里跑的比较多 (2) Tomcat用来做什么? 1、做Servlet等的容器比如现存一个搜索引擎,我们将它看成一个完整的web项目,它基于http协议中的请求和响应,我输入一些内容查询,而它接收到了这个请求后,简单的认为,背后有一个Servlet(一些应用于web项目的java代码)在处理这个请求,它会通过一系列方法,对你的数据进行处理,以及查询,例如,正常则查询,存在非法字则不查询,返回文字警告,最后再把相应的界面展示给用户,而 Tomcat 就作为一个容器,其中存放着Servlet等东西 2、让你/他人能在浏览器中访问你的web项目想要在浏览器中访问我们本地的web项目,那必然需要一个URL地址,例如http://localhost:8080/ (本地) ,也就是IP+端口号,那这个开放的端口,总得帮助我完成一些操作,它需要找到我再web.xml中配置的一些信息,然后找到我的Servlet,将我所需要的功能实现,执行完后,将结果返回到浏览器上,这样就能用java代码配合一些页面,实现数据动态的互动,从而在浏览器上查看这个效果 (二) 配置 Tomcat(1) Tomcat的启动和关闭Tomcat的运行需要依赖 JDK,它会通过JAVA_HOME路径来寻找 JDK,我们是有 Java基础的,所以这一步可以忽略 方式一 在我们的安装路径下的bin文件夹中,startup.bat、shutdown.bat这两个文件分别代表着启动和关闭 例如在我的电脑中开启 Tomcat:D:developJavaapache-tomcat-8.5.40binstartup.bat 方式二 如果想更加方便一点,可以将这两者也设为环境变量 计算机 --> 右键属性 --> 高级系统设置(左侧)--> 高级 --> 环境变量 新建系统变量 --> 变量名:CATALINA_HOME 变量值:Tomcat安装路径 修改path变量 --> 追加:%CATALINA_HOME%bin 这样我们就可以在cmd中直接输入startup或shudown,启动我们的 Tomcat 启动后,弹出名为Tomcat的框,内打印出日志信息,即代表成功开启 如果在浏览器地址栏中输入 http://localhost:8080,如果出现对应Tomcat页面,说明配置也就成功了 因为服务器在本地上,所以我们的主机名可以为,http://127.0.0.1:8080 或者 http://localhost:8080,端口前代表本地的主机名,tomcat的默认端口为8080 ...

August 20, 2019 · 1 min · jiezi

Ubuntu下5分钟快速部署java网站环境

如何在ubuntu下快速部署java网站环境,我们都知道,Linux中要运行java网站则需要安装Tomcat,一个完整的java网站环境由Tomcat+web服务组成。本文中java网站环境为Tomcat+Apache。我们将使用URLOS一键安装java网站环境,仅需5分钟哦,让我们开始吧! 首先,我们需要通过一下命令安装URLOS面板: curl -LO www.urlos.com/siu && sh siu安装完成后,在URLOS应用市场中安装JAVA网站环境: 在基本信息里填写服务名称、运行节点、端口号: 在网站信息中填写网站域名: 完成以上步骤后,点击提交,等待服务部署完成。 我们仅需5分钟就完成了JAVA网站环境的搭建,部署效率非常之高,感兴趣的朋友可以研究一下URLOS的其他功能。

July 15, 2019 · 1 min · jiezi

Servlet编写注册登录页面

新建一个servlet项目Flies --> new --> project-->ProjectSDK选择自己的JDK文件-->勾选Web Appliction -->Next 项目构造如下: 设置项目配置File --> Project Structure (快捷键:Ctrl + Shift + Alt + S) --> 选择Module : 配置Tomcat 红色框选择时,运行成功会会自动运行下方的URL链接 测试运行出现如下便创建成功 编写第一个Servlet代码,测试环境是否设置成功@WebServlet("/firstServlet")public class test extends HttpServlet { private String message; @Override public void init() throws ServletException { message = "第一个servlet"; } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置响应内容类型// response.setContentType("text/html"); response.setHeader("Content-type","text/html;charset=UTF-8"); // 实际的逻辑是在这里 PrintWriter out = response.getWriter(); out.println("<h1>" + message + "</h1>"); } public void destroy() { // 什么也不做 }}注解@WebServlet是设置该类的URL,也可以在web.xml里设置,如下: ...

July 8, 2019 · 1 min · jiezi

全栈之路JAVA基础课程九解决IntelliJ-IDEA控制台输出中文乱码问题20190706v10

欢迎进入JAVA基础课程 博客地址:https://mp.csdn.net/mdeditor/...本系列文章将主要针对JAVA一些基础知识点进行讲解,为平时归纳所总结,不管是刚接触JAVA开发菜鸟还是业界资深人士,都希望对广大同行带来一些帮助。若有问题请及时留言或加QQ:243042162。 寄语:无论生活、学习还是工作中,我们都要擅于利用工具。生活中我们要利用人情工具;学习中我们要利用书籍和各种信息化工具;工作中我们要借鉴和利用前辈的经验,唯有这样,才能使我们事半功倍。问题描述:IntelliJ IDEA 控制台输出中文乱码部分如图所示: 解决方法1.打开tomcat配置。 2.选择项目部署的tomcat,在配置项VM options文本框中输入-Dfile.encoding=UTF-8,点击Apply或OK即可。 3.尝试重启tomcat,乱码问题解决。 注意事项:若乱码问题依然存在,请尝试继续按以下步骤解决: 1.打开IntelliJ IDEA本地安装目录中bin文件夹下的idea.exe.vmoptions和idea64.exe.vmoptions这两个文件。 2.分别在这两个文件内容的末尾添加-Dfile.encoding=UTF-8 3.打开IntelliJ IDEA>File>Setting>Editor>File Encodings,将Global Encoding、Project Encoding、Default encodeing for properties files这三项都设置成UTF-8,点击OK或者Apply。 4.重启IntelliJ IDEA即可解决乱码问题。

July 6, 2019 · 1 min · jiezi

我对-SpringMVC-的一些误解

引言刚考完期末,再也不用考试啦!!! 最近学习了慕课网的实战课《手写SpringMVC,剑指开源框架灵魂》。 spring-boot太过智能了,智能到我们完全不用去管底层是如何实现的,都可以很轻易地去开发一款web应用。 最近将本课程和《看透Spring MVC》结合起来学习,感觉受益匪浅,同时,纠正了我之前对SpringMVC的一些误解。 误解洪荒时代的Java Web当年,开发Java Web都需要手动去实现Servlet。 public class TestServlet implements Servlet { @Override public void init(ServletConfig config) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { } @Override public String getServletInfo() { return null; } @Override public void destroy() { }}Servlet中规定了五个方法。 init初始化方法,service业务逻辑方法,destroy销毁方法。 在web.xml文件中配置路由到Servlet之间的映射,也就是说,我们没开发一个接口,都需要写一个Servlet,然后配一遍xml。 <!-- 基本配置 --><servlet> <servlet-name>test</servlet-name> <servlet-class>TestServlet</servlet-class></servlet><servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>/test</url-pattern></servlet-mapping>所以就导致了项目中会有很多的Servlet,以及极其冗长的xml配置文件。 ...

July 5, 2019 · 1 min · jiezi

GETPOST与后端接口详记

前言HTTP通信的7种方式在HTTP通信中主要分为GET和POST。如PUT,DELETE是类POST的传输方式,与POST没有实质区别。OPTION是查看服务器支持的请求方法。HEAD是测试服务器的该资源情况,不返回实体的主体部分。TRACE请求可以获取回服务器接收到的该请求的原始报文,从而判断路径中的代理和防火墙是否对该条请求进行修改。 HTTP请求报文发送格式不因请求方式不同而改变HTTP报文格式如下<请求方法> <请求路径> <协议版本><请求头> <主体body> 无论用任何请求方法,都可以发送这样的请求报文,报文结构是HTTP的协议规范,请求方法只是告诉服务器如何来看待这条请求。因为在有些文章中会提到GET请求不能传body数据,而真实的情况是有些服务端框架接收到GET请求后会自动将GET请求的body部分丢弃,所以大家要注意。所以为了规范,大家在使用GET请求时还是不要将请求数据放在body中。何时用GET请求为了规范,使用GET请求时就不要在主体body中放数据了,避免不必要的错误。所以请求中的数据是放在URL上的。 浏览器网址栏和页面跳转。为了获取信息且不需要传大量条件信息的接口。例如用GET做登录请求 GET /online/test/?name=haha&amp; password=miaomiao HTTP/1.1Host: 127.0.0.1:8080Content-Type: application/x-www-form-urlencodedcache-control: no-cachePostman-Token: 14a1347a-c540-48f0-9d49-6299f86c3a73何时用POST请求post请求可以在body中传送大量信息 以上传name=haha,password=miaomiao为例,查看不同body数据格式 form-data(表单,可以传文件)POST /online/test/? HTTP/1.1Host: 127.0.0.1:8080Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gWcache-control: no-cachePostman-Token: c6e21725-caec-4a40-841c-7b92f87f6999Content-Disposition: form-data; name="name"hahaContent-Disposition: form-data; name="password"miaomiao------WebKitFormBoundary7MA4YWxkTrZu0gW--若在表单中附加一张图片 POST /online/test/? HTTP/1.1Host: 127.0.0.1:8080Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gWcache-control: no-cachePostman-Token: 437207ba-e007-4de8-bbcd-bdc88db6e445Content-Disposition: form-data; name="name"hahaContent-Disposition: form-data; name="password"miaomiaoContent-Disposition: form-data; name="profile"; filename="C:\Users\Think\Pictures\profile.jpg------WebKitFormBoundary7MA4YWxkTrZu0gW--其中表单的每一项都有Content-Disposition描述。------WebKitFormBoundary7MA4YWxkTrZu0gW--是随机生成的分隔标记x-www-form-urlencoded(也是表单,但不可以传文件)POST /online/test/? HTTP/1.1Host: 127.0.0.1:8080Content-Type: application/x-www-form-urlencodedcache-control: no-cachePostman-Token: 35566466-0568-4731-9c1c-6eda7dfca105name=hahapassword=miaomiaoundefined=undefined因为不用传文件,所以不用单独描述,将表单信息拼凑在一起就可以了。application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的编码格式。multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。raw(text,json,xml...)(其它文本格式)以json格式为例 POST /online/test/? HTTP/1.1Host: 127.0.0.1:8080Content-Type: application/jsoncache-control: no-cachePostman-Token: 06a9f071-4424-428a-b17b-9b4fe6f209a2{ "name":"haha", "password":"miaomiao"}------WebKitFormBoundary7MA4YWxkTrZu0gW--binary(二进制)用作传输文件,包括前面的form-data上传文件,文件都是以一定的编码方式写在body中的,在服务器端获取该请求的输入流后,即可按行接收流中的数据信息。 在Spring Boot中接口的接收数据总结URL接收GET参数列表对于数字基本类型和包装类型都可接收,但是若前端并没传这个数字,那么包装类型可以在代码里判空,异常处理就好,但是基本类型是不能判空的,所以对于数字首选包装类型。 @RequestMapping(value = "/",method = RequestMethod.GET) @ResponseBody private ResInfo test(String name,String password){ return new ResInfo(200,"登录成功: "+name+" "+password); }PostMan接收 ...

July 2, 2019 · 2 min · jiezi

阿里云centos7线上项目绑定域名且使用https的方式访问

导读如今,毕业将近一年了。一直使用公司的老框架,该框架采用前后端不分离的模式。但是,最近公司想要采用前后端分离的模式,并让我重新架构新框架。对于,毕业不久的我,担任了架构师的角色,于是,徒手编写新的框架,最后,成功了,已实现前后端分离的效果。并把它部署到线上,同时,使用了HTTPS格式。 前后端具体怎么分离的,在这里,我就不细说了,我就说部署之后绑定域名和ssl这部分吧。 准备工作服务器。我使用阿里云的centos7服务器Tomcat。我用的是Tomcat7MySQL。我用的是MySQL5.7jdk。我用的是jdk8ssldns解析域名备案前提条件我已经把项目部署到centos7上,并能够通过ip访问。接下来,就是域名解析和绑定,并结合ssl。 具体做法阿里云后台首先登录阿里云的后台,你会看到如下界面 步骤1,单击之后,你会看到如下界面,选择云服务器 ECS 单击步骤2,你会看到步骤3,单击步骤4之后,再单击步骤4,会跳出配置安全组的弹框。具体如何配置安全组,在创建安全组旁边会有教程。 在安全组中加入 443 这个端口,为什么要加入这个端口号?HTTPS默认是的443端口。 绑定域名单击步骤1之后,选择域名服务,选单击下图中的域名 如果你还没有备案你的域名,可以单击此链接进行备案。 此时,你可以看到你备案完成的域名,如图所示: 单击右面的 解析,进入到域名解析页面,如图所示: 如果不太熟悉解析操作,直接单击新手指导,输入你公网的ip即可解析,如图所示: 此时,已完成解析。你解析完成后,也不能立即访问,因为可能有延迟。即便可以访问,但是,你不能使用 http 访问,因为,你还没有配置 ssl。接下来,就是配置ssl的操作。 配置ssl阿里云证书申请阿里云服务控制台->安全(云盾)->SSL证书 单击 购买证书 ,前去购买证书,填入补全资料,按照默认提示勾选,并绑定域名,即可申请成功。但是,你无法立即下载证书,因为的状态不是 已签发,这里有个审核期,如图所示: 此时,你的状态是已签发,你可以下载证书。此时,它是压缩包。你解压之后,会看到两个文件。一个是PDF格式的文件,这是证书名称,即keystoreFile;一个是以TXT结尾的文件,这是证书密码,即keystorePass。 然后,在你的服务器上的Tomcat目录下,建一个名为cert的文件夹,把解压后的文件拷贝进去,如图所示: 进入到文件夹cert下的 conf 文件中,找到 server.xml文件并打开,找到8443端口号。Tomcat默认将其注释,此时,将注释去掉,并修改端口号为 443 填写如下内容: <Connector port="443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" keystoreFile="你证书名称的全路径" keystoreType="PKCS12" keystorePass="你证书的密码" /> 此时,用不到 SSLProtocol和ciphers,直接注释掉就可以。 此时,找到host标签,如下图所示: 有人建议,需要在autoDeploy="true"后添加docBase属性,来配置指定目录的绝对路径。也就是说,当用户输入域名时,默认的展示页面。我没有添加,而是,直接再目录WebApps/ROOT中的目录中,将前端项目放在里面,如图所示: 此时,输入域名:https://www.superjson.com 即可访问该项目。 备注成为架构师还真不容易,需要掌握太多的知识点。越努力,越幸运。

June 26, 2019 · 1 min · jiezi

使用IDEA创建一个SpringMVC的项目

写在前面:参照《spring实战》实现 1. 使用idea创建项目 这里使用gradle构建项目依赖 使用自己本地的gradle环境 2. 构建完成项目之后修改gradle的配置文件(使用阿里库) 3. 引入springmvc的相关依赖 版本配置文件,这个信息都在上面的依赖中使用到了 4. 这里我们使用纯Java配置 a. 创建WebInitializer类用于替代web.xml的功能 b. WebConfig.java配置springmvc的相关参数 c. RootConfig.java配置spring的相关参数 d. 创建一个控制器HomeController e. 在下面的目录里面创建home.jsp 5. 使用tomcat启动项目,访问

June 26, 2019 · 1 min · jiezi

基于EC2配置一个全栈服务实例nginx-tomcat-mysql

最近世道动荡,在前往高级的路上走出了车到山前必有路,睁眼一看是绝路的感觉。所以就索性瞎折腾一下。领了一个服务器,开启了一个伪全栈的运维之路,各种服务线上部署。 服务器申请与实例连接接腾讯免费七天,阿里要钱,山里娃就在亚马逊AWS申请了一个可免费使用一年的EC2云服务器,申请链接,步骤很简单,跟着提示一步一步整就是,唯一要提醒的就是,需要准备一张信用卡,一张能支持外汇($)结算的最好。申请到资格后,选择你的云服务,选择对应的区域,你需要给服务实例选择一个操作系统,linux,windows常用的都可选(注意观察,我们只选免费的,很重要,很重要, 很重要)。然后配置安全组,bla,bla,....,然后启动实例。保存好你的密钥,然后打开ssh终端连接实例。操作步骤可以打开管理面板,选择实例-》选择实例-》连接-》根据面板提示连接。 安装与配置基础组件安装与配置登录进服务后,就可以开启一段服务器配置之旅了。如果你和我一样,对Linux常用的命令行还不熟悉,你可能需要这样一份手册:Linux常用命令大全。我选择的镜像是Ubuntu,如果你和我选择的一样,那么下面的命令你可以直接用,如果是redhat或者centos,有些命令,你需要自己去探索。先把一些常用的工具安装上: sudo apt-get install unzip // 解压工具 sudo apt-get install git // git工具 sudo apt-get install wget // 下载工具 sudo apt-get install nginx // 下载nginx node服务安装与配置node安装是一个相对简单的过程,你可以直接查看官网,然后按照提示一步一步进行。非常重要的一步就,你需要建立你命令的软链接。在这里我列出自己的操作步骤: -下载:sudo wget https://nodejs.org/download/r... 建一个文件夹:sudo mkdir -p /usr/local/lib/nodejs解压到上面新建文件夹:sudo tar -xJvf node-v8.16.0-linux-x64.tar.xz -C /usr/local/lib/nodejs建立node可执行命令链接:sudo ln -snf /usr/local/lib/nodejs/node-v8.16.0-linux-x64/bin/node /usr/bin/node重复上述步骤,建立npm可执行链接测试有效性:node -v // node-v8.16.0jdk的安装与配置centos可参考链接,同时也适用于ubuntu,现在使用wget下载jdk有点麻烦(需要鉴权),所以我是本地下载,然后scp上传上去的,以下是我的操作: 上传:scp -i "big.pem" jdk-8u211-linux-x64.tar.gz ubuntu@ec2-13-114-140-94.ap-northeast-1.compute.amazonaws.com:/home解压并重命名为tomcat:tar xzf jdk-8u211-linux-x64.tar.gz建立链接java,javac,jar:sudo ln -snf /home/tomcat/bin/java(你解压后的目录) /usr/bin/java, 其他两个照做测试: java -versiontomcat服务的安装与配置下载 wget http://mirrors.tuna.tsinghua....解压进入到bin目录,然后执行 ./startup.sh实例ip查看服务运行情况(前提是在安全策略允许了8080端口的连接)数据库的安装与配置mysql的安装复杂一点,折腾了自己大量时间,在redhat8上没有安装成功mysql5,也迫使我把镜像换成了ubuntu,曲折的路就不多说了,直接说顺利的。如果直接使用apt-get install mysql安装,默认是安装mysql8,所以在开启安装前,需要借助mysql-apt-config增加一段配置,具体安装步骤,请查考前人栽下的树:Ubuntu 16.04安装MySQL:通过APT方式安装。安装好之后,开启mysql,并登录 ...

June 24, 2019 · 2 min · jiezi

于一次简单的get请求得知tomcat的一个小坑

一、前言在接到需求后很快的做完了然后做本地测试发现: java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986因为是get请求里面参数数据是查询人名所以携带中文,对此进行了问题分析。 二、分析过程在当时我就立马咨询了百度老师,是因为Tomcat在某个版本里面升级了,对URL遵守RFC规范,对特殊字符不予以放行。要解决问题有两个方向: 1.解决编码问题。2.Tomcat降版本。 使用postman携带中文参数可以正常访问到数据,之前也没有遇到过这样的问题,因此java服务端是没问题的,而且服务是使用springboot 1.5.3 ,对应的Tomcat版本是8.5.14,不考虑打成war包部署就打算从编码入手了。 其实问题说起来还是挺简单的。。但是因为服务设计的框架所以走错了路子。。。想记录一下分析的过程。 从前端那里携带中文参数访问Tomcat,在Tomcat的访问日志里,看到了携带中文参数的请求是这样的: [18/Jun/2019:19:51:18 +0800] 0:0:0:0:0:0:0:1 "GET null null" 400 (0 ms)请求都没进来就被过滤掉了。 我在js里面对参数进行了编码 window.location.href='?p=ware&d=ware-register-query&agentName='+encodeURI($(".agent").val());在这里对参数进行了编码 ,发现并没有用。百思不得其解。 其实因为我们是 html+php+java架构的,请求是经过php处理后再发送到java后台的,在js中编码过的参数,发送到php处理的时候,会自动解码: var_dump(check_merchant_query.'?agentName='.$_GET['agentName']); // 打印拼接的url$req = new httpRequest('get',check_merchant_query.'?agentName='.$_GET['agentName'],null,function($result){return $result;});这里打印出来的结果是已经解码过的,当时没注意到,只是觉得这个url没错,因此多花了许多时间。。以为在PHP里面构造的http请求的get参数是已经编码过的,所以我将接下来的时间都放在了如何设置tomcat对特殊字符放行上。。 如果是正常的html+java,那么上面的编码就是没问题的,只是分析的时候忘记了还要经过php处理。。 最后在Php中对参数进行编码就可以啦 $req = new httpRequest('get',check_merchant_query.'?agentName='.urlencode($_GET['agentName']),null,function($result){return $result;});至于postman为什么能够输入中文参数就能够直接访问tomcat呢?是因为postman就相当于一个浏览器,在发送请求的时候已经对参数进行了编码操作啦

June 19, 2019 · 1 min · jiezi

Tomcat-7-类加载器是如何实现的

Tomcat 7 类加载器是如何实现的XML分析器和Java在安全管理器下运行高级配置概观 概述与许多服务器应用程序一样,Tomcat安装了各种类加载器(即实现的类java.lang.ClassLoader),以允许容器的不同部分和容器上运行的Web应用程序访问可用类和资源的不同存储库。此机制用于提供Servlet规范2.4版中定义的功能 - 特别是9.4和9.6节。 在Java环境中,类加载器排列在父子树中。通常,当要求类加载器加载特定的类或资源时,它首先将请求委托给父类加载器,然后仅在父类加载器找不到所请求的类或资源时查找它自己的存储库。 。请注意,Web应用程序类加载器的模型与此略有不同,如下所述,但主要原则是相同的。 当Tomcat启动时,它会创建一组类加载器,这些加载器被组织成以下父子关系,其中父类加载器位于子类加载器之上: Bootstrap | System | Common / \ Webapp1 Webapp2 ...这些类加载器的特征,包括它们可见的类和资源的来源,将在下一节中详细讨论。 类加载器定义如上图所示,Tomcat在初始化时创建以下类加载器: Bootstrap - 此类加载器包含Java虚拟机提供的基本运行时类,以及System Extensions目录($JAVA_HOME/jre/lib/ext)中存在的JAR文件中的任何类。 注意:一些JVM可能将其实现为多个类加载器,或者它可能根本不可见(作为类加载器)。System - 此类加载器通常从CLASSPATH环境变量的内容初始化。Tomcat内部类和Web应用程序都可以看到所有这些类。但是,标准的Tomcat启动脚本($CATALINA_HOME/bin/catalina.sh或 %CATALINA_HOME%bincatalina.bat)完全忽略CLASSPATH环境变量本身的内容,而是从以下存储库构建System类加载器:$CATALINA_HOME/bin/bootstrap.jar - 包含用于初始化 Tomcat 服务器的main() 方法,以及它依赖的类加载器实现类。$CATALINA_BASE/bin/tomcat-juli.jar 或 $CATALINA_HOME/bin/tomcat-juli.jar - 记录实现类。其中包括java.util.loggingAPI 的增强类 ,称为Tomcat JULI,以及Tomcat内部使用的Apache Commons Logging库的软件包重命名副本。有关详细信息,请参阅日志记录如果tomcat-juli.jar是出现在 $CATALINA_BASE/bin 中,它被用来代替 $CATALINA_HOME/bin 中的那一个。它在某些日志记录配置中很有用 $CATALINA_HOME/bin/commons-daemon.jar - 来自Apache Commons Daemon项目的类。这个JAR文件不存在于CLASSPATH 由脚本catalina.bat|.sh 构建,但是从bootstrap.jar的清单文件中引用。 Common - 此类加载器包含对Tomcat内部类和所有Web应用程序都可见的其他类。通常情况下,应用类应该不 放在这里。此类由common.loader加载器搜索的位置$CATALINA_BASE/conf/catalina.properties 中的属性定义。默认设置将按列出的顺序搜索以下位置: 解压缩的类和资源 $CATALINA_BASE/libJAR文件 $CATALINA_BASE/lib解压缩的类和资源 $CATALINA_HOME/libJAR文件 $CATALINA_HOME/lib默认情况下,这包括以下内容: annotations-api.jar - JavaEE注释类。catalina.jar - Tomcat的Catalina servlet容器部分的实现。catalina-ant.jar - Tomcat Catalina Ant任务。catalina-ha.jar - 高可用性包。catalina-tribes.jar - 群组通信包。ecj - * .jar - Eclipse JDT Java编译器。el-api.jar - EL 2.2 API。jasper.jar - Tomcat Jasper JSP编译器和运行时。jasper-el.jar - Tomcat Jasper EL实现。jsp-api.jar - JSP 2.2 API。servlet-api.jar - Servlet 3.0 API。tomcat-api.jar - Tomcat定义的几个接口。tomcat-coyote.jar - Tomcat连接器和实用程序类。tomcat-dbcp.jar - 基于包重命名的Apache Commons Pool和Apache Commons DBCP 1.x的数据库连接池实现。tomcat-i18n - **。jar - 包含其他语言资源包的可选JAR。由于默认捆绑包也包含在每个单独的JAR中,因此如果不需要消息的国际化,则可以安全地删除它们。tomcat-jdbc.jar - 另一种数据库连接池实现,称为Tomcat JDBC池。有关详细信息,请参阅 文档tomcat-util.jar - Apache Tomcat的各种组件使用的公共类。tomcat7-websocket.jar - WebSocket 1.1实现websocket-api.jar - WebSocket 1.1 APIWebappX - 为部署在单个Tomcat实例中的每个Web应用程序创建一个类加载器。/WEB-INF/classesWeb应用程序目录中的所有解压缩的类和资源,以及Web应用程序/WEB-INF/lib目录下的JAR文件中的类和资源,都对此Web应用程序可见,但对其他应用程序不可见。 ...

June 13, 2019 · 1 min · jiezi

NginxTomcat动静分离

动静分离动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路动静分离简单的概括是:动态文件与静态文件的分离。 软件开发中,有些请求是需要后台处理的(如:.jsp,.do等等),有些请求是不需要经过后台处理的(如:css、html、jpg、js等等文件),这些不需要经过后台处理的文件称为静态文件,否则动态文件。因此我们后台处理忽略静态文件。这会有人又说那我后台忽略静态文件不就完了吗。当然这是可以的,但是这样后台的请求次数就明显增多了。在我们对资源的响应速度有要求的时候,我们应该使用这种动静分离的策略去解决。动静分离将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。这里我们将静态资源放到nginx中,动态资源转发到tomcat服务器中。 ###静态资源访问 server { listen 80; server_name static.tmp.com; location /static/imgs { root data/tmp; index index.html index.htm; } } ###动态资源访问 server { listen 80; server_name www.tmp.com; location / { proxy_pass http://127.0.0.1:8080; index index.html index.htm; } }

June 12, 2019 · 1 min · jiezi

如何通过maven往tomcat部署war包

tomcat的manager提供了可以部署项目的接口,可以使用maven的tomcat插件通过一个命令方便的进行部署、重新部署等操作。 修改~/.m2/setting.xml新增一个<server> <server> <id>tomcat8</id> <username>tomcat</username> <password>tomcat</password></server>加入tomcat插件<!-- 加到pom.xml中 --><build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <url>http://localhost:8080/manager/text</url> <server>tomcat8</server> <!-- 这里是项目的context path --> <path>/</path> </configuration> </plugin> </plugins></build>使用方法先启动tomcat,并确定manager页面可用并且可成功登陆 部署到tomcatmvn tomcat7:deploymvn tomcat7:deploy-only重新部署mvn tomcat7:redeploymvn tomcat7:redeploy-only取消部署mvn tomcat7:undeploy

June 9, 2019 · 1 min · jiezi

从开源小白到-Apache-Member我的成长之路

我们走过的每一步路,都会留下印记,越坚实,越清晰。 近日,Apache 软件基金会(ASF)官方 Blog 宣布全球新增 40 位 Apache Member,张乎兴有幸成为其中一位。 目前,全球共有771位 ASF Member,中国仅13位。本文将分享作者从0基础的开源小白,一路走来的感触,希望把期间的经历分享出来,让更多的人看到,世界开源舞台的中国力量。只要有持续的付出,总会有所收获。 初次参与开源2014年,我加入阿里巴巴中间件团队,开始接手集团应用容器的维护工作。当时集团的应用容器绝大部分都是基于 JBoss,老旧且无人维护,另外有一小部分跑在 Jetty 和 Tomcat 之上,当时中间件团队维护了 Tomcat 的一个私有分支,最大的目标就是要统一所有集团的应用容器为 Tomcat。而在那之前,我从未接触过 Tomcat 的开发和运维,对我来说,挑战很大。然而,更大的挑战来自于团队大 leader 提出的,在当时看来几乎是无法实现的目标:成为 Apache Tomcat 的 committer。 要知道,作为 Apache 的核心项目之一,Tomcat 自1999年发布第一版以来,一直是开源届和 Apache 基金会的明星项目,至今仍然在应用容器领域市场占有率保持第一,历经20年发展,依旧热度不减。Tomcat 历经这么多年的发展,却从未出现过一位来自中国的 committer。而我们小团队只有4个人,根本没有任何开源的经验,也完全不知道从何做起。团队 leader 问我们,谁愿意挑战一下的时候,我也没有多想,就承担了下来。 就这样,我开始了自己的 Apache 开源之旅。 说实话,一开始,自己并没有太多的思路,于是开始反复浏览 Tomcat 官网,希望能够查询到一些有用的信息。所有的 Apache 项目几乎都会有新用户指南,介绍如何参与到此开源项目当中,Tomcat也不例外。很快,我从修复 bug 开始,第一个 patch 是修复一个Websocket 测试用例失败的问题,修复该问题涉及到了对代码的一些重构。 还记得当时提交之前我非常谨慎,和 leader 一起反复讨论了很多次,终于形成了一个比较满意的方案。提交给 Tomcat 社区之后,很快,社区便有了响应,并合并了我提交的补丁。第一次提交便获得了认可,心里很开心,紧张的情绪也缓解了。看到 Tomcat 的 release note 里面出现了自己的名字,真的非常开心。 Apache Roadshow China2015年10月,我有幸在北京参加了 Apache Roadshow China 的活动,算是第一次和Apache 基金会有了亲密接触。在大会上,亲眼目睹了时任 Apache 基金会主席的 Brett Porter、Apache 基金会副总裁 Niclas Hedhman 等大牛们的演讲,以及在 Panel Disussion 里面,和他们,以及几位来自中国的 Apache 成员,一起探讨社区领导的开发流程等。 ...

June 3, 2019 · 2 min · jiezi

聊聊Tomcat的架构设计

微信公众号「后端进阶」,专注后端技术分享:Java/Golang/WEB框架/分布式中间件/服务治理 老司机倾囊相授,带你一路进阶,来不及解释了快上车!Tomcat 是 Java WEB 开发接触最多的 Servlet 容器,但它不仅仅是一个 Servlet 容器,它还是一个 WEB 应用服务器,在微服务架构体系下,为了降低部署成本,减少资源的开销,追求的是轻量化与稳定,而 Tomcat 是一个轻量级应用服务器,自然被很多开发人员所接受。 Tomcat 里面藏着很多值得我们每个 Java WEB 开发者学习的知识,可以这么说,当你弄懂了 Tomcat 的设计原理,Java WEB 开发对你来说已经没有什么秘密可言了。本篇文章主要是跟大家聊聊 Tomcat 的内部架构体系,让大家对 Tomcat 有个整体的认知。 前面我也说了,Tomcat 的本质其实就是一个 WEB 服务器 + 一个 Servlet 容器,那么它必然需要处理网络的连接与 Servlet 的管理,因此,Tomcat 设计了两个核心组件来实现这两个功能,分别是连接器和容器,连接器用来处理外部网络连接,容器用来处理内部 Servlet,我用一张图来表示它们的关系: 一个 Tomcat 代表一个 Server 服务器,一个 Server 服务器可以包含多个 Service 服务,Tomcat 默认的 Service 服务是 Catalina,而一个 Service 服务可以包含多个连接器,因为 Tomcat 支持多种网络协议,包括 HTTP/1.1、HTTP/2、AJP 等等,一个 Service 服务还会包括一个容器,容器外部会有一层 Engine 引擎所包裹,负责与处理连接器的请求与响应,连接器与容器之间通过 ServletRequest 和 ServletResponse 对象进行交流。 ...

May 31, 2019 · 3 min · jiezi

JavaWeb学生选课ServletJSPJDBC

运行结果: 数据库的2个表:course表 student表 ps:一定要build path导入数据库用的jar包,以及在在lib文件夹中导入数据库jar包 文件目录结构: 具体代码:index.jsp 首页 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>欢迎进入选课系统</title></head><body><center><h2>欢迎进入选课 系统</h2><a href="login.jsp">学生登录</a><a href="regist.jsp">学生注册</a><a href="admin.jsp">管理员登录</a></center></body></html>login.jsp 学生登录 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>学生登录</title></head> <body style="text-align: center;"> <br><br> <h3>学生登录</h3> <form action="LoginServlet" method="post"> 学号:<input type="text" name="stuno"> <br><br> 密码:<input type="password" name="stupassowrd"> <br><br> <input type="submit" value="登录" name="submit"> <a href="regist.jsp" role="button">注册</a> <a href="index.jsp">返回</a> </form> </body></html>regist.jsp 学生注册 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>注册</title> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"></head><body><h2 align=center>注册页面</h2> <center> <form action="RegisterServlet" method="post" > <table border="1"> <tr> <td>学号:</td> <td><input name="userNo"></td> </tr> <tr> <td>姓名:</td> <td><input name="userName"></td> </tr> <tr> <td>密码:</td> <td><input name="password" type="password"></td> </tr> <tr> <td>院系:</td> <td><input name="major"></td> </tr> <tr> <td>年级:</td> <td><input name="grade"></td> </tr> <tr> <td>班级:</td> <td><input name="sclass"></td> </tr> <tr align="center"> <td colspan="2"><input type="submit" value="提交注册"><input type = "reset" value = "重置"></td> </tr> </table> </form> 您有账号?<a href="login.jsp"><front color="GREEN" >点击直接登录</front></a> </center> </body></html>studentIndex.jsp 学生选课主页 ...

May 30, 2019 · 17 min · jiezi

hibernatevalidator版本问题引发的tomcat7下项目启动失败

线上环境jdk8tomcat7.0.90 报错java.lang.NoClassDefFoundError:javax/el/ELManager原因版本引入包:hibernate-validator:6.0.16.Final版本,使用邮箱验证注解功能,则需要依赖加载对应javax/el/ELManager。因线上使用tomcat版本为tomcat7.0.90,在其CATALINA_HOME/lib目录下的el-api.jar的版本为2.2版本,无类javax/el/ELManager。(tomcat8中,el-api.jar包升级为3.0版本,不会找不到类)因此启动失败。 解决将hibernate-validator版本降到5.4.3.Final版本,去除引用校验邮箱的注解特性,该用业务代码处理 为什么线下未发现呢?因为线下环境使用的tomcat版本为8.5.32版本,与线上未统一。当然这也是不合理的点

May 28, 2019 · 1 min · jiezi

CENTOS-7安装步骤apachetomcat8534windowsx86

1,全文可能比较详细(就是比较琐碎)(对新手比较友好)全部命令在行末!2,首先克隆一个VM虚拟机。以下这个操作出错率较高,防止不必要损失。建议在虚拟机上动手操作! 选择完整克隆: 克隆OK 3,如果忘记root密码。我在其他博客有写解决方法!确保你的CONNECT是连接状态!(不用PUTTY就无碍啦) 开始操作: 4,从WINDOWS桌面,直接拖拽apache-tomcat-8.5.34-windows-x86.zip到VM虚拟机。 如图: 我们先找到他的位置: find / -name 'apache-tomcat-8.5.34-windows-x86*' 进入此目录,pwd记录下路径:[root@localhost Desktop]# pwd/home/yuanlai/Desktop5,将其拷贝到/usr/local/下。(记得将被拷贝的那个删除掉。节省磁盘空间。)已经删除:6,解压缩:unzip apache-tomcat-8.5.34-windows-x86.zip 同样记得删除: 最好重命名一下:改为tomcat。这样比较好找。 7,cd bin 不是 cd /bin 这两个完全不同的! 一个.bat用于WINDOWS。 另外一个.sh用于Linux。 查看权限:没有执行权限。 加上就好啦: chmod 777 startup.sh 但是,又出现: Catalina方便记忆: 改完之后就OK啦! 8,连接测试:默认是8080.要想在WINDOWS访问。要开放一下这个8080端口。![在这里插入图片描述](https://img-blog.csdn.net/20181004142057221?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mjg1OTI4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) firewall-cmd --zone=public --add-port=8080/tcp --permanent在防火墙中新增8080端口 firewall-cmd --reload重新加载防火墙,这样开启的8080端口才生效 ![在这里插入图片描述](https://img-blog.csdn.net/20181004142110401?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mjg1OTI4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 9,启用:![在这里插入图片描述](https://img-blog.csdn.net/20181004142117355?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mjg1OTI4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 然而开启不了。还要再写个文件。/etc/init.d/tomcat。/etc/init.d:存放着很多的服务程序(当然都是可执行的)init最初的意思。![在这里插入图片描述](https://img-blog.csdn.net/20181004142128763?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mjg1OTI4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 复制到具有很多服务的/etc/init.d里面。Vim编辑即可。如图,写入:# chkconfig: 112 63 37description: tomcat server init scriptSource Function Library. /etc/init.d/functions JAVA_HOME=/usr/local/jdk/CATALINA_HOME=/usr/local/tomcat 编辑完成后,再次编辑打开查看一下确认。赋予权限。 10, OK! 11,history 命令仅供参考。我也不知道哪个是必不可少的。 History可以查看最近500条命令! [root@localhost bin]# history 1 find / -name 'apache-tomcat-8.5.34-windows-x86*' 18 cd /home/yuanlai/Desktop/ 19 pwd 22 cd /usr/local/ 23 ls 27 cp /home/yuanlai/Desktop/apache-tomcat-8.5.34-windows-x86.zip ./ 28 ls 29 cd /home/yuanlai/Desktop/ 30 rm apache-tomcat-8.5.34-windows-x86.zip apache-tomcat-8.5.34-windows-x86.zip 31 ls 32 cd /usr/local/ 33 ls 34 unzip apache-tomcat-8.5.34-windows-x86.zip 35 ls 36 rm apache-tomcat-8.5.34-windows-x86.zip 37 ls 38 mv apache-tomcat-8.5.34 tomcat 39 ls 43 cd tomcat/ 44 ls 5 7 cd bin 61 ls 62 ./startup.sh 63 ls -al 64 chmod 777 startup.sh 65 ls -al 67 ./startup.sh 69 chmod 777 catalina.sh 70 ./startup.sh 72 firewall-cmd --zone=public --add-port=8080/tcp --permanent 73 firewall-cmd --reload 76 service tomcat start 77 cp -p /usr/local/tomcat/bin/catalina.sh /etc/init.d/tomcat 78 vim /etc/init.d/tomcat 79 chmod 755 /etc/init.d/tomcat 80 chkconfig --add tomcat 81 chkconfig tomcat on 82 service tomcat start 83 service tomcat restart 84 service tomcat stop 85 service tomcat start ...

May 22, 2019 · 1 min · jiezi

Centos7安装jdk18tomcat8mysql8

安装前准备JDK依赖包:yum install glibc.i686MYSQL依赖包:yum -y install libaio.so.1 libgcc_s.so.1 libstdc++.so.6 yum update libstdc++-4.4.7-4.el6.x86_64yum -y install libncurses.so.5 libtinfo.so.5安装java JDK1.下载下载jDK1.8到本地 安装mysql安装tomcat

May 21, 2019 · 1 min · jiezi

tomcat项目原始部署

javaWeb简单项目部署1.部署并启动 tomcat 服务器. 1). 解压 apache-tomcat-6.0.16.zip 到一个非中文目录下 2). 配置一个环境变量. java_home(指向 JDK 安装的根目录) 或 jre_home 3). 通过双击 apache-tomcat-6.0.16bin 目录下的 startup.bat, 启动服务器 4). 可以在浏览器中输入 localhost:8080 来检验 Tomcat 安装是否正确. 5). 若已经启动了一个 Tomcat 应用, 若再启动同一个 Tomcat 应用, 会抛出异常: java.net.BindException: Address already in use: JVM_Bind:8080因为端口已经被占用了. 2.Tomcat: 开源的 Servlet 容器. 3.可以通过修改 server.xml 文件中的配置信息来修改 Tomcat 服务器的端口号:<Connector port=“8989” protocol=“HTTP/1.1” connectionTimeout=“20000” redirectPort=“8443” />4.为了可以在任意目录下启动 Tomcat 服务器4.1 把 D:apache-tomcat-6.0.16bin 添加到 path 下添加成功后, 若在任意目录下通过 startup 启动 Tomcat 服务器, 会有提示:The CATALINA_HOME environment variable is not defined correctlyThis environment variable is needed to run this program即: 要求设置 CATALINA_HOME 这个环境变量。 5.设置 CATALINA_HOME 环境变量:5.1 通过阅读 startup.bat 批处理文件, 可知 CATALINA_HOME 环境变量下有一个 bin 目录,而 bin 目录又有一个 catalina.bat 文件, 由此可知 CATALINA_HOME 指向的应该是 Tomcat 安装的根目录。于是把 Tomcat 的根目录设为 CATALINA_HOME 环境变量. 此时即可以在 任意 目录下通过 startup.bat、shutdown.bat 启动、关闭 Tomcat 服务器. 6.继续阅读 startup.bat 文件, 发现启动 tomcat 服务器的是 catalina.bat 文件。在命令行窗口直接输入 catalina, 提示如下: commands: debug Start Catalina in a debugger debug -security Debug Catalina with a security manager jpda start Start Catalina under JPDA debugger run Start Catalina in the current window run -security Start in the current window with security manager start Start Catalina in a separate window start -security Start in a separate window with security manager stop Stop Catalina version What version of tomcat are you running?catalina 命令有如上的可选参数.run: 在 catalina 同一个命令行窗口下启动服务器. start: 开启一个新窗口启动服务器stop: 关闭服务器.7.第一个 WEB 应用程序: 开发, 并部署到 Tomcat 服务器下运行1). 在 Eclipse 新建一个 Java Project2). 在 Java 项目下创建 WEB 开发的目录结构 -WebContent -WEB-INF -classes (编译后的 class 文件必须放在该目录下.) -lib -web.xml (从 apache-tomcat-6.0.16\webapps\docs\WEB-INF 中复制过来, 可以不做修改) html 页面 JSP 页面 图片…3). 在 src 下新建一个 Person 类package com.atguigu.test;public class Person { public String getPersonInfo(){ return “person info…”; }}4). 手工的 Person 类对应的 class 文件(含包)复制到 classes 目录下可以通过修改默认的输出目录达到自动把编译好的 class 放到 classes 目录下:5). 在 WebContent 目录下新建一个 JSP 文件:<%@page import=“com.atguigu.test.Person”%><%@ page language=“java” contentType=“text/html; charset=ISO-8859-1” pageEncoding=“ISO-8859-1”%><% Person person = new Person(); System.out.print(person.getPersonInfo()); %>6). 把 WebContent 目录复制到 Tomcat 的 webapps 目录下, 并改名为: helloworld7). 在浏览器的地址栏中输入: http://localhost:8989/helloworld/hello.jsp 即可看到命令行的打印信息8). 配置任意目录下的Web应用程序: 在 conf 目录下依次创建 catalinalocalhost 目录,然后在 localhost 目录下为 test 这个Web应用程序建立 test.xml 文件,编辑这个文件输入以下内容:<?xml version=“1.0” encoding=“UTF-8”?><Context docBase=“E:\Java\Source\atguigu\java-1\firstWebApp\WebContent” reloadable=“true”/> ...

April 18, 2019 · 2 min · jiezi

JVM的基本概念与维护调优

一、概念数据类型java虚拟机中,数据类型可以分为两类:基本类型引用类型基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。基本类型包括:byte,short,int,long,float,double,Boolean。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址位置。引用类型包括:类的类型,接口类型和数组。堆与栈栈是运行时单位堆是存储单位栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;堆解决的是数据存储问题,即数据怎么放,放在哪。在java中一个线程就会相应有一个线程栈与之对应,这点很容易理解,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈。而堆则是所有线程共享的。栈因为是运行单位,因此里面存储的信息都是跟当前线程相关的信息。包括局部变量、程序运行状态、方法返回值等;而堆只负责存储对象信息。为什么要把堆和栈区分出来呢?栈中不是也可以存储数据吗?从software设计角度来看,栈代表了处理逻辑,而堆代表了数据。这样分开,使得处理逻辑更为清晰。分而治之思想。这种隔离,模块化思想在软件设计的方面都有体现。堆与栈的分离,使得堆中的内容可以被多个栈共享(也可以理解为多个线程访问同一个对象)。这种共享的收益很多的。一方面这种共享提供了一种有效的数据交互方式(共享内存),另一方面,堆中的共享常量和缓存可以被所有栈访问,节省了空间。栈因为运行时的需要,比如保存系统运行上下文,需要进行地址段的划分。由于栈只能向上增长,因此就会限制住栈存储内容的能力。而堆不同,堆中的对象是可以根据需要动态增长的,因此栈和堆的拆分,使得动态增长成为可能,相应栈中只需要记录堆中的一个地址即可。面向对象就是堆和栈的完美结合。其实,面向对象方式的程序与以前结构化的程序在执行上没有任何区别。但是,面向对象的引入,使得对待问题的思考方式发生了改变,而更接近于自然方式的思考。当我们把对象拆开,你会发现,对象的属性其实就是数据,存放在堆中;而对象的行为(方法),就是运行逻辑,放在栈中。我们在编写对象的时候,其实即编写了数据结构,也编写了处理数据的逻辑。不得不承认,面向对象的设计,确实完美。堆中存什么?栈中存什么?堆中存对象栈中存最基本数据类型和堆中对象的引用一个对象的大小是不可估计的,或者说是可估计的,或者说是可以动态改变的,但在栈中,一个对象只对应4byte的引用。为什么不把基本类型放堆中呢?因为其占用的空间一般是18个字节,需要空间比较少,而且因为是基本类型,所以不会出现动态增长的情况,长度固定,因此栈中存储就够了,如果把他存在堆中是没什么意义的。可以说是浪费。基本类型和对象的引用都是在存放在栈中,而且都是几个字节的一个数,因此在程序运行时,他们的处理方式是统一的。但是基本类型、对象引用和对象本身就是有所区别的,因为一个栈中的数据一个是堆中的数据。最常见的一个问题就是,java中参数传递时的问题。java中的参数传递时传值呢?还是传引用?不要试图与C进行类比,java中没有指针的概念程序运行永远都是在栈中进行的,因而参数传递时,只存在传递基本类型和对象引用的问题。不会直接传对象本身。java在方法调用传递参数时,因为没有指针,所以它都是进行传值调用。因此,很多书里面都说java是进行传值调用,这点没有问题,而且也简化了C中的复杂性。但是传引用的错觉是如何造成的呢?在运行栈中,基本类型和引用的处理都是一样的,都是传值,所以,如果是传引用的方法调用,也同时可以理解为“传引用值”的传值调用,即引用的处理跟基本类型是完全不一样的。但是当进入被调用方法时,被传递的这个引用的值,被程序解释到堆中的对象,这个时候才对应到真正的对象,如果此时进行修改,修改的是引用对应的对象,而不是引用本身,即修改的是堆中的数据。所以这个修改是可以保持的了。对象,是由基本类型组成的。可以把一个对象看做成一棵树,对象的属性如果还是对象,则还是一棵树(即非叶子节点),基本类型则为树的叶子节点。程序参数传递时,被传递的值本身都是不能进行修改的,但是,如果这个值是一个非叶子节点(即一个对象引用),则可以修改这个节点下面的所有内容。堆和栈中,栈是程序运行最根本的东西。程序运行可以没有堆,但不能没有栈。而堆是为栈进行数据存储服务,说白了堆就是一块共享的内存。不过,正是因为堆和栈的分离的思想,才使得java的垃圾回收成为可能。java中,栈的大小通过-Xss来设置,当栈中存储的数据比较多时,需要适当调大这个值,否则会出现java.lang.StackOverflowError异常。常见的出现这个异常的是无法返回的递归,因为此时栈中保存的信息都是方法返回的记录点。引用类型对象引用类型分为:强引用软引用弱引用和虚引用强引用:就是我们一般声明对象是时虚拟机生成的引用,强引用环境下,垃圾回收时需要严格判断当前对象是否被强引用,如果被强引用,则不会被垃圾回收软引用:软引用一般被做为缓存来使用。与强引用的区别是,软引用在垃圾回收时,虚拟机会根据当前系统的剩余内存来决定是否对软引用进行回收。如果剩余内存比较紧张,则虚拟机会回收软引用所引用的空间:如果剩余内存相对富裕,则不会进行回收。换句话说,虚拟机在发生OutOfMemory时,肯定是没有软引用存在的。弱引用:弱引用与软引用类似,都是作为缓存来使用。但与软引用不同,弱引用在进行垃圾回收时,是一定会被回收掉的,因此其生命周期只存在于一个垃圾回收周期内。强引用是我们系统一般在使用时都是用的强引用。而“软引用”和“弱引用”比较少见。他们一般被作为缓存使用,而且一般是在内存大小比较受限的情况下做为缓存。因为如果内存足够大的话,可以直接使用强引用作为缓存即可,同时可控性更高。因而,他们常见的是被使用在桌面应用系统的缓存。二、基本垃圾回收算法此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段:第一阶段从根节点开始标记所有被引用对象。第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-请除”的碎片问题,同时也避免了“复制”算法的空间问题。按系统线程分串行收集:串行收集使用单线程处理所有垃圾回收工作,因为无需多线程交互,实现容易而且效率比较高,但是,其局限性也比较明显,即无法使用多处理器的优势,所以此收集通过单处理器机器。当然,此收集器也可以用在小数据量(100M左右)情况下的多处理器机机器上。并行收集:并行收集使用多线程处理垃圾回收工作,因而速度快,效率高。而且理论上CPU数目越多,越能体现出并行收集器的优势。并发收集:相对于串行收集和并行收集而言,前面两个在进行垃圾回收工作时,需要暂时停止整个运行环境,而只有垃圾回收程序在运行,因此,系统在垃圾回收时会有明显的暂停,而且暂停时间会因为堆越大而越长。三、垃圾回收面临的问题如何区分垃圾?上面说到的“引用计数”法,通过统计控制生成对象和删除对象时的引用数来判断。垃圾回收程序收集计数为0的对象即可。但是这种方法无法解决循环引用。所以,后来实现的垃圾判断算法中,都是从程序运行的根节点出发,遍历整个对象引用,查找存活的对象。那么在这种方式的实现中,垃圾回收从哪儿开始的呢?从哪儿开始查找哪些对象是正在被当前系统使用的,上面分析的堆和栈的区别,其中栈是真正进行程序执行地方,所以要获取哪些对象正在被使用,则需要从Java栈开始。同时,一个栈是与一个线程对应的,因此,如果有多个线程的话,则必须对这些线程对应的所有的栈进行检查。同时,除了栈外,还有系统运行时的寄存器等,也是存储程序运行数据的。这样,以栈或寄存器中的引用为起点,我们可以找到堆中的对象,又从这些对象找到对堆中其他对象的引用,这种引用逐步扩展,最终以null引用或者基本类型结束,这样就形成了一颗以Java栈中引用所对应的对象为根节点的一颗对象树,如果栈中有多个引用,则最终会形成多颗对象树。在这些对象树上的对象,都是当前系统运行所需要的对象,不能被垃圾回收。而其他剩余对象,则可以视为无法被引用到的对象,可以被当做垃圾进行回收。因此,垃圾回收的起点是一些根对象(java栈,静态变量,寄存器)。而最简单的Java栈就是Java程序执行的main函数。这种回收方式,也是上面提到的“标记-请除”的回收方式。如何处理碎片?由于不同Java对象存活时间是不一定的,因此,在程序运行一段时间以后,如果不进行内存整理,就会出现零散的内存碎片。碎片最直接的问题就是会导致无法分配大块的内存空间,以及程序运行效率降低。所以,在上面提到的基本垃圾回收算法中,“复制”方式和“标记-整理”方式,都可以解决碎片的问题.如何解决同时存在的对象创建和对象回收问题?垃圾回收线程是回收内存的,而程序运行线程则是消耗(或分配)内存的,一个回收内存,一个分配内存,从这点看,两者是矛盾的。因此,在现有的垃圾回收方式中,要进行垃圾回收前,一般都需要暂停整个应用(即暂停内存的分配),然后进行垃圾回收,回收完成后再继续应用。这种实现方式是最直接,而且最有效的解决一者矛盾的方式。但是这种方式有一个很明显的弊端,就是当堆空间持续增大时,垃圾回收的时间也将会相应的持续增大,对应应用暂停的时间也会相应的增大。一些对相应时间要求很高的应用,比如最大暂停时间要求是几百毫秒,那么当堆空间大于几个G时,就很有可能超过这个限制,在这种情况下,垃圾收将会成为系统运行的一个瓶颈。为解决这种矛盾,有了并发垃圾回收算法,使用这种算法,垃圾回收线程与程序运行线程同时运行。在这种方式下,解决了暂停的问题,但是因为需要在新生成对象的同时又要回收对象,算法复杂性会大大增加,系统的处理能力也会相应降低,同时,“碎片”问题将会比较难解决。四、分代垃圾回收详述为什么要分代?分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http 请求中的Session对象、线程、Socket连接,这类对象跟业务直接挂钩,因此生命的周期比较长,但是还有一些对象,主要是程序运行过程中生成的临时变量,这些对象生命周期会比较短,比如:String对象,由于其不变类的特性,系统会产生大量的这些对象,有些对象甚至只用一次即可回收。试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,花费时间相对会长,同时,因为每次回收都需要遍历所有存活对象,但实际上,对于生命周期长的对象而言,这种遍历是没有效果的,因为可能进行了很多次通历,但是他们依旧存在因此,分代垃圾回收采用分治的思想,进行代的划分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。虚拟机中的共划分为三个代:年轻代(Young Generation)年老代(Old Generation)持久代(Permanent Generation)其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。年轻代:所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区:1个Eden区,2个Survivor区(一般而言)。大部分对象在Eden区中生成,当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor区也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor区过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,Survivor区是可以配置多个的,这样可以增加对象在年轻代中存在的时间,减少被放到老代的可能。年老代:在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中,因此,可认为年老代中存放的都是一些生命周期较长的对象。持久代:用于存放静态文件,java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类,持久代大小通过-XX:MaxPermSize=<N>进行设置。什么情况下触发垃圾回收?由于对像进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GCFull GcScavenge GC:一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发 Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区,然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会须繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。Full GC:对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个堆进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于Full GC的调节。有如下原因可能导致Full GC:年老代(Tenured)被写满持久代(Perm)被写满System.gc()被显示调用上一次GC之后Heap的个域分配策略动态变化选择合适的垃圾收集算法串行收集器:用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器。当然,此收集器也可以用在小数据量(100M左右)情况下的多处理器机器上。可以使用-XX:+UseSerialGC打开。并行收集器:对年轻代进行井行垃圾回收,因此可以减少垃圾回收时间。一般在多线程多处理器机器上使用。使用-XX:+UseParallelGC打开,并行收集器在J2SE5.0第六6更新上引入,在JavaSE6.0中进行了增强,可以对年老代进行并行收集,如果年老代不使用并发收集的话,默认是使用单线程进行垃圾回收,因此会制约扩展能力。使用XX:+UseParalelOldGC打开并行收集器收集年老代,使用-XX:ParalelGCThreads=<N>设置并行垃圾回收的线程数。此收集器可以进行如下配置:最大垃圾回收暂停:指定垃圾回的时的最长暂停时间,通讨-XX:MaxGCPauseMilis=<N>指定。<N>为毫秒,如果指定了此值的话,堆大小和垃圾回收相关参数会进行调整以达到指定值。设定此值可能会减少应用的吞吐量。吞吐量:吞吐量为垃圾回收时间与非垃圾回收时间的比值,通过-XX:GCTimeRatio=<N>来设定,公式为1/(1+N)。例如,-XX:GCTimeRatio=19时,表示5%的时间用于垃圾回收。默认情况为99,即1%的时间用于垃圾回收。并发收集器:可以保证大部分工作都并发进行(应用不停止),垃圾回收只暂停很少的时间,此收集器适合对响应时间要求比较高的中、大规模的应用。使用-XX:+UseConcMarkSweepGC打开。并发收集器主要减少年老代的暂停时间,他在应用不停止的情况下使用独立的垃圾回收线程,跟踪可达对象。在每个年老代垃圾回收周期中,在收集初期并发收集器会对整个应用进行简短的暂停,在收集中还会再暂停一次。第二次暂停会比第一次稍长,在此过程中多个线程同时进行垃圾回收工作。并发收集器使用处理器短暂的停顿时间。在一个N个处理器的系统上,并发收集部分使用KWN个可用处理器进行回收,一般情况下1<=K<=N/4。在只有一个处理器的主机上使用并发收集器,设置为incrementalmode 模式也可获得较短的停顿时间。浮动垃圾:由于在应用运行的同时进行垃圾回收,所以有些垃圾可能在拉圾回收进行完成时产生,这样就造成了“Floating Garbage”,这些垃圾需要在下次拉圾回收周期时才能回收掉,所以,并发收集器一般需要20%的预留空间用于这些浮动垃圾。Concurrent Mode Failure:并发收集器在应用运行时进行收集,所以需要保证堆在垃圾回收的这段时间有足够的空间供程序使用,否则,垃圾回收还未完成,堆空间先满了。这种情况下将会发生“并发模式失败”,此时整个应用将会暂停,进行垃极回收。启动并发收集器:因为并发收集在应用运行时进行收集,所以必须保证收集完成之前足够的内存空间供程序使用,否则会出现“Concurrent Mode Failure”.通过设置XX:CMSInitiatingOccupancyFraction=<N>指定还有多少剩余堆时开始执行并发收集。小结串行处理器:适用情况:数据量比较小(100M左右):单处理器下并且对响应时间无要求的应用。缺点:只能用于小型应用。并行处理器:适用情况:“对吞吐量有高要求”,多CPU、对应用响应时间花装求的中、大型应用。举例:后台处理、科学计算。缺点:垃圾收集过程中应用响应时间可能加长。并发处理器:适用情况:“对响应时间有高要求”,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。五、常见配置汇总堆设置-Xms:初始堆大。-Xmx:最大堆大小。初始堆大小与最大堆大小尽量小于4G。两值不相等的话,内存地址中会计算会对应用程序产生影响,索性设为相等。-XX:NewSize=n:设置年轻代大小。-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代的1/4。-XX:SurvivorRatio=n:年轻代中Eden区与连个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年代的1/5。-XX:MaxPermSize=n:设置持久代大小。收集器设置-XX:+UseSerialGC:设置串行。-XX:+UseParallelGC:设置并行。-XX:+UseParalledlOldGC:设置并行年老代。-XX:+UseConcMarkSweepGC:设置并发。垃圾回收统计信息-XX:+PrintGC:输出GC日志。-XX:+PrintGCDetails:输出GC的详细日志。-XX:+PrintGCTimeStamps:输出GC的时间戳(以基准时间的形式)。-Xloggc:filename:日志文件的输出路径。并发收集器设置-XX:ParallelGCThreads=n:设置并行收集器收集使用的CPU数。并行收集线程数。-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间。-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式1/(1+n)。-XX:+CMSlncrementalMode:设置为增量模式。适用于单CPU情况。-XX:ParallelGCThreads=n:设置并发收集器年期代收集方式,使用的CPU数。并行收集线程。六、典型配置举例堆大小设置JVM中最大堆大小有三方面限制:相关操作系统的数据模型(32bit还是64bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统下,一般限制在1.5G2G;64位操作系统对内存无限制。在Windows Server 2003系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。典型设置:java -Xms3550m -Xmx3550m -Xmn2G -Xss128k-Xmx3550m:设置JVM最大可用堆内存。-Xms3550m:设置JVM初始堆内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。-Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小+年老代大小+持久代大小。持久代一般固定在64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置整个堆的3/8-Xss128k:设置每个线程的堆栈大小。JDK5以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256k。具应用的线程所需内存大小进行调整。在相同的物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,阀值在3000-5000左右。java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermmSize=16m -XX:MaxTenuringThreshold=0-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久刘代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor 区占整个年轻代的1/6。-XX:MaxPermSize=16m:设置持久代大小为16m。-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入老年代。对于年老代比较多的应用,可以提高效率。如果将此值设为一个较大值,则年轻对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加年轻代即被回收的概论。回收器选择JVM给了三种选择:串行收集器、并行收集器、并发收集器,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器。默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数,JDK5.0以后,JVM会根据当前系统配置进行判断。吞吐量优先的并行收集器如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等。典型配置:java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParalelGC -XX:ParallelGCThreads=20-XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。年轻代使用并行收集,而年老代仍旧使用串行收集。-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParalleloldGC-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集:JDK6.0支持对年老代并行收集。java-Xmx3550m-Xms3550m-Xmn2g-Xss128k-XX:+UseParallelGC -XX:MaxGCPauseMilis=100-XX:MaxGCPauseMilis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整大小,以满足此值java -Xmx 3550m -Xms 3550m -Xmn2g -Xss128k -XX:+UseParalleGC -XX:MaxGCPauseMilis=100 -XX:+UseAdaptiveSizePolicy-XX:+UseParalleGC:设置此项后,并行收集器会自动选择年轻代区大小和相应的Surivor区比例,已达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器,一直打开。响应时间优先的并发收集器如上文所述,并发收集器主要保证系统的响应时间,减少垃圾收集时间的停顿时间。适用于应用服务器、电信领域等。典型配置:java-Xmx3550m-Xms3550m-Xmn2g-Xss128k-XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC-XX:+UseConcMarkSweepGC:设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。XX:+UseParNewGC:设置年轻代为并行收集,可与CMS收集同时使用JDK5.0以上JVM会根据系统配置自行设置,所以无需再设置此值。java-Xmx3550m-Xms3550m-Xmn2g-Xss128k-XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection-XX:CMSFulGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。-XX:CMSCompactAtFullCollection:打开对年老代的压缩。可能会影响性能,但是可以消除碎片。七、调优总结年轻代大小选择响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择);在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。年老代大小选择响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式:如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:并发垃圾收集信息持久代并发收集次数传统GC信息花在年轻代和年老代回收上的时间比例减少年轻代和年老代花费的时间,一般会提高应用的效率吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。较小堆引起的碎片问题因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩。八、常见异常内存泄漏检查内存泄漏一般可以理解为系统资源(各方面的资源,堆、栈、线程等)在错误使用的情况下,导致使用完毕的资源无法回收(或没有回收),从而导致新的资源分配请求无法完成,引起系统错误。内存泄漏对系统危害比较大,因为他可以直接导致系统的崩溃。需要区别一下,内存泄漏和系统超负荷两者是有区别的,虽然可能导致的最终果是一样的。内存泄漏是用完的资源没有回收引起错误,而系统超负荷则是系统确实没有那么多资源可以分配了(其他的资源都在使用)。年老代堆空间被占满异常:java.lang.OutOfMemoryError.Java heap space说明:堆大小与使用堆成锯齿状。这是最典型的内存泄漏方式,简单说就是所有堆空间都被无法回收的垃圾对象占满,虚拟机无法再在分配新空间。锯齿状每一次形成三角的顶点而下降为回收点,所有谷底部分表示是一次垃圾回收后剩余的内存。连接所有谷底的点,可以发现一条由底到高的线,这说明,随时间的推移,系统的堆空间被不断占满,最终会占满整个堆空间。因此可以初步认为系统内部可能有内存泄漏。(上面的图仅供示例,在实际情况下收集数据的时间需要更长,比如几个小时或者几天)解决:通过jmap把可用对象打出来,这种方式解决起来也比较容易,一般就是根据垃极回收前后情况对比,同时根据对象引用情况(常见的集合对象引用)分析,基本都可以找到泄漏点。持久代被占满异常:java.lang.OutOfMemoryError:PermGen space说明:Perm空间被占满。无法为新的cdass分配存储空间而引发的异常。这个异常以前是没有的,但是在Java反射大量使用的今天这个异常比较常见了。主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。更可怕的是,不同的classLoader即便使用了相同的类,但是都会对其进行加载,相当于同一个东西,如果有N个classLoader那么他将会被加载N次。因此,某些情况下,这个问题基本视为无解。当然,存在大量classLoader和大量反射类的情况其实也不多。解决:1.-XX:MaxPermSize=16m。2.换用JDK。比如JRocket。堆栈溢出异常:java.lang.StackOverflowError说明:一般就是递归没返回,或者循环调用造成.线程堆栈满异常:Fatal:Stack size too small说明:java中一个线程的空间大小是有限制的。JDK5.0以后这个值是1M。与这个线程相关的数据会保存在其中。但是当线程空间满了以后,将会出现上面异常。解决:增加线程栈大小。-Xss2m。但这个配置无法解决根本问题,还要看代码部分是否有造成泄漏的部分。系统内存被占满异常:java.lang.OutOfMemoryError:unable to create new.native thread说明:这个异常是由于操作系统没有足够的资源来产生这个线程造成的。系统创建线程时,除了要在Java堆中分配内存外,操作系统本身也需要分配资源来创建线程。因此,当线程数量大到一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,就出现这个异常了。分配给Java虚拟机的内存越多,系统剩余的资源就越少,因此,当系统内存固定时,分配给Java虚拟机的内存越多,那么,系统总共能够产生的线程也就越少,两者成反比的关系。同时,可以通过修改-Xss来减少分配给单个线程的空间,也可以增加系统总共内生产的线程数。解决:1.重新设计系统减少线程数量。2.线程数量不能减少的情况下,通过-Xss减小单个线程大小。以便能生产更多的线程。九、JVM调优工具JVM可视化监控工具:Jconsole:jdk自带,功能简单,但是可以在系统有一定负荷的的情况下使用。对垃圾回收算法有很详细的跟踪。Jprofile:商业软件,需要付费。功能强大。VisualVM:JDK自带,功能强大,与JProfile类似。推荐。JVM调优监控工具jstat(性能分析)https://www.jianshu.com/p/213710fb9e40jstack(分析线程情况)https://jingyan.baidu.com/article/4f34706e3ec075e387b56df2.htmlhttp://www.importnew.com/23601.htmljmap(堆栈dump)https://www.cnblogs.com/kongzhongqijing/articles/3621163.htmljinfo(jvm信息情况)https://www.jianshu.com/p/ece32dacce64jps(jvm进程情况)https://www.jianshu.com/p/d39b2e208e72JVM调优工具转载至一些优质的博客,可以详细学习参考文档整理于JVM视频学习课程,感谢提供教育视频的IT人才们,整理分享还未接触到这层知识的人们,也收藏个人学习。 ...

April 18, 2019 · 1 min · jiezi

使用idea创建SpringBoot项目

首先我们打开idea。这里我是用的版本是2019.1.这边项目名选默认的就可以了,项目地址个人建议用一个专门的文件夹进行存放。

April 18, 2019 · 1 min · jiezi

nginx配置多个tomcat负载均衡

nginx, tomcat的下载安装就不多说了nginx(1.15.x): http://nginx.org/en/download....tomcat(8.5.x): https://tomcat.apache.org/dow...1. 配置多个tomcat这里介绍是一台服务器配置多个tomcat,更改端口的方法。如果是多台服务器各配一个tomcat,那可以直接使用默认的配置。1.1 复制多个复制多个tomcat。假定下载解压后的tomcat为apache-tomcat-8.5.8,建议复制并更改名称为.apache-tomcat-8.5.8-8081apache-tomcat-8.5.8-8082apache-tomcat-8.5.8-80831.2 配置端口修改每个tomcat里面的配置文件。如apache-tomcat-8.5.8-8081/conf/server.xml,修改 3个地方 的端口号8443端口,若有需要再进行修改。apache-tomcat-8.5.8-8081<?xml version=“1.0” encoding=“UTF-8”?><!– 1 默认8005改成8006 –><Server port=“8006” shutdown=“SHUTDOWN”> <!– 2 Http默认8080 改成9081 –> <Connector port=“9081” protocol=“HTTP/1.1” connectionTimeout=“20000” redirectPort=“8443” /> <!– 3 AJP默认8009 改成8010 –> <Connector port=“8010” protocol=“AJP/1.3” redirectPort=“8443” /> apache-tomcat-8.5.8-8082<?xml version=“1.0” encoding=“UTF-8”?><!– 1 默认8005改成8007 –><Server port=“8007” shutdown=“SHUTDOWN”> <!– 2 Http默认8080 改成9082 –> <Connector port=“9082” protocol=“HTTP/1.1” connectionTimeout=“20000” redirectPort=“8443” /> <!– 3 AJP默认8009 改成8011 –> <Connector port=“8011” protocol=“AJP/1.3” redirectPort=“8443” /> apache-tomcat-8.5.8-8083<?xml version=“1.0” encoding=“UTF-8”?><!– 1 默认8005改成8008 –><Server port=“8008” shutdown=“SHUTDOWN”> <!– 2 Http默认8080 改成9083 –> <Connector port=“9083” protocol=“HTTP/1.1” connectionTimeout=“20000” redirectPort=“8443” /> <!– 3 AJP默认8009 改成8011 –> <Connector port=“8011” protocol=“AJP/1.3” redirectPort=“8443” /> 1.3运行3个tomcat# 进入tomcat目录cd /相对路径/apache-tomcat-8.5.8-8081# 运行tomcat/bin/startup.sh其他2个tomcat同理运行。运行成功后,可以访问浏览器2. 配置Nginx ...

April 11, 2019 · 1 min · jiezi

Tomcat 上的项目参数传递问题

修改 Tomcat 中的 catalina.sh 文件部署在 Tomcat 上面的 Spring Boot 项目,在某些情况下,我们可能会修改配置文件中的参数,这样应该怎么做呢?传统的方式是直接在本地修改,然后打包部署,但是这种方式太麻烦了,要是我只是修改了很小的一个参数,都要重新打包,得不偿失。于是稍微研究了一下,找到了两种方式,来向项目传递参数。第一种方式就是修改 Tomcat 中的 catalina.sh 这个文件,例如我在 Spring Boot 项目的配置文件中自定义了一个配置,如下:#application.yml 中的配置project: args: ${info}然后修改 Tomcat 下面的 bin/catalina.sh 文件,添加一个 JAVA_OPTS 属性,指定 info 的值:需要注意的是,如果指定的是一个包含了空格的字符串,要用单引号包围,例如上面的 -Dinfo="‘I am roseduan’" 。这种方式出现的问题:但是,这种传递参数的方式是不太方便的,举个例子:在本地环境,启动项目的时候,该怎么去设置这个 info 的值呢?如果不指定肯定是要报错的。只不过我也找到了一种方式,在 IntelliJ IDEA 中,我们可以在 Run/Debug Configuration 中设置参数:这样就能够在本地启动启动项目了。但是还存在一个问题,就是使用 maven 打包的时候,也会报错,仍然是找不到 info 的值,这时候我们也可以使用mvn 打包时来传递参数,命令是:mvn package -Dinfo=“I am roseduan” 。部署到 tomcat 中后,我们就可以使用修改 catalina.sh 中的内容来指定 info 的值。2. 修改 Tomcat 中的 contxt.xml 文件上面的这种方式,其实应该少量的配置是可以的,但是如果我们需要指定大量的配置,并且每个配置的内容都很长,这样就不是非常方便了,因为每次打包,都需要写很多参数。所以第二种方式,修改 context.xml 文件,就十分的有优势了。我们不需要修改任务本地的配置,也不用配置任何参数,还是上面那个例子,假如 application.yml 中有如下配置:#application.yml 中的配置project: args: I am roseduan并且这个配置是已经打包在了 Tomcat 上了,我们可以在 Tomcat 中的 conf/context.xml 中添加一些配置来修改这个参数的值:name 是配置参数在 application.yml 文件中的路径,Type 对应的是 Java 类型,value 是具体的值。这样的话,我们可以直接在这个文件中指定很多的值了,这样修改还有一个好处便是,不用重启 Tomcat ,配置即时生效 (只不过需要多试几次,或者稍微等一会)。最后,需要注意一点:配置在 application.yml 中的自定义配置,最好是小写,或者使用 - 分隔,不然有可能 context.xml 中的配置不会生效。

April 10, 2019 · 1 min · jiezi

SpringBoot 仿抖音短视频小程序开发(一)

一、项目简介模仿抖音做的一个短视频微信小程序,用SpringBoot搭建小程序后台,用SSM框架搭建短视频后台管理系统,小程序后台通过分布式zookeeper监听节点自动下载或删除短视频后台管理系统上传的视频。二、环境参数核心框架:SpringBoot、SSM数据库:MySQL、 HikariCP数据源、MyBatis逆向工程中间件:zookeeper,redis,swagger2前端框架: Bootstrap + Jquery、jqGrid分页组件音频处理: FFmpeg开发工具: IDEA 热门技术点 三、项目展示 功能: 小程序【注册登录注销】、【上传头像】、【上传作品】、【查看所有/单个短视频】、【点赞】、【关注某用户】、【短视频和BGM合并】、【留言评论回复】、【举报】、【下载短视频到手机】 四、数据库设计CREATE TABLE bgm ( id varchar(64) NOT NULL, author varchar(255) NOT NULL, name varchar(255) NOT NULL, path varchar(255) NOT NULL COMMENT ‘播放地址’, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE comments ( id varchar(20) NOT NULL, father_comment_id varchar(20) DEFAULT NULL, to_user_id varchar(20) DEFAULT NULL, video_id varchar(20) NOT NULL COMMENT ‘视频id’, from_user_id varchar(20) NOT NULL COMMENT ‘留言者,评论的用户id’, comment text NOT NULL COMMENT ‘评论内容’, create_time datetime NOT NULL, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘课程评论表’;CREATE TABLE search_records ( id varchar(64) NOT NULL, content varchar(255) NOT NULL COMMENT ‘搜索的内容’, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘视频搜索的记录表’;CREATE TABLE vuser ( id varchar(64) NOT NULL, username varchar(20) NOT NULL COMMENT ‘用户名’, password varchar(64) NOT NULL COMMENT ‘密码’, face_image varchar(255) DEFAULT NULL COMMENT ‘我的头像,如果没有默认给一张’, nickname varchar(20) NOT NULL COMMENT ‘昵称’, fans_counts int(11) DEFAULT ‘0’ COMMENT ‘我的粉丝数量’, follow_counts int(11) DEFAULT ‘0’ COMMENT ‘我关注的人总数’, receive_like_counts int(11) DEFAULT ‘0’ COMMENT ‘我接受到的赞美/收藏 的数量’, PRIMARY KEY (id), UNIQUE KEY id (id), UNIQUE KEY username (username)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE users_fans ( id varchar(64) NOT NULL, user_id varchar(64) NOT NULL COMMENT ‘用户’, fan_id varchar(64) NOT NULL COMMENT ‘粉丝’, PRIMARY KEY (id), UNIQUE KEY user_id (user_id,fan_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘用户粉丝关联关系表’;CREATE TABLE users_like_videos ( id varchar(64) NOT NULL, user_id varchar(64) NOT NULL COMMENT ‘用户’, video_id varchar(64) NOT NULL COMMENT ‘视频’, PRIMARY KEY (id), UNIQUE KEY user_video_rel (user_id,video_id) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘用户喜欢的/赞过的视频’;CREATE TABLE users_report ( id varchar(64) NOT NULL, deal_user_id varchar(64) NOT NULL COMMENT ‘被举报用户id’, deal_video_id varchar(64) NOT NULL, title varchar(128) NOT NULL COMMENT ‘类型标题,让用户选择,详情见 枚举’, content varchar(255) DEFAULT NULL COMMENT ‘内容’, userid varchar(64) NOT NULL COMMENT ‘举报人的id’, create_date datetime NOT NULL COMMENT ‘举报时间’, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘举报用户表’;CREATE TABLE videos ( id varchar(64) NOT NULL, user_id varchar(64) NOT NULL COMMENT ‘发布者id’, audio_id varchar(64) DEFAULT NULL COMMENT ‘用户使用音频的信息’, video_desc varchar(128) DEFAULT NULL COMMENT ‘视频描述’, video_path varchar(255) NOT NULL COMMENT ‘视频存放的路径’, video_seconds float(6,2) DEFAULT NULL COMMENT ‘视频秒数’, video_width int(6) DEFAULT NULL COMMENT ‘视频宽度’, video_height int(6) DEFAULT NULL COMMENT ‘视频高度’, cover_path varchar(255) DEFAULT NULL COMMENT ‘视频封面图’, like_counts bigint(20) NOT NULL DEFAULT ‘0’ COMMENT ‘喜欢/赞美的数量’, status int(1) NOT NULL COMMENT ‘视频状态:\r\n1、发布成功\r\n2、禁止播放,管理员操作’, create_time datetime NOT NULL COMMENT ‘创建时间’, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘视频信息表’; ...

April 7, 2019 · 2 min · jiezi

linux 安装tomcat

下载tomcattomcat将安装包拷贝到 /usr/local下解压安装包 tar -xvf apache-tomcat-8.5.39.tar.gz 删除安装包rm -rf apache-tomcat-8.5.39.tar.gz启动1) cd apache-tomcat-8.5.39/bin/ 2) .startup.sh如果不能访问, 开放默认端口8080firewall-cmd –zone=public –add-port=8080/tcp –permanent#重启systemctl restart firewalld.service#重新加载载firewall-cmd –reload访问http://192.168.102.128:8080/,出现下面页面说明成功

April 5, 2019 · 1 min · jiezi

springboot登陆页面图片验证码简单的web项目

写在前面前段时间大家都说最近大环境不好,好多公司在裁员,换工作的话不推荐轻易的裸辞,但是我想说的是我所在的公司好流弊,有做不完的业务需求,还有就是招不完的人……最近我也是比较繁忙,但是还是要抽一点时间来进行自我复盘和记录,最近也写一个简单的小功能,就是登陆界面的图片验证码功能环境:Tomcat9、Jdk1.81 生成验证码的工具类public class RandomValidateCodeUtil { public static final String RANDOMCODEKEY= “RANDOMVALIDATECODEKEY”;//放到session中的key private String randString = “0123456789”;//随机产生只有数字的字符串 private String //private String randString = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;//随机产生只有字母的字符串 //private String randString = “0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ”;//随机产生数字与字母组合的字符串 private int width = 95;// 图片宽 private int height = 25;// 图片高 private int lineSize = 40;// 干扰线数量 private int stringNum = 4;// 随机产生字符数量 private static final Logger logger = LoggerFactory.getLogger(RandomValidateCodeUtil.class); private Random random = new Random(); /** * 获得字体 / private Font getFont() { return new Font(“Fixedsys”, Font.CENTER_BASELINE, 18); } /* * 获得颜色 / private Color getRandColor(int fc, int bc) { if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc - 16); int g = fc + random.nextInt(bc - fc - 14); int b = fc + random.nextInt(bc - fc - 18); return new Color(r, g, b); } /* * 生成随机图片 / public void getRandcode(HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(); // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作 g.fillRect(0, 0, width, height);//图片大小 g.setFont(new Font(“Times New Roman”, Font.ROMAN_BASELINE, 18));//字体大小 g.setColor(getRandColor(110, 133));//字体颜色 // 绘制干扰线 for (int i = 0; i <= lineSize; i++) { drowLine(g); } // 绘制随机字符 String randomString = “”; for (int i = 1; i <= stringNum; i++) { randomString = drowString(g, randomString, i); } logger.info(randomString); //将生成的随机字符串保存到session中 session.removeAttribute(RANDOMCODEKEY); session.setAttribute(RANDOMCODEKEY, randomString); g.dispose(); try { // 将内存中的图片通过流动形式输出到客户端 ImageIO.write(image, “JPEG”, response.getOutputStream()); } catch (Exception e) { logger.error(“将内存中的图片通过流动形式输出到客户端失败>>>> “, e); } } /* * 绘制字符串 / private String drowString(Graphics g, String randomString, int i) { g.setFont(getFont()); g.setColor(new Color(random.nextInt(101), random.nextInt(111), random .nextInt(121))); String rand = String.valueOf(getRandomString(random.nextInt(randString .length()))); randomString += rand; g.translate(random.nextInt(3), random.nextInt(3)); g.drawString(rand, 13 * i, 16); return randomString; } /* * 绘制干扰线 / private void drowLine(Graphics g) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(13); int yl = random.nextInt(15); g.drawLine(x, y, x + xl, y + yl); } /* * 获取随机的字符 / public String getRandomString(int num) { return String.valueOf(randString.charAt(num)); }}这个类不用动,可以直接拿来用2 页面代码<!–html/bady代码–><div > <div > <div > <input type=“tel” id=“verify_input” placeholder=“请输入验证码” maxlength=“4”> </div> </div> <div > <a href=“javascript:void(0);” title=“点击更换验证码”> <img id=“imgVerify” src=“login/getVerify” alt=“更换验证码” height=“36” width=“170” onclick=“getVerify(this);"> </a> </div> <input type=“button” onclick=“aVerify()” value=“提交”></div></body><!–js中的代码–><script type=“text/javascript” src=”./js/jquery.min.js”></script><script> //获取验证码 /function getVerify(obj){ obj.src = “login/getVerify?"+Math.random();//原生js方式 }/ //获取验证码 function getVerify() { // $("#imgCode”).on(“click”, function() { $("#imgVerify”).attr(“src”, ’login/getVerify?’ + Math.random());//jquery方式 // }); } function aVerify(){ var value =$("#verify_input").val(); // alert(value); $.ajax({ async: false, type: ‘post’, url: ’login/checkVerify’, dataType: “json”, data: { verifyInput: value }, success: function (result) { if (result) { alert(“success!”); } else { alert(“failed!”); } // window.location.reload(); getVerify(); } }); }</script>注意:这里有2种获取验证码图片的方法3 获取code和验证code的类@RestController@RequestMapping("/login")public class Picverifyaction { private final static Logger logger = LoggerFactory.getLogger(Picverifyaction.class); /* * 生成验证码 / @RequestMapping(value = “/getVerify”) public void getVerify(HttpServletRequest request, HttpServletResponse response) { try { response.setContentType(“image/jpeg”);//设置相应类型,告诉浏览器输出的内容为图片 response.setHeader(“Pragma”, “No-cache”);//设置响应头信息,告诉浏览器不要缓存此内容 response.setHeader(“Cache-Control”, “no-cache”); response.setDateHeader(“Expire”, 0); RandomValidateCodeUtil randomValidateCode = new RandomValidateCodeUtil(); randomValidateCode.getRandcode(request, response);//输出验证码图片方法 } catch (Exception e) { logger.error(“获取验证码失败>>>> “, e); } } /* * 校验验证码 */ @RequestMapping(value = “/checkVerify”, method = RequestMethod.POST,headers = “Accept=application/json”) public boolean checkVerify(@RequestParam String verifyInput, HttpSession session) { try{ //从session中获取随机数 String inputStr = verifyInput; String random = (String) session.getAttribute(“RANDOMVALIDATECODEKEY”); if (random == null) { return false; } if (random.equals(inputStr)) { return true; } else { return false; } }catch (Exception e){ logger.error(“验证码校验失败”, e); return false; } }}4 效果图镇楼5 源码当然上面代码只是核心部分,如果有问题可去github自行下载 charmsongo如果有什么更好的方法欢迎留言参考:https://blog.csdn.net/Colton_… ...

April 2, 2019 · 3 min · jiezi

JavaWeb 项目与系统时间相差 8 个小时的问题

写在前面今天记录分享一个排查部署到 Linux 上的 web 项目执行的时间和本地系统时间相差 8 小时的问题环境:redhat 6.5考虑有规律的时间差可能和时区不同有关1 查看 Linux 系统时间和时区[root@localhost ~]# date2019年 03月 31日 星期日 16:00:32 CST[root@localhost ~]# date -RSun, 31 Mar 2019 16:00:44 +0800[root@localhost ~]# date +"%Z %z"CST +0800从这里可以确定,系统的时间和时区正常(北京时间,也就是东八区),时区详情请看这里2 查看 jvm 时间和时区2.1 先在 Linux 上某个目录执行 javac ,看 javac 命令是否可用,出现如下显示就可以(中间部分已省略)[root@localhost test]# javac用法: javac <options> <source files>其中, 可能的选项包括: -g 生成所有调试信息 -g:none 不生成任何调试信息 -g:{lines,vars,source} 只生成某些调试信息 …… -X 输出非标准选项的提要 -J<标记> 直接将 <标记> 传递给运行时系统 -Werror 出现警告时终止编译 @<文件名> 从文件读取选项和文件名2.2 编写测试程序import java.util.TimeZone;import java.util.Date;public class time { public static void main(String[] args) { System.out.println(“当前时间:"+new Date()); System.out.println(“当前默认时区:"+TimeZone.getDefault()); }}2.3 编译执行[root@localhost test]# javac time.java [root@localhost test]# ll总用量 8-rw-r–r– 1 root root 780 3月 31 16:02 time.class-rw-r–r– 1 root root 239 3月 31 16:00 time.java[root@localhost test]# java time当前时间:Sun Mar 31 08:02:34 CTM 2019当前默认时区:sun.util.calendar.ZoneInfo[id=“GTM”,offset=28800000,dstSavings=0,useDaylight=false,transitions=29,lastRule=null]这里有导其他的包,如果以上命令不好使,则使用如下命令 (中间的点 . 是当前目录的意思)[root@localhost test]# javac -d . time.java[root@localhost test]# ll总用量 8-rw-r–r– 1 root root 780 3月 31 16:03 time.class-rw-r–r– 1 root root 239 3月 31 11:00 time.java[root@localhost test]# java -cp . time当前时间:Sun Mar 31 08:02:40 CST 2019当前默认时区:sun.util.calendar.ZoneInfo[id=“GTM”,offset=28800000,dstSavings=0,useDaylight=false,transitions=29,lastRule=null]这里显然 jvm 的时间比系统的时间早了 8 个小时,且是格林威治的时区,所以这里修改 jvm 的时区即可,这里说下,网上查询说 jvm 的时区默认读取的是硬件时区,目录为 /etc/sysconfig/clock (详情),查看如下[root@localhost test]# cat /etc/sysconfig/clock ZONE=“Asia/Shanghai"与网上对比,这里没有下面这两行UTC=falseARC=false这里看有人说是没有设置 UTC=false 导致的问题,查看资料说 UTC 指定 BIOS 中保存的时间是否是 GMT/UTC 时间,true 表示 BIOS 里面保存的时间是 UTC 时间,false 表示 BIOS 里面保存的时间是本地时间。加上后有的机器还是不好使,如果是在 tomcat 下运行的项目,那就重启 tomcat 即可。如果还不好使,还有修改 tomcat 配置文件的方法,欢迎参考之前的文章:Tomcat修改日期的时区现在问题基本已解决,以上有些内容是客户现场出现的,所以现在记录时也是凭笔记和记忆回忆的,如有偏差也请不吝赐教。文章参考:https://blog.csdn.net/liqingh… ...

March 31, 2019 · 1 min · jiezi

Spring Boot 项目打成 war 包部署到 Tomcat

1要知道,Spring Boot 的项目,默认是打为 jar 包的,这时候问题就来了,如果我想打成 war 包部署到 Tomcat,该怎么做呢?又是在网上找了半天的答案,质量不太好,绕来绕去没说个明白。其实还算是非常简单的,只需要大概几个步骤就行了。2首先,在项目的 pom.xml 文件中做一些修改:添加 <packaging>war</packaging>排除掉 web 里面自带的 Tomcat,只需要在spring-boot-starter-web 这个依赖上添加如下内容:添加一个自己的 Tomcat ,在配置文件中,加入下面的依赖即可:添加一个插件,在文件的 build -> plugins 下面添加如下内容:其中需要注意一下,上面的 <warName>ROOT</warName> 表示的是打包之后,war 包的名称,当然你可以改成其他的名字,至于有什么区别,后面再说。3找到项目的启动类,让其继承一个类:SpringBootServletInitializer,并且覆盖 configure 方法,在方法中添加 return builder.sources(WarDemoApplication.class); ,当然,这里的 WarDemoApplication.class 是我的启动类名称,你只需要改成你自己的名称即可。4这时候,进行最后的打包操作了,执行命令 mvn packgae 即可,这时候,war 包就在项目的 target 文件夹下面,因为我是取名为 ROOT 的,所以 war 就叫做 ROOT.war。然后我们可以将 war 包复制到本地的或是远程的 Tomcat 的webapps 目录下面,需要提前删除 webapps 目录下面的所有文件 ,然后启动 Tomcat ,会自动解压这个 war 包。最后,该如何访问项目中的接口呢?如果我部署在了远程的 Tomcat 上面,例如 ip 是 192.168.66.128,那直接访问 192.168.66.128:8080/接口名 ,如果你的 war 包不是以 ROOT 命名,例如叫做 demo.war,那么你的访问路径就是 192.168.66.128:8080/demo/接口名,这也是我上面说到的区别。

March 28, 2019 · 1 min · jiezi

tomcat 实现http跳转https 【已解决】 启动时项目重复加载 【已解决】

问题一:tomcat 实现http跳转https 【已解决】今天做项目遇到一个需求就是直接通过域名访问项目时不带项目名称并且会自动跳转到https,但是tomcat默认的是8080和8443,然后windows系统对应的是80和443,所以很多人就理所当然的世界就将8080改成80,8443改成443,事实并非如此,我也百度了很多文章,但是大多都是抄来抄去问题非但没有解决还误导人,我也是被折腾了好久,废话不多说,直接进入主题:1.改端口:8080改成80,8443改成443。所有的redirectPort=“8443"都要改成redirectPort=“443"2.SSL证书自己可以到阿里云上面申请免费的 https://common-buy.aliyun.com…申请证书后按照此步骤配置:https://help.aliyun.com/docum…3.域名直接访问(不加项目名):修改<host></host>标签,demo为项目名称,域名地址以百度为例<Host name=“baidu.com” appBase=“webapps” unpackWARs=“true” autoDeploy=“true”> <Context docBase=“demo” path="/demo” reloadable=“true” crossContext=“true”/> <Valve className=“org.apache.catalina.valves.AccessLogValve” directory=“logs” prefix=“localhost_access_log.” suffix=".txt” pattern="%h %l %u %t &quot;%r&quot; %s %b" /></Host> 3.配置好后到tomcat的conf目录下面修改web.xml文件,在最下面添加标签 <security-constraint> <web-resource-collection> <web-resource-name>SSL</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>4.通过以上配置就可以实现baidu.com直接跳转成https://www.baidu.com5.如果存在端口被占用的情况需要自行解决了通过输入 netstat -ano|findstr 443可以查看443端口被哪个进程占用了,然后去任务管理器中找到对应的进程并结束掉如上图,443端口被5004进程占用,当然每个人的电脑不一样,之前这个端口是被进程4占用的,在任务管理器中查看这个进程,有的小伙伴发现在任务管理器不知道怎么找这个进程4,看下图结果发现这个进程是一个NT Kernel & System,具体什么意思我也不清楚,关键这是个系统进程我也不敢随意杀掉,然后百度找到一个方法:1、打开regedit2、找到HKEY_LOCAL_MACHINE目录3、找到System4、找到CurrentControlSet5、找到Services6、找到http7、右边栏:找到start8、打开,将3改为4,确定9、重启电脑,就解除了NT Kernel & System占用443端口问题二:tomcat启动时项目会重复加载可以借鉴这篇文章 https://blog.csdn.net/u012554102/article/details/50409452下面是我修改后的,我在tomcat根目录下新建一个webroot文件夹,然后 appBase=“webroot"path里面不填,docBase填写觉得路径,重启tomcat就没有重复加载项目了

March 26, 2019 · 1 min · jiezi