-
该模块可以为Nginx提供主动式嵌入式服务器健康检查的功能(同时支持四层和七层嵌入式服务器的健康检测)-...
2021-02-03 19:52:45ngx_healthcheck_module:用于上游服务器运行状况检查的nginx模块。 支持流和http上游。该模块可以为Nginx提供主动式嵌入式服务器健康检查的功能(同时支持四层和七层嵌入式服务器的健康检测) -
学习Spring Boot 嵌入式服务器
2018-11-12 02:07:07此功能会导致许多操作方法问题,包括如何更改嵌入式服务器以及如何配置嵌入式服务器。本节回答了这些问题。摘译自官方文档 使用其他Web服务器 许多Spring Boot启动器都包含默认的嵌入式容器。 对于servlet堆栈...嵌入式Web服务器
每个Spring Boot Web应用程序都包含一个嵌入式Web服务器。此功能会导致许多操作方法问题,包括如何更改嵌入式服务器以及如何配置嵌入式服务器。本节回答了这些问题。摘译自官方文档
使用其他Web服务器
许多Spring Boot启动器都包含默认的嵌入式容器。
- 对于servlet堆栈应用程序,
spring-boot-starter-web
包括Tomcatspring-boot-starter-tomcat
,但您可以使用spring-boot-starter-jetty
或spring-boot-starter-undertow
替代。 - 对于反应栈的应用,
spring-boot-starter-webflux
包括反应堆的Netty通过包括spring-boot-starter-reactor-netty
,但你可以使用spring-boot-starter-tomcat
,spring-boot-starter-jetty
或spring-boot-starter-undertow
代替。
切换到其他HTTP服务器时,除了包含所需的依赖项外,还需要排除默认依赖项。Spring Boot为HTTP服务器提供单独的启动程序,以帮助使此过程尽可能简单。
以下Maven示例显示如何排除Tomcat并为Spring MVC包含Jetty:
<properties> <servlet-api.version> 3.1.0 < /servlet-api.version> </ properties> <dependency> <groupId> org.springframework.boot </ groupId> <artifactId> spring-boot-starter-web </ artifactId> <exclusions> <! - 排除Tomcat依赖项 - > <exclusion> <groupId> org.springframework.boot </ groupId> <artifactId> spring-boot-starter-tomcat </ artifactId> </ exclusion > </ exclusions> </ dependency> <! - 使用Jetty - > <dependency> <groupId>org.springframework.boot </ groupId> <artifactId>spring-boot-starter-jetty </ artifactId> </ dependency>
Servlet API的版本已被覆盖,与Tomcat 9和Undertow 2.0不同,Jetty 9.4不支持Servlet 4.0。
以下Gradle示例显示如何排除Netty并包含Spring WebFlux的Undertow:
configurations { // exclude Reactor Netty compile.exclude module: 'spring-boot-starter-reactor-netty' } dependencies { compile 'org.springframework.boot:spring-boot-starter-webflux' // Use Undertow instead compile 'org.springframework.boot:spring-boot-starter-undertow' // ... }
spring-boot-starter-reactor-netty
需要使用WebClient
该类,因此即使您需要包含不同的HTTP服务器,也可能需要依赖Netty。禁用Web服务器
如果您的类路径包含启动Web服务器所需的位,Spring Boot将自动启动它。要禁用此行为,请
WebApplicationType
在您的配置中进行配置application.properties
,如以下示例所示:<span style="color:#333333"><span style="color:#000000"><span style="color:#7f007f">spring.main.web-application-type</span> = none</span></span>
更改HTTP端口
在独立应用程序中,主HTTP端口默认为
8080
但可以设置server.port
(例如,application.properties
作为System属性或作为System属性)。由于轻松绑定Environment
值,您还可以使用SERVER_PORT
(例如,作为OS环境变量)。要完全关闭HTTP端点但仍然创建一个
WebApplicationContext
,请使用server.port=-1
。(这样做有时对测试很有用。)有关更多详细信息,请参阅“ Spring Boot功能”部分中的“ 第28.4.4节 ” ,“自定义嵌入式Servlet容器”或
ServerProperties
源代码。使用随机未分配的HTTP端口
要扫描一个空闲端口(使用OS本机来防止冲突),请使用
server.port=0
。在运行时发现HTTP端口
您可以从日志输出或
ServletWebServerApplicationContext
通过其输出访问服务器正在运行的端口WebServer
。获得该功能并确保已初始化的最佳方法是添加一个@Bean
类型,ApplicationListener<ServletWebServerInitializedEvent>
并在发布时将容器拉出事件。使用的测试
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
还可以使用@LocalServerPort
注释将实际端口注入字段,如以下示例所示:@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) public class MyWebIntegrationTests { @Autowired ServletWebServerApplicationContext server; @LocalServerPort int port; // ... }
@LocalServerPort
是一个元注释@Value("${local.server.port}")
。不要尝试在常规应用程序中注入端口。正如我们刚刚看到的那样,只有在容器初始化之后才设置该值。与测试相反,应用程序代码回调会尽早处理(在值实际可用之前)。启用HTTP响应压缩
Jetty,Tomcat和Undertow支持HTTP响应压缩。它可以启用
application.properties
,如下所示:<span style="color:#333333"><span style="color:#000000"><span style="color:#7f007f">server.compression.enabled</span> = true</span></span>
默认情况下,响应必须至少为2048字节,才能执行压缩。您可以通过设置
server.compression.min-response-size
属性来配置此行为 。默认情况下,只有在内容类型为以下内容之一时才会压缩响应:
text/html
text/xml
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
您可以通过设置
server.compression.mime-types
属性来配置此行为。配置SSL
可以通过设置各种
server.ssl.*
属性以声明方式配置SSL ,通常在application.properties
或中application.yml
。以下示例显示了在以下位置设置SSL属性application.properties
:<span style="color:#333333"><span style="color:#000000"><span style="color:#7f007f">server.port</span> = 8443 <span style="color:#7f007f">server.ssl.key-store</span> = classpath:keystore.jks <span style="color:#7f007f">server.ssl.key-store-password</span> = secret <span style="color:#7f007f">server.ssl.key-password</span> = another-secret</span></span>
有关
Ssl
所有支持的属性的详细信息,请参阅。使用上述示例之类的配置意味着应用程序不再支持端口8080上的普通HTTP连接器.Spring Boot不支持HTTP连接器和HTTPS连接器的配置
application.properties
。如果要同时使用这两者,则需要以编程方式配置其中一个。我们建议使用application.properties
配置HTTPS,因为HTTP连接器更容易以编程方式配置。有关spring-boot-sample-tomcat-multi-connectors
示例,请参阅 示例项目。配置HTTP / 2
您可以使用
server.http2.enabled
配置属性在Spring Boot应用程序中启用HTTP / 2支持 。此支持取决于所选的Web服务器和应用程序环境,因为JDK8不支持该协议。Spring Boot不支持
h2c
HTTP / 2协议的明文版本。因此,您必须先配置SSL。带有Undertow的HTTP / 2
从Undertow 1.4.0+开始,支持HTTP / 2,对JDK8没有任何额外要求。
带Jetty的HTTP / 2
从Jetty 9.4.8开始,Conscrypt库也支持HTTP / 2 。要启用该支持,您的应用程序需要有两个额外的依赖项:
org.eclipse.jetty:jetty-alpn-conscrypt-server
和org.eclipse.jetty.http2:http2-server
。使用Tomcat的HTTP / 2
Spring Boot默认使用Tomcat 9.0.x,它在使用JDK 9或更高版本时支持HTTP / 2开箱即用。或者,如果
libtcnative
库及其依赖项安装在主机操作系统上,则可以在JDK 8上使用HTTP / 2 。必须使库文件夹(如果尚未可用)到JVM库路径。您可以使用诸如的JVM参数来完成此操作
-Djava.library.path=/usr/local/opt/tomcat-native/lib
。有关Tomcat官方文档的更多 信息。在没有该本机支持的情况下在JDK 8上启动Tomcat 9.0.x会记录以下错误:
ERROR 8787 --- [ main] o.a.coyote.http11.Http11NioProtocol : The upgrade handler [org.apache.coyote.http2.Http2Protocol] for [h2] only supports upgrade via ALPN but has been configured for the ["https-jsse-nio-8443"] connector that does not support ALPN.
此错误不是致命的,应用程序仍然以HTTP / 1.1 SSL支持启动。
带有Reactor Netty的HTTP / 2
在
spring-boot-webflux-starter
默认情况下,反应堆的Netty作为服务器使用。可以使用JDK 9或更高版本的JDK支持为Reactor Netty配置HTTP / 2。对于JDK 8环境或最佳运行时性能,此服务器还支持具有本机库的HTTP / 2。要启用它,您的应用程序需要具有其他依赖项。Spring Boot管理
io.netty:netty-tcnative-boringssl-static
“超级jar” 的版本 ,包含所有平台的本机库。开发人员可以选择使用分类器仅导入所需的依赖项(请参阅Netty官方文档)。配置Web服务器
通常,您应首先考虑使用众多可用配置键中的一个,并通过在您的
application.properties
(application.yml
或环境等)中添加新条目来自定义您的Web服务器,请参阅“ 第77.8节”,“发现外部属性的内置选项” “) 。该server.*
命名空间是非常有用的在这里,它包括命名空间一样server.tomcat.*
,server.jetty.*
和其他人,了解特定服务器的功能。请参阅附录A,常见应用程序属性列表。前面的部分涵盖了许多常见用例,例如压缩,SSL或HTTP / 2。但是,如果您的用例不存在配置密钥,则应该查看
WebServerFactoryCustomizer
。您可以声明这样的组件并获得与您选择的服务器工厂相关的访问权限:您应该为所选服务器(Tomcat,Jetty,Reactor Netty,Undertow)和所选Web堆栈(Servlet或Reactive)选择变体。以下示例适用于具有
spring-boot-starter-web
(Servlet堆栈)的Tomcat :@Component public class MyTomcatWebServerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory factory) { // customize the factory here } }
另外Spring Boot提供:
服务器 Servlet堆栈 反应堆栈 Tomcat的
TomcatServletWebServerFactory
TomcatReactiveWebServerFactory
码头
JettyServletWebServerFactory
JettyReactiveWebServerFactory
暗潮
UndertowServletWebServerFactory
UndertowReactiveWebServerFactory
反应堆
N / A
NettyReactiveWebServerFactory
一旦您有权访问a
WebServerFactory
,您通常可以向其添加定制器以配置特定部件,例如连接器,服务器资源或服务器本身 - 所有这些都使用特定于服务器的API。作为最后的手段,您还可以声明自己的
WebServerFactory
组件,它将覆盖Spring Boot提供的组件。在这种情况下,您不能再依赖server
命名空间中的配置属性。向应用程序添加Servlet,过滤器或监听器
在servlet堆栈应用程序中,即使用
spring-boot-starter-web
,有两种方法可以向应用程序添加Servlet
,Filter
和ServletContextListener
,以及Servlet API支持的其他侦听器:使用Spring Bean添加Servlet,过滤器或监听器
要添加
Servlet
,Filter
或servlet*Listener
使用的Spring bean,你必须提供一个@Bean
它的定义。当您想要注入配置或依赖项时,这样做非常有用。但是,您必须非常小心,它们不会导致太多其他bean的初始化,因为它们必须在应用程序生命周期的早期安装在容器中。(例如,让它们依赖于您的DataSource
或JPA配置并不是一个好主意。)您可以通过在首次使用而不是初始化时懒惰地初始化bean来解决此类限制。在的情况下
Filters
和Servlets
,还可以通过添加添加映射和初始化参数FilterRegistrationBean
或ServletRegistrationBean
代替或除了下面的部件。如果
dispatcherType
在过滤器注册中指定了no ,REQUEST
则使用。这与Servlet规范的默认调度程序类型一致。像任何其他Spring bean一样,您可以定义Servlet过滤器bean的顺序; 请务必检查“ 名为”将Servlet,过滤器和监听器注册为Spring Beans “部分。
禁用Servlet或过滤器的注册
正如前面所述,任何
Servlet
或Filter
豆与servlet容器自动注册。要禁用特定Filter
或Servlet
bean的注册,请为其创建注册Bean并将其标记为已禁用,如以下示例所示:@Bean public FilterRegistrationBean registration(MyFilter filter) { FilterRegistrationBean registration = new FilterRegistrationBean(filter); registration.setEnabled(false); return registration; }
使用类路径扫描添加Servlet,过滤器和监听器
@WebServlet
,@WebFilter
和带@WebListener
注释的类可以通过使用@Configuration
带有@ServletComponentScan
并指定包含要注册的组件的包的类来注释类来自动注册嵌入式servlet容器。默认情况下,@ServletComponentScan
从带注释的类的包中进行扫描。配置访问日志记录
可以通过各自的命名空间为Tomcat,Undertow和Jetty配置访问日志。
例如,以下设置使用自定义模式在Tomcat上记录访问权限 。
server.tomcat.basedir=my-tomcat server.tomcat.accesslog.enabled=true server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
日志的默认位置是
logs
相对于Tomcat基目录的目录。默认情况下,该logs
目录是临时目录,因此您可能希望修复Tomcat的基目录或使用日志的绝对路径。在前面的示例中,日志my-tomcat/logs
相对于应用程序的工作目录可用。可以以类似的方式配置Undertow的访问日志记录,如以下示例所示:
server.undertow.accesslog.enabled=true server.undertow.accesslog.pattern=%t %a "%r" %s (%D ms)
日志存储在
logs
相对于应用程序工作目录的目录中。您可以通过设置server.undertow.accesslog.directory
属性来自定义此位置 。最后,Jetty的访问日志记录也可以配置如下:
server.jetty.accesslog.enabled=true server.jetty.accesslog.filename=/var/log/jetty-access.log
默认情况下,日志会重定向到
System.err
。有关更多详细信息,请参阅 Jetty文档。在前端代理服务器后面运行
您的应用程序可能需要发送
302
重定向或使用绝对链接将内容呈现回自身。在代理后面运行时,调用者需要指向代理的链接,而不是托管应用程序的计算机的物理地址。通常,这种情况是通过与代理的合同来处理的,代理会添加标题以告诉后端如何构建自身链接。如果代理添加了常规
X-Forwarded-For
和X-Forwarded-Proto
头文件(大多数代理服务器都这样做),则应该正确呈现绝对链接,前提server.use-forward-headers
是true
在您的中设置application.properties
。如果您的应用程序在Cloud Foundry或Heroku中运行,则该
server.use-forward-headers
属性默认为true
。在所有其他情况下,默认为false
。自定义Tomcat的代理配置
如果使用Tomcat,还可以配置用于携带“转发”信息的标头名称,如以下示例所示:
server.tomcat.remote-ip-header=x-your-remote-ip-header server.tomcat.protocol-header=x-your-protocol-header
Tomcat还配置了一个默认正则表达式,该表达式匹配要信任的内部代理。默认情况下,IP地址中
10/8
,192.168/16
,169.254/16
和127/8
是值得信赖的。您可以通过添加条目来自定义阀门的配置application.properties
,如以下示例所示:server.tomcat.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
仅当使用属性文件进行配置时才需要双反斜杠。如果使用YAML,则单个反斜杠就足够了,并且值等于前面示例中显示的值
192\.168\.\d{1,3}\.\d{1,3}
。您可以通过将其设置
internal-proxies
为空来信任所有代理(但在生产中不这样做)。您可以
RemoteIpValve
通过关闭自动关闭(为此,设置server.use-forward-headers=false
)并在TomcatServletWebServerFactory
bean中添加新的阀门实例来完全控制Tomcat的配置。使用Tomcat启用多个连接器
可以添加
org.apache.catalina.connector.Connector
到TomcatServletWebServerFactory
,这可以允许多个连接器,包括HTTP和HTTPS连接器,显示在下面的例子:@Bean public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addAdditionalTomcatConnectors(createSslConnector()); return tomcat; } private Connector createSslConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); try { File keystore = new ClassPathResource("keystore").getFile(); File truststore = new ClassPathResource("keystore").getFile(); connector.setScheme("https"); connector.setSecure(true); connector.setPort(8443); protocol.setSSLEnabled(true); protocol.setKeystoreFile(keystore.getAbsolutePath()); protocol.setKeystorePass("changeit"); protocol.setTruststoreFile(truststore.getAbsolutePath()); protocol.setTruststorePass("changeit"); protocol.setKeyAlias("apitester"); return connector; } catch (IOException ex) { throw new IllegalStateException("can't access keystore: [" + "keystore" + "] or truststore: [" + "keystore" + "]", ex); } }
使用Tomcat的LegacyCookieProcessor
默认情况下,Spring Boot使用的嵌入式Tomcat不支持Cookie格式的“Version 0”,因此您可能会看到以下错误:
java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value
如果可能的话,您应该考虑将代码更新为仅存储符合以后Cookie规范的值。但是,如果您无法更改cookie的编写方式,则可以将Tomcat配置为使用
LegacyCookieProcessor
。要切换到LegacyCookieProcessor
,请使用WebServerFactoryCustomizer
添加a 的 beanTomcatContextCustomizer
,如以下示例所示:@Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() { return (factory) -> factory.addContextCustomizers( (context) -> context.setCookieProcessor(new LegacyCookieProcessor())); }
使用Undertow启用多个侦听器
一个添加
UndertowBuilderCustomizer
到UndertowServletWebServerFactory
与收听添加到Builder
,如图所示在下面的例子:@Bean public UndertowServletWebServerFactory servletWebServerFactory() { UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory(); factory.addBuilderCustomizers(new UndertowBuilderCustomizer() { @Override public void customize(Builder builder) { builder.addHttpListener(8080, "0.0.0.0"); } }); return factory; }
使用@ServerEndpoint创建WebSocket端点
如果要在使用
@ServerEndpoint
嵌入式容器的Spring Boot应用程序中使用,则必须声明一个ServerEndpointExporter
@Bean
,如以下示例所示:@Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }
前面示例中显示的
@ServerEndpoint
bean使用基础WebSocket容器注册任何带注释的bean。当部署到独立的servlet容器时,此角色由servlet容器初始化程序执行,并且ServerEndpointExporter
不需要该 bean。 - 对于servlet堆栈应用程序,
-
C语言实现程序连接数据库并实现简单的嵌入式服务器
2020-01-08 21:03:45我们可以直接访问数据库,当然我们也需要在程序中连接数据库。 接下来我将介绍嵌入式MySQL服务器库。 使用嵌入式 MySQL 服务器库, 能够在客户端应用程序中使用具备全部... 其结果是嵌入式服务器也是用 C/C++语言编...我们可以直接访问数据库,当然我们也需要在程序中连接数据库。
接下来我将介绍嵌入式MySQL服务器库。
使用嵌入式 MySQL 服务器库, 能够在客户端应用程序中使用具备全部特性的 MySQL 服务器。 主要优点在于,增加了速度,并使得嵌入式应用程序的管理更简单。嵌入式服务器库是以 MySQL 的客户端/ 服务器版本为基础的, 采用 C/C++语言编写。 其结果是嵌入式服务器也是用 C/C++语言编写的。 在其他语言中, 嵌入式服务器不可用。
具体简单步骤:1.获取或者初始化MYSQL结构
首先MYSQL是一个结构类型,该结构代表 1 个数据库连接的句柄。 几乎所有的 MySQL 函数均使用它。
函数介绍MYSQL *mysql_init(MYSQL *mysql) /* 分配或初始化与 mysql_real_connect()相适应的 MYSQL 对象。 如果 mysql 是 NULL 指针, 该函数将分配、 初始化、 并返回新对象。 否则, 将初始化对象, 并返回对象的地址。 如果 mysql_init()分配了新的对象, 当调用 mysql_close()来关闭连接时。 将释放该对象。 初始化的 MYSQL*句柄。 如果无足够内存以分配新的对象, 返回 NULL。 */
我们来获得一个句柄
MYSQL *mysql =mysql_init(NULL); //获得数据库连接的句柄,分配或初始化与 mysql_real_connect()相适应的 MYSQL 对象 if(mysql == null){ printf("mysql_init error!\n"); return -1; }
2.尝试与数据库引擎建立连接
我们会用到一个函数
函数介绍MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag) /* 描述:mysql_real_connect()尝试与运行在主机上的 MySQL 数据库引擎建立连接。 在你能够执行 需要有效 MySQL 连接句柄结构的任何其他 API 函数之前, mysql_real_connect()必须成功完成。 第 1 个参数应是已有 MYSQL 结构的地址。 调用 mysql_real_connect()之前, 必须调 用 mysql_init()来初始化 MYSQL 结构。 “host”的值必须是主机名或 IP 地址。 如果“host”是 NULL 或字符串"localhost", 连接 将被视为与本地主机的连接。 “user”参数包含用户的 MySQL 登录 ID。 如果“user”是 NULL 或空字符串"", 用户将 被视为当前用户。 “passwd”参数包含用户的密码。 如果“passwd”是 NULL, 仅会对该用户的(拥有 1 个空密码字段的) 用户表中的条目进行匹配检查。 “db”是数据库名称。 如果 db 为 NULL, 连接会将默认的数据库设为该值。 如果“port”不是 0, 其值将用作 TCP/IP 连接的端口号。 如果 unix_socket 不是 NULL, 该字符串描述了应使用的套接字或命名管道。 client_flag 的值通常为 0, */
我们来尝试连接
mysql = mysql_real_connect(mysql,"localhost(主机)","root(用户)","password(密码)","databases(数据库名称)",3306,NULL,0); if(mysql == NULL){ printf("mysql_real_connect error:%s\n",mysql_error(mysql)); //mysql_error()这个函数返回上次调用的MYSQL函数的错误信息,是一串以null终结的字符串 return -1; }
3.执行SQL语句
连接上数据库后,我们就可以执行SQL语句了,这些语句可以是DDL,DQL,DML等等语句,由用户自己输入。
函数介绍mysql_query(MYSQL *mysql,const char *sql); /* 执行由“Null 终结的字符串”查询指向的 SQL 查询。 正常情况下, 字符串必须包含 1 条 SQL 语句, 而且不应为语句添加终结分号(‘;’) 或“\g”。 如果允许多语句执行, 字符串可包含多条由分号隔开的语句。 如果希望了解查询是否应返回结果集, 可使用 mysql_field_count()进行检查 如果查询成功, 返回 0。 如果出现错误, 返回非 0 值。 */
接下来我们自己输入想要执行的SQL语句
char query[1024]={}; printf("mysql>"); gets(query); if(strcmp(query,"quit") == 0 || strcmp(query,"exit") == 0){ //当输入的sql语句是quit或者exit时,退出该嵌入式服务器 printf("Bye!\n"); break; } mysql_query(mysql,"set names utf8"); //这行代码的作用是当设置环境为utf-8编码, //如果不设置,很有可能中文字符无法正常显示,会显示为一堆乱码 int ret = mysql_query(mysql,query); //执行sql语句 if(ret != 0){ printf("mysql_query error:%s\n",mysql_error(mysql)); continue; }
4.获得结果集
当我们执行完一条sql语句后,可能有结果集,也有可能没有结果集,所以接下来我们将会用个函数来接收一个结果集。
函数介绍MYSQL_RES * mysql_store_result(MYSQL *mysql); /* 对于成功检索了数据的每个查询(SELECT、 SHOW、 DESCRIBE、 EXPLAIN、 CHECKTABLE 等) , 必须调用 mysql_store_result()或 mysql_use_result() 于其他查询, 不需要调用 mysql_store_result()或 mysql_use_result(), 但是如果在任何情 况下均调用了 mysql_store_result(), 它也不会导致任何伤害或性能降低。 通过检查 mysql_store_result()是否返回 0, 如果查询未返回结果集, mysql_store_result()将返回 Null 指针(例如, 如果查询是 INSERT 语句) 。 如果读取结果集失败, mysql_store_result()还会返回 Null 指针。 通过检查 mysql_error()是 否返回非空字符串, mysql_errno()是否返回非 0 值, 或 mysql_field_count()是否返回 0, 可 以检查是否出现了错误。 如果未返回行, 将返回空的结果集。 (空结果集设置不同于作为返回值的空指针) 。 */
那我们看一下执行完sql语句后的结果集如何
我们还需要介绍一下另外一个结构体MYSQL_RES,该结构代表返回行的查询结果(SELECT, SHOW, DESCRIBE, EXPLAIN) 。MYSQL *result = mysql_store_result(mysql); if(result == NULL){ if(mysql_errno(mysql) != 0){ printf("mysql_store_result error:%s\n",mysql_error(mysql)); return -1; }else{ printf("Query OK!\n"); continue; } /* 有必要解释这几行代码,当result为空的时候,会有两种情况,第一种就是出现了错误, //那我们需要显示错误信息,当发生错误时,mysql_errno()会返回上次调用的 MySQL 函数的错误编号, //这个编码为非0值,所以当mysql_errno(mysql) != 0时就是表示发生了错误。 所以当mysql_errno(mysql) == 0时表示没有出现错误,但是没有结果集, //比如当我们执行DML,DDL,TCL语句时就不会反回结果,这回返回影响了几条记录,比如"Query OK, 1 row affected (0.00 sec)" */ }
5.显示结果集
当我们获得结果集后,就需要显示结果集了,首先我们需要知道这个结果集中一行(即一条记录,元组)的信息,这时候我们又有了另外两个结构体类型 MYSQL_ROWh和MYSQL_FIELD。
MYSQL_ROW这是 1 行数据的“类型安全”表示。 它目前是按照计数字节字符串的数组实施的。 (如果字段值可能包含二进制数据, 不能将其当作由 Null 终结的字符串对待, 这是因为这类值可能会包含 Null 字节) 。 行是通过调用 mysql_fetch_row()获得的。
MYSQL_FIELD该结构包含关于字段的信息, 如字段名、 类型和大小。 这里详细介绍了其成员。 通过重复调用 mysql_fetch_field(), 可为每个字段获得 MYSQL_FIELD 结构。 字段值不是该结构的组成部份, 它们包含在 MYSQL_ROW 结构中。接下来我们看一下该如何显示结果集
函数介绍unsigned int mysql_num_fields(MYSQL_RES *result); //返回结果集中的行数。注意, 你可以从指向结果集的指针或指向连接句柄的指针获得行数。 MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result); //对于结果集, 返回所有 MYSQL_FIELD 结构的数组。 每个结构提供了结果集中 1 列的字段定义。 my_ulonglong mysql_num_rows(MYSQL_RES *result); //返回结果集中的行数。 MYSQL_ROW mysql_fetch_row(MYSQL_RES *result); //检索结果集的下一行。 在 mysql_store_result()之后使用时, 如果没有要检索的行, //mysql_fetch_row()返回 NULL。 在 mysql_use_result()之后使用时, 如果没有要检索的行或出现了 //错误, mysql_fetch_row()返回 NULL。
具体代码实现
unsigned int fields = mysql_num_fields(result); MYSQL_ROW record; MYSQL_FIELD *fl = mysql_fetch_field(result); size_t i; printf("**************************\n"); for(i=0;i<fields;i++){ printf("%-15s ",fl[i].name); } printf("\n"); while(record = mysql_fetch_row(result)){ for(i=0;i<fileds;i++){ printf("%-10s ",record[i]); } printf("\n"); } my_ulonglong rows = mysql_num_rows(result); printf("%lu rows in set (0.012 sec)\n",(unsigned long int)(rows));
6.释放资源,关闭连接
当我们完成数据库的操作后,需要释放资源和关闭连接,否则会出现其他许多问题。
函数介绍void mysql_free_result(MYSQL_RES *result); //释放由 mysql_store_result()、 mysql_use_result()、 mysql_list_dbs()等为结果集分配的内存。 //完成对结果集的操作后, 必须调用 mysql_free_result()释放结果集使用的内存 void mysql_close(MYSQL *mysql); //关闭前面打开的连接。 如果句柄是由 mysql_init()或 mysql_connect()自动分配的, //mysql_close()还将解除分配由 mysql 指向的连接句柄。
最后我们关闭连接,释放资源
if(result != NULL){ //如果当我们执行的第一句sql语句就是exit或者quit时,此时result仍未null, //那这时候不需要释放,如果强行释放就会产生段错误. mysql_free_result(result); } mysql_close(mysql);
7.全部源代码
最后我们以这份源代码收尾
#include <mysql/mysql.h> #include <stdio.h> int main(){ MYSQL *mysql = mysql_init(NULL); if(mysql == NULL){ printf("mysql_init error!\n"); return -1; } mysql = mysql_real_connect(mysql,"localhost","root","123456","test",3306,NULL,0); //这里需要根据每个数据库的具体数据来写参数 if(mysql == NULL){ printf("mysql_real_connect error:%s\n",mysql_error(mysql)); return -1; } MYSQL_RES *result=NULL; while(1){ char query[1024] = {}; printf("mysql>"); gets(query); if(strcmp(query,"quit") == 0 || strcmp(query,"exit") == 0){ printf("Bye\n"); break; } mysql_query(mysql,"set names utf8"); int ret = mysql_query(mysql,query); if(ret != 0){ printf("mysql_query error:%s\n",mysql_error(mysql)); continue; } result = mysql_store_result(mysql); //获得结果集 if(result == NULL){ if(mysql_errno(mysql) != (unsigned int)(0)){ printf("mysql_store_result error:%s\n",mysql_error(mysql)); return -1; }else{ continue; } } unsigned int fields = mysql_num_fields(result); MYSQL_ROW record; MYSQL_FIELD *fl = mysql_fetch_field(result); size_t i; printf("**************************\n"); for(i=0;i<fields;i++){ printf("%-15s ",fl[i].name); } printf("\n"); while(record = mysql_fetch_row(result)){ for(i=0;i<fields;i++){ printf("%-10s ",record[i]); } printf("\n"); } my_ulonglong rows = mysql_num_rows(result); printf("%lu rows in set (0.012 sec)\n",(unsigned long int)(rows)); } if(result!=NULL){ mysql_free_result(result); } mysql_close(mysql); return 0; }
在运行这段程序前,我们还需要下载一个库libmysqlclient或者,平台不同要下载的东西也不同,但是大致都一样。
8.运行效果
最后的最后我们来看一下结果怎么样?
BYEBYE; -
jetty9.0.4嵌入式服务器开发所必须的全部jar包
2016-11-29 16:32:22jetty嵌入式服务器开发所必须的全部jar包。本人使用jetty版本为9.0.4,这个版本比较稳定些。jar包数据很多,最后集中在jetty-all中,再外引入一下servlet-api-这个包,是与9.0.4配套的。 好东西,大家分享。 -
车位管理主机的新型嵌入式服务器技术研究
2020-07-26 00:53:06针对停车场车位管理人员与现场嵌入式Linux车位管理主机的交互需求,讨论了在嵌入式Linux车位管理主机中使用Apache和SQLite构建嵌入式WEB服务器的关键技术和实现过程。 -
嵌入式服务器jetty,让你更快开发web
2017-09-01 09:59:30它的最大特点是:可以很方便的作为嵌入式服务器。 它是eclipse的一个开源项目。不用怀疑,就是你常用的那个eclipse。 它是使用Java开发的,所以天然对Java支持良好。 官方网址 github源码地址 什么是嵌入式服务器? ...概述
jetty是什么?
jetty是轻量级的web服务器和servlet引擎。
它的最大特点是:可以很方便的作为嵌入式服务器。
它是eclipse的一个开源项目。不用怀疑,就是你常用的那个eclipse。
它是使用Java开发的,所以天然对Java支持良好。
什么是嵌入式服务器?
以jetty来说明,就是只要引入jetty的jar包,可以通过直接调用其API的方式来启动web服务。
用过Tomcat、Resin等服务器的朋友想必不会陌生那一套安装、配置、部署的流程吧,还是挺繁琐的。使用jetty,就不需要这些过程了。
jetty非常适用于项目的开发、测试,因为非常快捷。如果想用于生产环境,则需要谨慎考虑,它不一定能像成熟的Tomcat、Resin等服务器一样支持企业级Java EE的需要。
jetty的嵌入式启动
我觉得嵌入式启动方式的一个好处在于:可以直接运行项目,无需每次部署都得再配置服务器。
jetty的嵌入式启动使用有两种方式:
API方式
maven插件方式
API方式
添加maven依赖
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>9.3.2.v20150730</version> <scope>test</scope> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-annotations</artifactId> <version>9.3.2.v20150730</version> <scope>test</scope> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>apache-jsp</artifactId> <version>9.3.2.v20150730</version> <scope>test</scope> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>apache-jstl</artifactId> <version>9.3.2.v20150730</version> <scope>test</scope> </dependency>
官方的启动代码
public class SplitFileServer { public static void main( String[] args ) throws Exception { // 创建Server对象,并绑定端口 Server server = new Server(); ServerConnector connector = new ServerConnector(server); connector.setPort(8090); server.setConnectors(new Connector[] { connector }); // 创建上下文句柄,绑定上下文路径。这样启动后的url就会是:http://host:port/context ResourceHandler rh0 = new ResourceHandler(); ContextHandler context0 = new ContextHandler(); context0.setContextPath("/"); // 绑定测试资源目录(在本例的配置目录dir0的路径是src/test/resources/dir0) File dir0 = MavenTestingUtils.getTestResourceDir("dir0"); context0.setBaseResource(Resource.newResource(dir0)); context0.setHandler(rh0); // 和上面的例子一样 ResourceHandler rh1 = new ResourceHandler(); ContextHandler context1 = new ContextHandler(); context1.setContextPath("/"); File dir1 = MavenTestingUtils.getTestResourceDir("dir1"); context1.setBaseResource(Resource.newResource(dir1)); context1.setHandler(rh1); // 绑定两个资源句柄 ContextHandlerCollection contexts = new ContextHandlerCollection(); contexts.setHandlers(new Handler[] { context0, context1 }); server.setHandler(contexts); // 启动 server.start(); // 打印dump时的信息 System.out.println(server.dump()); // join当前线程 server.join(); } }
直接运行Main方法,就可以启动web服务。
注:以上代码在eclipse中运行没有问题,如果想在Intellij中运行还需要为它指定配置文件。
如果想了解在Eclipse和Intellij都能运行的通用方法可以参考我的github代码示例。
我的实现也是参考springside的方式。
代码行数有点多,不在这里贴代码了。
Maven插件方式
如果你熟悉maven,那么实在太简单了
注: Maven版本必须在3.3及以上版本。
(1) 添加maven插件
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.12.v20160915</version> </plugin>
(2) 执行maven命令:
mvn jetty:run
讲真,就是这么简单。jetty默认会为你创建一个web服务,地址为127.0.0.1:8080。
当然,你也可以在插件中配置你的webapp环境
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.3.12.v20160915</version> <configuration> <webAppSourceDirectory>${project.basedir}/src/staticfiles</webAppSourceDirectory> <!-- 配置webapp --> <webApp> <contextPath>/</contextPath> <descriptor>${project.basedir}/src/over/here/web.xml</descriptor> <jettyEnvXml>${project.basedir}/src/over/here/jetty-env.xml</jettyEnvXml> </webApp> <!-- 配置classes --> <classesDirectory>${project.basedir}/somewhere/else</classesDirectory> <scanClassesPattern> <excludes> <exclude>**/Foo.class</exclude> </excludes> </scanClassesPattern> <scanTargets> <scanTarget>src/mydir</scanTarget> <scanTarget>src/myfile.txt</scanTarget> </scanTargets> <!-- 扫描target目录下的资源文件 --> <scanTargetPatterns> <scanTargetPattern> <directory>src/other-resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> <excludes> <exclude>**/myspecial.xml</exclude> <exclude>**/myspecial.properties</exclude> </excludes> </scanTargetPattern> </scanTargetPatterns> </configuration> </plugin>
官方给的jetty-env.xml范例
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <!-- Add an EnvEntry only valid for this webapp --> <New id="gargle" class="org.eclipse.jetty.plus.jndi.EnvEntry"> <Arg>gargle</Arg> <Arg type="java.lang.Double">100</Arg> <Arg type="boolean">true</Arg> </New> <!-- Add an override for a global EnvEntry --> <New id="wiggle" class="org.eclipse.jetty.plus.jndi.EnvEntry"> <Arg>wiggle</Arg> <Arg type="java.lang.Double">55.0</Arg> <Arg type="boolean">true</Arg> </New> <!-- an XADataSource --> <New id="mydatasource99" class="org.eclipse.jetty.plus.jndi.Resource"> <Arg>jdbc/mydatasource99</Arg> <Arg> <New class="com.atomikos.jdbc.SimpleDataSourceBean"> <Set name="xaDataSourceClassName">org.apache.derby.jdbc.EmbeddedXADataSource</Set> <Set name="xaDataSourceProperties">databaseName=testdb99;createDatabase=create</Set> <Set name="UniqueResourceName">mydatasource99</Set> </New> </Arg> </New> </Configure>
参考
-
嵌入式服务器appweb接收浏览器post的文件失败
2019-07-24 15:10:35嵌入式服务器appweb接收浏览器post的文件失败 题目已经描述了问题,这是在工作中遇到的问题,想要的功能是通过浏览器传输固件升级文件到appweb服务器,可总是失败。 究其原因也很简单,就是固件文件大小超过了app...嵌入式服务器appweb接收浏览器post的文件失败
题目已经描述了问题,这是在工作中遇到的问题,想要的功能是通过浏览器传输固件升级文件到appweb服务器,可总是失败。
究其原因也很简单,就是固件文件大小超过了appweb服务器所能承受的大小,导致上传失败。
appweb服务器有一个默认的接收文件的大小,比较小,所以要修改appweb服务器的配置文件,将默认的大小变大就可以啦。
在appweb.conf的末尾增加如下4行:
AddInputFilter uploadFilter
UploadAutoDelete on
LimitUpload 10M
InactivityTimeout 20min如果你遇到了这个问题可以去尝试下本方法是否可行。
一个开卷有益的公众号:IT平头哥
-
使用Jetty作为嵌入式服务器
2011-09-13 16:31:05使用Jetty作为嵌入式服务器 分类: 测试工具开发 2006-08-23 23:46 5781人阅读 评论 (5) 收藏 举报 需要最少的包: commons-l... -
嵌入式服务器boa的搭建
2012-04-26 14:25:36嵌入式服务器Boa的搭建方法 虚拟机:RHEL5.0.2 物理机:win7旗舰版 Arm平台:博创UP-TECH-P270 一.在虚拟机上搭建boa 1. 在www.boa.org上下载boa-0.94.13.tar.gz,这个版本已经很久未更新过,所以选这个就行... -
gohead 嵌入式服务器
2014-11-19 16:00:40GOHEAD 1、 简介 ...嵌入式web服务器正好迎合了这种需求,它们嵌入在网络设备之中,使用标准的浏览器就可以远程访问和控制它们。 然而,并不是所有的web服务器都可以担当如此重任,我们需要的是一 -
基于TCP/IP协议栈的嵌入式服务器研究
2020-07-05 12:11:44基于TCP/IP协议栈的EWS设计,解决了现场设备监测数据难以远程传输的问题。通过分析嵌入式TCP/IP协议栈的设计原理,着重探讨TCP、ARP等协议的设计以及EWS的设计。 -
jetty嵌入式服务器
2014-11-01 18:41:19作为嵌入式服务器使用代码实例 Java代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ... -
Jetty嵌入式服务器的JNDI快速配置指南
2019-05-26 01:53:05NULL 博文链接:https://seraph115.iteye.com/blog/436300 -
Atitit 嵌入式tomcat 嵌入式服务器 attilax 你感觉艾提拉 总结 比起嵌入jetty ,文件可以自动刷新貌似还...
2018-04-07 12:43:45Atitit 嵌入式tomcat 嵌入式服务器 attilax 你感觉艾提拉 总结 比起嵌入jetty ,文件可以自动刷新貌似还不错。。方便调试debug package com.attilax.web; import java.io.File; import org.apache.catalina.... -
Jetty嵌入式服务器
2011-05-24 15:48:00原文地址:http://yzw2007.iteye.com/blog/424114关键字: jetty服务器Jetty 是一个用 Java 实现、开源、基于标准的,并且具有丰富功能的 Http ...Jetty 可以用来作为一个传统的 Web 服务器,也可以作为一个动 -
【后台】嵌入式服务器Boa和CGI
2017-07-30 11:26:25大三的时候做过一个大学生创新项目,基于ZigBee的无线火警系统,后台使用的服务器就是自己在S3C2410开发板上移植搭建的Boa嵌入式web服务器。最近在复习做过的项目,顺便回顾了一下相关的内容。 一般的嵌入式web... -
mysticmind-postgresembed:等同于Postgres嵌入式服务器,包括.Net应用程序的扩展-源码
2021-02-05 16:59:22这是一个用于运行Postgres服务器嵌入式等效项的库,其中包括针对Windows x64的扩展。 该项目还以一种简洁的配置和使用方式很好地处理了Postgres扩展。 默认情况下,此项目使用发布在Nuget包的二进制文件。 请注意... -
springboot的嵌入式服务器tomcat配置
2019-07-09 09:23:39TomcatServletWebServerFactory只是现成的tomcat的配置,如果你使用其他的服务器,那么需要配置其他的factory 本文对tomcat配置示例只是将不同的code 比如:404/500跳到不同的页面. 更可以在配置文件里: ... -
单机游戏数据库探讨(MySQL嵌入式服务器的使用)(未完)
2013-10-17 11:40:23以前玩单机游戏,总会对单机游戏的目录结构作探讨。 通常,游戏的存储数据都会存储在一个名叫save的文件夹中。如果游戏不大,可以...现在先不说在服务器中怎样使用MySQL,先谈谈MySQL嵌入式服务器的使用。没有涉及到 -
嵌入式服务器端配置tftpd
2011-06-29 08:29:00嵌入式linux的tftp开发环境包括两个方面:一是linux服务器端的tftp-server支持,二是嵌入式目标系统的tftp-client支持。因为u-boot本身内置支持tftp-client,所以嵌入式目标系统端就不用配置了。下面就详细介绍一下... -
Redis嵌入式服务器,用于Java集成测试
2019-06-22 22:20:47您还可以使用cluster.sentinelPorts() 或服务器获取哨兵端口cluster.serverPorts()。JedisUtilclass包含与Jedis客户端一起使用的实用程序方法。 使用预定义端口 您还可以在预定义的端口上启动Redis群集,甚至... -
jetty 嵌入式服务器介绍
2011-02-08 10:05:003.jetty嵌入式服务器介绍 http://www.51testing.com/html/89/n-20389.html http://keben1983.blog.163.com/blog/static/1436380812010101010812432/ http://yzw2007.javaeye.com/blog/424114 -
WAR文件与具有嵌入式服务器的Java应用程序
2020-05-16 19:25:39大多数服务器端Java应用程序(例如,面向Web或面向服务的)都希望在容器中运行。 打包这些应用程序以进行分发的传统方法是将它们捆绑为WAR文件。 这无非是具有标准目录布局的ZIP归档文件,其中包含运行时所需的所有... -
嵌入式服务器appweb交叉编译指南
2014-01-22 21:07:50appweb+matrixssl+php+sqlite是一款十分流行及轻量,十分适合嵌入式平台的web服务器实现方案,网上关于搭建这个平台的资料大多基于appweb2.4及更早,这里给出的思路为叙述appweb4.5 及 matrixssl 3.4.2 的交叉编译及... -
阶段2-新手上路\项目-移动物体监控系统\Sprint4-嵌入式web服务器开发\第1课-BOA嵌入式服务器移植...
2016-11-02 00:48:00(百度直接搜:嵌入式web服务器,选择boa,再搜索boa的移植) 进入boa服务器里面的src目录下,进行配置 查看有无makefile的生成 修改生成的Makefile的编译选项为arm平台下 接下来进行编译, util.c文件... -
thttpd嵌入式服务器安装,配置 测试
2015-06-08 16:59:20安装完了thttpd之后 服务器可以运行,但是在thttpd.conf中设置的服务器根目录就是不对应,不知道是哪里的问题,最后通过搜寻cgi-bin,找到了根目录的对应路径在/srv/www下,让我好找一通,最后测试通过,可以正常显示...
-
process-power:一个用于网站processpower.surge.sh的存储库-源码
-
制造业智慧工厂管理系统软件解决方案
-
2020年中高级Android面试秘籍(Android高级篇-2)
-
存储器
-
MySQL你该了解的那些事【服务端篇】
-
MaxScale 实现 MySQL 读写分离与负载均衡
-
华为1+X——网络系统建设与运维(高级)
-
libFuzzer视频教程
-
基于蓝牙接收模块的TPA3110音频功放板ALTIUM 设计硬件原理图+PCB+封装库文件.zip
-
前天是哪天
-
程序是如何在 CPU 中运行的(一)
-
程序员必修基础套餐课
-
GL error Invalid operation:Optix7官方Demo奇怪问题解决方案
-
华为1+X——网络系统建设与运维(中级)
-
MySQL 高可用工具 heartbeat 实战部署详解
-
bas-spec:BAS语言规范-源码
-
JSTL标签库jar包.rar
-
day02
-
项目1--源码
-
Xamarin天气-源码