使用HttpClient或者RestTemplate时,一般都会自定义封装一个HttpUtil来使用。
Apache HttpClient的两个版本:
环境依赖
spring-boot-2.2.2.RELEASE
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
spring-boot-2.2.2.RELEASE默认httpclient版本4.5.10。
配置类
/**
* @author: lijiangang
* @date: 2022-4-2 14:50
*/
@Configuration
public class HttpClientConfig {
@Bean
public CloseableHttpClient httpClient() {
// 长连接保持30秒
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
//设置整个连接池最大连接数 根据自己的场景决定
connectionManager.setMaxTotal(500);
//同路由的并发数,路由是对maxTotal的细分
connectionManager.setDefaultMaxPerRoute(500);
RequestConfig requestConfig = RequestConfig.custom()
//服务器返回数据(response)的时间,超过该时间抛出read timeout
.setSocketTimeout(10000)
//连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
.setConnectTimeout(5000)
//从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
.setConnectionRequestTimeout(500)
.build();
//headers
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"));
headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
headers.add(new BasicHeader("Accept-Language", "zh-CN"));
headers.add(new BasicHeader("Connection", "Keep-Alive"));
headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8"));
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.setDefaultHeaders(headers)
// 保持长连接配置,需要在头添加Keep-Alive
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
//重试次数,默认是3次,没有开启
// .setRetryHandler(new DefaultHttpRequestRetryHandler(2, true))
.build();
}
}
自定义请求工具类
@Component
public class HttpClientUtil {
@Autowired
private CloseableHttpClient httpClient;
public String get(String url) {
CloseableHttpResponse response = null;
BufferedReader in;
String result = "";
try {
// 创建http请求,请求设置,请求参数
HttpGet httpGet = new HttpGet(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
httpGet.setConfig(requestConfig);
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
httpGet.setHeader("Accept", "application/json");
// 执行http请求
response = httpClient.execute(httpGet);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer();
String line;
// 获取操作系统对应的换行符
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
result = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != response) {
// 释放连接
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
public String post(String url, Object param) {
CloseableHttpResponse response = null;
BufferedReader in;
String result = "";
try {
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
httpPost.setHeader("Accept", "application/json");
httpPost.setEntity(new StringEntity(JSON.toJSONString(param), Charset.forName("UTF-8")));
response = httpClient.execute(httpPost);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer();
String line;
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
result = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != response) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
}
使用
@RestController
@RequestMapping("/http")
public class HttpTestController {
@Autowired
private HttpClientUtil httpClientUtil;
@GetMapping("test")
public ApiResult test() {
return ApiUtil.success();
}
@GetMapping("test1")
public ApiResult test1() {
String json = httpClientUtil.get("http://127.0.0.1:8888/http/test");
return JSON.parseObject(json, new TypeReference<ApiResult>() {
});
}
}
详细使用可参考:https://www.cnblogs.com/qnlcy/p/15378446.html
OkHttp是一个高效的HTTP客户端,允许所有同一个主机地址的请求共享同一个socket连接;连接池减少请求延时;透明的GZIP压缩减少响应数据的大小;缓存响应内容,避免一些完全重复的请求。
当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。
配置OkHttpClient。
依赖配置
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.10.0</version>
</dependency>
配置类
@Configuration
public class OkHttpConfig {
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient.Builder()
// .sslSocketFactory(sslSocketFactory(), x509TrustManager())
.retryOnConnectionFailure(false)
.connectionPool(pool())
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build();
}
@Bean
public X509TrustManager x509TrustManager() {
return new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
}
@Bean
public SSLSocketFactory sslSocketFactory() {
try {
//信任任何链接
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{
x509TrustManager()}, new SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return null;
}
@Bean
public ConnectionPool pool() {
return new ConnectionPool(200, 5, TimeUnit.MINUTES);
}
}
使用
@RestController
@RequestMapping("/http")
public class HttpTestController {
@Autowired
private OkHttpUtil okHttpUtil;
@GetMapping("test")
public ApiResult test() {
return ApiUtil.success();
}
@GetMapping("test2")
public ApiResult test2() {
String json = okHttpUtil.get("http://127.0.0.1:8888/http/test", null);
return JSON.parseObject(json, new TypeReference<ApiResult>() {
});
}
}
retrofit是现在比较流行的网络请求框架,可以理解为okhttp的加强版,底层封装了okhttp。准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。
底层原理
应用程序通过Retrofit请求网络,实质上是使用Retrofit接口层封装请求参数、Header、Url等信息,之后由okhttp来完成后续的请求工作。在服务端返回数据后,okhttp将原始数据交给Retrofit,Retrofit根据用户需求解析。
Retrofit将okhttp请求抽象成java接口,采用注解描述和配置网络请求参数,用动态代理将该接口的注解“翻译”成一个Http请求,最后执行Http请求。
注意:接口中的每个方法的参数都要用注解标记,否则会报错。
Retrofit的优点
1. 请求方法
注解 | 描述 |
---|---|
@GET | get请求 |
@POST | post请求 |
@PUT | put请求 |
@DELETE | delete请求 |
@PATCH | patch请求,该请求是对put请求的补充,用于更新局部资源 |
@HEAD | head请求 |
@OPTIONS | options请求 |
@HTTP | 通过注解,可以替换以上所有的注解,它拥有三个属性:method、path、hasBody |
2. 请求头
注解 | 描述 |
---|---|
@Headers | 用于添加固定请求头,可以同时添加多个,通过该注解的请求头不会相互覆盖,而是共同存在 |
@Header | 用于添加不固定的header,作为方法的参数传入,它会更新已有请求头 |
3. 请求参数
注解 | 描述 |
---|---|
@Body | 多用于Post请求发送非表单数据,根据转换方式将实例对象转化为对应字符串传递参数,比如使用Post发送Json数据,添加GsonConverterFactory则是将body转化为json字符串进行传递 |
@Filed | 多用于Post方式传递参数,需要结合@FromUrlEncoded使用,即以表单的形式传递参数 |
@FiledMap | 多用于Post请求中的表单字段,需要结合@FromUrlEncoded使用 |
@Part | 用于表单字段,Part和PartMap与@multipart注解结合使用,适合文件上传的情况 |
@PartMap | 用于表单字段,默认接受类型是Map<String,RequestBody>,可用于实现多文件上传 |
@Path | 用于Url中的占位符 |
@Query | 用于Get请求中的参数 |
@QueryMap | 与Query类似,用于不确定表单参数 |
@Url | 指定请求路径 |
4. 请求和响应格式(标记)
注解 | 描述 |
---|---|
@FromUrlCoded | 表示请求发送编码表单数据,每个键值对需要使用@Filed注解 |
@Multipart | 表示请求发送form_encoded数据(使用于有文件上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值 |
@Streaming | 表示响应用字节流的形式返回,如果没有使用注解,默认会把数据全部载入到内存中,该注解在下载大文件时特别有用 |
自定义请求接口,采用注解描述和配置请求参数。
本示例不是直接使用的retrofit依赖,而是使用的retrofit整合springboot依赖。
retrofit依赖
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.9.0</version>
</dependency>
retrofit整合springboot依赖
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
启动类配置
@SpringBootApplication
@RetrofitScan("com.joker.http.retrofit")
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
自定义接口
import com.github.lianjiatech.retrofit.spring.boot.annotation.RetrofitClient;
import com.joker.common.base.result.ApiResult;
import com.joker.pojo.User;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.http.*;
import java.util.Map;
@RetrofitClient(baseUrl = "http://127.0.0.1:8888")
public interface RetrofitHttpApi {
@GET("http/test")
ApiResult test();
/**
* 简单的GET请求
* @Query:用于Get请求中的参数
*/
@GET("http/test1")
ApiResult test1(@Query("id") long id);
/**
* 不确定参数的GET请求
* @QueryMap 与@Query类似,用于不确定表单参数。通过Map将不确定的参数存入,然后在方法体中带给网络接口。
*/
@GET("http/test2")
ApiResult test2(@QueryMap Map<String, Object> map);
/**
* From表单POST请求
* @FormUrlEncoded:请求格式注解,表明请求实体是一个From表单,每个键值对需要使用@Field注解
* @Field:表单参数,而且需要配合@FormUrlEncoded使用
* @return
*/
@FormUrlEncoded
@POST("http/test3")
ApiResult test3(@Field("name") String name, @Field("age") Integer age);
/**
* 不确定参数的From表单POST请求
*/
@FormUrlEncoded
@POST("http/test4")
ApiResult test4(@FieldMap Map<String, Object> map);
/**
* json方式POST请求
*/
@POST("http/test5")
ApiResult test5(@Body User user);
/**
* 文件上传表单POST请求
* @Multipart:表示请求实体是一个支持文件上传的表单,需要配合@Part和@PartMap使用,适用于文件上传
* @Part:用于表单字段,适用于文件上传的情况,@Part支持三种类型:RequestBody、MultipartBody.Part任意类型
* @PartMap:用于多文件上传, 与@FieldMap和@QueryMap的使用类似
* @return
*/
@Multipart
@POST("http/test6")
ApiResult test6(@Part("name") RequestBody name, @Part MultipartBody.Part file);
/**
* 多文件上传POST请求
* @param map
* @return
*/
@Multipart
@POST("http/test7")
ApiResult test7(@PartMap Map<String, MultipartBody.Part> map);
/**
* 路径参数请求
* @param id
* @return
*/
@GET("http/test8/{id}")
ApiResult test8(@Path("id") Long id);
/**
* 请求头参数请求
* @Header:请求头注解,用于添加不固定请求头
* @param token
* @return
*/
@GET("http/test9")
ApiResult test9(@Header("token") String token);
/**
* 请求头参数请求
* @Headers:请求头注解,用于添加固定请求头,可以添加多个
* @return
*/
@Headers({
"version:1.0","os:windows"})
@GET("http/test10")
ApiResult test10();
/**
* 动态url请求
* @Url:将地址以参数的形式传入,请求方法注解中定义的url忽略
* @param url
* @return
*/
@GET("http/test11")
ApiResult test11(@Url String url);
/**
* 下载文件请求
* @Streaming:响应体的数据用流的方式返回,使用于返回数据比较大,该注解在下载大文件时特别有用
* @return
*/
@Streaming
@POST("http/test12")
ResponseBody test12();
/**
* @HTTP:注解的作用是替换@GET、@POST、@PUT、@DELETE、@HEAD以及更多拓展功能
* @return
*/
@HTTP(method = "GET", path = "http/test13", hasBody = false)
ApiResult test13();
}
详细使用可参考:https://blog.csdn.net/why_still_confused/article/details/108041657
RestTemplate是Spring提供的用于访问Rest服务的客户端库。它提供了一套接口,实现这套接口的http库都可以通过RestTemplate来使用。
常用的有:
RestTemplate默认使用的http库是JDK自带的HttpURLConnection来建立HTTP连接(使用SimpleClientHttpRequestFactory客户端)。另外三方http库通过实现ClientHttpRequestFactory接口来自定义客户端,可以通过RestTemplate的setRequestFactory指定要使用的客户端。
ClientHttpRequestFactory接口的实现类:
RestTemplate在spring-web包中。Spring项目有spring-web包即可,SpringBoot项目有spring-boot-starter-web包即可,如果要少使用Apache的HttpClient、OKHttp等相关三方http库,则还需要器对应的包。
RestTemplate内部模板使用HttpMessageConverter实例将HTTP消息转换为POJO和从POJO转换。主要MIME类型的转换器是默认注册的,也可以通过setMessageConverters方法注册其他转换器。
RestTemplate提供操作http的方法
方法名称 | 支持的HTTP方法 | 方法描述 |
---|---|---|
getForObject | GET | 直接返回响应对象,可设置路径参数 |
getForEntity | GET | 返回封装的响应对象,可设置路径参数 |
postForObject | POST | 直接返回响应对象,可设置路径参数,可设置请求body和请求header |
postForEntity | POST | 返回封装的响应对象,可设置路径参数,可设置请求body和请求header |
postForLocation | POST | 返回URI对象,适用于返回网络资源的请求方式。可设置路径参数,可设置请求body和请求header |
put | PUT | 无返回值,可设置路径参数,可设置请求body和请求header |
delete | DELETE | 无返回值,可设置路径参数 |
headForHeaders | HEAD | 返回HttpHeaders,可设置路径参数 |
optionsForAllow | OPTIONS | 返回Set<HttpMethod>,可设置路径参数 |
execute | 都支持 | 直接返回响应对象,通用请求方法 |
exchange | 都支持 | 返回封装的响应对象,通用请求方法 |
注意:封装的响应对象除了能获取到响应对象,还能额外获取到响应状态,响应Header信息。
配置RestTemplate(如果不配置客户端,会使用默认的客户端SimpleClientHttpRequestFactory),就可以直接使用。
方法1
使用spring默认客户端SimpleClientHttpRequestFactory
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
方法2
使用Apache HttpClient客户端(HttpComponentsClientHttpRequestFactory)。
@Bean
@DependsOn("httpClient")
public RestTemplate restTemplate3(HttpClient httpClient) {
RestTemplate restTemplate = new RestTemplate(httpComponentsClientHttpRequestFactory(httpClient));
setRestTemplate(restTemplate);
return restTemplate;
}
@Bean
public ClientHttpRequestFactory httpComponentsClientHttpRequestFactory(HttpClient httpClient) {
return new HttpComponentsClientHttpRequestFactory();
}
HttpClient的配置参考上面HttpClient的使用示例。
方法3
使用OKHttp客户端(OkHttp3ClientHttpRequestFactory)。
@Bean
@DependsOn("okHttpClient")
public RestTemplate restTemplate4(OkHttpClient okHttpClient) {
RestTemplate restTemplate = new RestTemplate(okHttp3ClientHttpRequestFactory(okHttpClient));
setRestTemplate(restTemplate);
return restTemplate;
}
@Bean
public ClientHttpRequestFactory okHttp3ClientHttpRequestFactory(OkHttpClient okHttpClient) {
return new OkHttp3ClientHttpRequestFactory(okHttpClient);
}
OkHttpClient的配置参考上面OKhttp的使用示例。
1.先按上面的使用方法配置好RestTemplate。
2.进行接口测试,示例如下:
@Autowired
private RestTemplate restTemplate;
@GetMapping("test4")
public ApiResult test4() {
// 1.Get请求
ApiResult result = restTemplate.getForObject(getUrl("get"), ApiResult.class);
System.out.println("Get请求:" + JSON.toJSONString(result));
// 2.设置路径参数的Get请求
result = restTemplate.getForObject(getUrl("get/{id}"), ApiResult.class, 123);
System.out.println("设置路径参数的Get请求:" + JSON.toJSONString(result));
// 3.封装返回对象的Get请求
ResponseEntity<ApiResult> responseEntity = restTemplate.getForEntity(getUrl("get"), ApiResult.class);
System.out.println("封装返回对象的Get请求:" + responseEntity.getBody());
// 4.设置header的Get请求
HttpHeaders headers = new HttpHeaders();
headers.add("token", "token");
ResponseEntity<ApiResult> response = restTemplate.exchange(getUrl("get"), HttpMethod.GET, new HttpEntity<String>(headers), ApiResult.class);
System.out.println("设置header的Get请求:" + response.getBody());
// 5.Post请求
User user = new User();
user.setId("1");
result = restTemplate.postForObject(getUrl("post"), user, ApiResult.class);
System.out.println("Post请求:" + result);
// 6.设置header的Post请求
response = restTemplate.postForEntity(getUrl("post"), new HttpEntity<>(user, headers), ApiResult.class);
System.out.println("设置header的Post请求:" + response.getBody());
// 7.设置header的put请求
// 无返回值
restTemplate.put(getUrl("put"), new HttpEntity<>(user, headers));
// 带返回值
response = restTemplate.exchange(getUrl("put"), HttpMethod.PUT, new HttpEntity<>(user, headers), ApiResult.class);
System.out.println("设置header的put请求:" + response.getBody());
// 8.设置路径参数的del请求
// 无返回值
restTemplate.delete(getUrl("delete/{id}"), 123);
// 带返回值
response = restTemplate.exchange(getUrl("delete/{id}"), HttpMethod.DELETE, null, ApiResult.class,123);
System.out.println("设置路径参数的del请求:" + response.getBody());
return ApiUtil.success();
}
文章浏览阅读2.4k次。其他 NAS 型号,可以于下载中心查询是否支援 Synology Drive Server 套件。_ds212j管理
文章浏览阅读1.4k次。Weka新手文章(一) 收藏数据仓库,数据分析,不涉及商业方面的高层决策之用,故本篇文章只适合初学数据仓库,为了完成老师作业,且想用weka做简单数据挖掘之用的童鞋。weka版本是3.6.2,数据库库是SQL Server 2005,没办法,老师提供的几万条数据保存在excel表中,如果从excel转为csv格式,再从weka中导入该csv文件,涉及到格式的转换,很是麻烦~况且几万条数_cannot resolve weka:weka:3.6.2
文章浏览阅读1.2k次。电子标签的概念电子标签的概念二、RFID电子标签的分类:三、RFID标签的原理四、RFID标签的组成五、RFID的工作原理阅读器和电子标签之间的射频信号的耦合类型有两种:电感耦合电磁反向散射耦合六、RFID电子标签的数据存储七、RFID低频简介八、RFID高频简介九、RFID超高频简介十、RFID微波段简介RFID电子标签的防冲撞机制面向比特的防冲突机制面向时隙的防冲突机制总结)电子标签的概念电子标签又称射频标签、应答器、数据载体;是一种存储数据识别资料的装置,可以透过无线电波与读写器之间互相传递_rfid防冲突机制
文章浏览阅读1.6k次,点赞2次,收藏4次。注意:以下方法是我通过多方查找摸索拼凑出来的出来的,可能和某些书籍或博主给出的不同; 亲测能自动播放音乐,但不知道什么缘故只我再测试时只有360极速游览器可以用。 由于没开网站,效果可以自己试试(很简陋)1:代码如下:<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>歌曲</title> <style type="text/css"&g.._sublime音乐播放器代码
文章浏览阅读8.8k次,点赞3次,收藏7次。抽个中午的时间写一篇博客,想必大家现在正在午饭呢吧,深圳的天气真是变换无常,刚刚大雨倾盆,不一会就晴天高照。打球吗?约起来哇,哈哈。。今天给大家带来一篇Dialog提示附加动画效果的功能。这种Dialog提示效果基本变成了每个App都必不可少功能。例如,退出提示,弹出分享框,App升级提示等等。。其实在Android中实现提示功能由很多种方式:自定义Dialog,AlertDialog,自_android dialog 动画右出出入效果
文章浏览阅读432次。tff.learning 模块用于使用联合学习算法的模型开发的公共API模块framework模块:面向开发联合学习算法的贡献者的公共API类BatchOutput类: 保存tf .learning. model输出的结构。Model类: 表示TensorFlow联邦中使用的模型。TrainableModel类: 带有用..._tff.learning.build_federated_averaging_process
文章浏览阅读1.7k次,点赞2次,收藏3次。最近在部署一个springboot的war文件到tomcat的时候,出现了一大堆的404,找不到的问题,在eclipse调试中不曾出现。后来仔细核实发现,原来确实是路径有问题。在浏览器可以看见他的后台访问路径如下:XHR POST http://127.0.0.1:8080/home/welcome //这是一个mapping映射,到controller......_war包 静态资源必须放入 classes文件夹才能被访问到
文章浏览阅读202次。一. 首先开启Windows功能在这里把你需要的服务都选中,如果你不清楚具体需要哪些,不妨全部选中。二. 进入IIS管理器三. 建站把你的网站资源和文件存到一个合适的位置,为了测试我们只用最简单的示范(稍微正经一点的网页也不会像我这么写...)。<html><body><h1>My IIS Test Page</h1></body></html>..._iis搭建网站的基本原理
文章浏览阅读9.5k次,点赞4次,收藏9次。pandas提供基于行和列的聚合操作,groupby可理解为是基于行的,agg则是基于列的从实现上看,groupby返回的是一个DataFrameGroupBy结构,这个结构必须调用聚合函数(如sum)之后,才会得到结构为Series的数据结果。 而agg是DataFrame的直接方法,返回的也是一个DataFrame。当然,很多功能用sum、mean等等也可以实现。但是agg更加简洁, 而..._pandas group by agg
文章浏览阅读4.1k次,点赞3次,收藏25次。使用onchange事件,当点击不同下拉框选项时,改变div背景颜色以及文字效果展示代码演示<!DOCTYPE html><html> <head lang="en"> <meta charset="UTF-8"> <title>onchange()</title> <style type="text/css"> #div { width: 300px; height_js select>option鼠标滑动背景色设置
文章浏览阅读2.4k次。一、计算机基础知识,Java语言的概述,运行环境及开发工具的下载安装1、计算机基础知识1.1、计算机的概念什么是计算机:(Computer)全称:电子计算机,俗称电脑。是一种能够按照程序运行,自动、高速处理数据的现代化智能电子设备。由硬件和软件所组成,没有安装任何软件的计算机称为裸机。常见的形式有台式计算机、笔记本计算机。按照规模分为微型机、小型机、大型机、巨型机(超级计算机)等。1.2、计算机的组成计算机组成大致由“计算机硬件”和“计算机软件”组成①、计算机硬件:计算机硬件(Computer_计算机中数据的分类
文章浏览阅读1.5k次。快速导入和导出DWG,DXF,JPG,3DS格式文件,实现方案构思,效果图与施工图绘制的完美结合。专业用于 3D 建模,设计,创建和交流建筑,施工,工程等方面的创意。方便的推拉功能,设计师通过一个图形就可以方便的生成3D几何体,无需进行复杂的三维建模。适用范围广阔,可以应用在建筑,规划,园林,景观,室内以及工业设计等领域。具有草稿,线稿,透视,渲染等不同显示模式。_sketchup_pro2023 m1