SpringBoot开发手册
SpringBoot
这篇文章,介绍了通过SpringBoot开发的具体流程,和SpringBoot中一些常见的知识点
1、第一个HelloWorld程序
SpringBoot项目创建
Spring官网创建
https://start.spring.io/
不推荐
IDEA的Spring Initializr
File->New->Project->Spring Initializr
中途可以选择需要的组件
SpringBoot目录介绍
初始化后项目的目录
一般情况下项目的目录结构
com+- example+- myproject+- Application.java|+- domain| +- Customer.java| +- CustomerRepository.java|+- service| +- CustomerService.java|+- controller| +- CustomerController.java| +- config| +- swagerConfig.java|
Application.java
是项目的启动类- domain目录主要用于实体(Entity)与数据访问层(Repository)
- service 层主要是业务类代码
- controller 负责页面访问控制
- config 目录主要放一些配置类
新建一个Controller
新建controller包,并创建一个HelloController
增加@RestController
注解
- 这个
@RestController
注解,就是@Controller
+@ResponseBody
// @Controller
// @ResponseBody
// 使用@RestController注解,可以替代COntroller 和ResponseBody注解
@RestController
public class HelloController {@RequestMapping("/hello")public String hello() {return "hello springboot";}
}
修改配置文件application.propertise
,将端口改为2333
server.port=2333
运行测试
小结
了解了SpringBoot项目的创建
了解了注解
@RestController
,既可以让类被Spring扫描到,又可以让返回请求不跳转到页面,而是在浏览器上显示返回内容
2、RestFul风格
RESTful Web 服务与传统的 MVC 开发一个关键区别是返回给客户端的内容的创建方式:传统的 MVC 模式开发会直接返回给客户端一个视图,但是 RESTful Web 服务一般会将返回的数据以 JSON 的形式返回,这也就是现在所推崇的前后端分离开发。
程序实例
book实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {private int id;private String name;
}
BookController:
@RestController
@RequestMapping("/RestFul")
public class BookController {private List<Book> books = new ArrayList<Book>();/**** @param book 前端传入的是json类型数据* 而使用RequestBody,就能将Json类型数据反序列化为合适的Java对象* @return*/@PostMapping("/add")public ResponseEntity<List<Book>> addBook(@RequestBody Book book) {books.add(book);return ResponseEntity.ok(books);}@DeleteMapping("/del/{id}")public ResponseEntity deleteBookById(@PathVariable("id") int id) {books.remove(0);return ResponseEntity.ok(books);}@GetMapping("/get")public ResponseEntity getBookByName(@RequestParam("name")String name) {List<Book> list = books.stream().filter(book -> book.getName().equals(name)).collect(Collectors.toList());return ResponseEntity.ok(list);}//上面的也可以改成RestFul形式@GetMapping("/get/{name}")public ResponseEntity getBookByName(@PathVariable("name")String name) {List<Book> list = books.stream().filter(book -> book.getName().equals(name)).collect(Collectors.toList());return ResponseEntity.ok(list);}@GetMapping("/list")public ResponseEntity getBookList() {return ResponseEntity.ok(books);}
}
@RestController
**将返回的对象数据直接以 JSON 或 XML 形式写入 HTTP 响应(Response)中。**绝大部分情况下都是直接以 JSON 形式返回给客户端,很少的情况下才会以 XML 形式返回。转换成 XML 形式还需要额为的工作,上面代码中演示的直接就是将对象数据直接以 JSON 形式写入 HTTP 响应(Response)中。关于@Controller
和@RestController
的对比,我会在下一篇文章中单独介绍到(@Controller
+@ResponseBody
=@RestController
)。@RequestMapping
:上面的示例中没有指定 GET 与 PUT、POST 等,因为**@RequestMapping
默认映射所有HTTP Action**,你可以使用@RequestMapping(method=ActionType)
来缩小这个映射。@PostMapping
实际上就等价于@RequestMapping(method = RequestMethod.POST)
,同样的@DeleteMapping
,@GetMapping
也都一样,常用的 HTTP Action 都有一个这种形式的注解所对应。@PathVariable
:取url地址中的参数。@RequestParam
url的查询参数值。@RequestBody
:可以将 *HttpRequest* body 中的 JSON 类型数据反序列化为合适的 Java 类型。
ResponseEntity
: 表示整个HTTP Response:状态码,标头和正文内容。我们可以使用它来自定义HTTP Response 的内容(作用)。
测试:
使用postman进行测试:
小结
学习了:
@GetMapping,@DeleteMapping,@PostMapping
等注解
@PathVariable
用来获取URL中的参数地址
@RequestParam
url查询中的参数(但这种方式,URL的请求就不是restful风格的了)
@RequestBody
可以将 *HttpRequest* body 中的 JSON 类型数据反序列化为合适的 Java 类型
ResponseEntity
: 表示整个HTTP Response:状态码,标头和正文内容。我们可以使用它来自定义HTTP Response 的内容。
3、SpringBoot读取配置文件
使用@Value
my-phone: 18120194475
@Value("my-phone")private String phoneNum;
这种方式,Spring不推荐
Spring建议使用一下方式
使用@ConfigurationProperties
配置文件:
server:port: 8081my-phone: 18120194475library:name: FARO_Z图书馆books:- id: 1name: 悲惨世界- id: 2name: 合金弹头
编写一个实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix ="library")
@Component
@PropertySource("application.yml")
public class Library {private String name;private List<Book> books;
}
@Component
表示将该类识别为一个Bean
@ConfigurationProperties
用于绑定属性,其中prefix表示所绑定的属性的前缀
@PropertySource(value = "application.yml")
表示配置文件路径。
编写一个controller进行测试:
@RestController
public class LibraryController {@Autowiredprivate Library lib;@GetMapping("/lib")public String getLib() {return lib.toString();}
}
@Autowired
如果要用配置好的实体类的话,一定要写,这样才可以绑定
测试结果:
小结
@ConfigurationProperties(prefix="")
:用于绑定属性,其中prefix表示所绑定的属性的前缀
@PropertySource(value"")
:表示噢诶之文件的路径
@Autowired
:对于想要使用配置的属性,一定要使用@Autowired绑定
再给出配置文件的优先级:
4、异常处理
4.1 、SpringBoot异常处理几种方式
https://snailclimb.gitee.io/springboot-guide/#/./docs/advanced/springboot-handle-exception
4.2、SpringBoot异常处理在实际项目中的应用
https://snailclimb.gitee.io/springboot-guide/#/./docs/advanced/springboot-handle-exception-plus
5、JPA
这里我先暂时跳过,先以只用Mybatis为主
6、过滤器和拦截器
6.1、实现过滤器
在servlet中,已经对过滤器有了了解
Filter 过滤器主要是用来过滤用户请求的,它允许我们对用户请求进行前置处理和后置处理,比如实现 URL 级别的权限控制、过滤非法请求等等。
Filter 过滤器是面向切面编程——AOP 的具体实现
自定义filter的话,只要实现javax.Servlet.Filter
接口,然后重写里面的三个方法即可:
public interface Filter {//初始化过滤器后执行的操作default void init(FilterConfig filterConfig) throws ServletException {}// 对请求进行过滤void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;// 销毁过滤器后执行的操作,主要用户对某些资源的回收default void destroy() {}
}
过滤器是如何实现拦截的
Filter
接口中有一个叫做 doFilter
的方法,这个方法实现了对用户请求的过滤。具体流程大体是这样的:
- 用户发送请求到 web 服务器,请求会先到过滤器;
- 过滤器会对请求进行一些处理比如过滤请求的参数、修改返回给客户端的 response 的内容、判断是否让用户访问该接口等等。
- 用户请求响应完毕。
- 进行一些自己想要的其他操作。
编写过滤器
这里我们自定义一个过滤器:
@Component
public class MyFilter implements Filter {//这个是SLF4J 是类似log4j的日志实现private final Logger logger = LoggerFactory.getLogger(MyFilter.class);@Overridepublic void init(FilterConfig filterConfig) throws ServletException {logger.info("初始化过滤器:"+filterConfig.getFilterName());}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {logger.info("过滤器开始对请求进行处理");HttpServletRequest req = (HttpServletRequest) servletRequest;System.out.println("请求接口为:"+req.getRequestURI());long start = System.currentTimeMillis();//放行filterChain.doFilter(servletRequest,servletResponse);long end = System.currentTimeMillis();System.out.println("用户请求结束,请求处理耗时:"+Long.valueOf((end-start))+"ms");}@Overridepublic void destroy() {logger.info("销毁过滤器");}
}
1、手动注册配置实现
配置文件中注册自定义的过滤器:
@Configuration
public class MyFilterConfig {@AutowiredMyFilter myFilter;public FilterRegistrationBean<MyFilter> thirdFilter() {FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();filterRegistrationBean.setFilter(myFilter);filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));return filterRegistrationBean;}}
2、注解实现
在自定义的Filter上,加上@WebFilter
注解
别忘记加上@Component
注解,不然Spring无法扫描到,就无法实例化,就没有用:
@WebFilter(filterName = "MyFilter",urlPatterns = "/*")
@Component
public class MyFilter implements Filter {...
}
其实,也可以不添加@Component
注解,而是在启动类上,添加@ServletComponentScan
注解,这样,Spring就会自动去找和Servlet
相关的类,然后对它们进行实例化
不添加@Component注解:
@WebFilter(filterName = "MyFilter",urlPatterns = "/*")
public class MyFilter implements Filter {//不添加@Component注解...
}
而是为启动类添加@ServletComponentScan
注解:
@SpringBootApplication
@ServletComponentScan
public class StudyApplication {public static void main(String[] args) {SpringApplication.run(StudyApplication.class, args);}
}
一般,还是建议加@Component
定义多个拦截器,决定执行顺序
1、配置类方式
在配置文件中调用setOrder
,来设置启动优先级
2、注解方式
只要在过滤器上加上一个@Order(优先级)
注解,就可以决定filter启用顺序
Filter1启动优先级设置为1:
@WebFilter(filterName = "MyFilter2",urlPatterns = "/*")
@Order(1)
@Component
public class MyFilter2 implements Filter {}
FIlter2启动优先级设置为2:
@WebFilter(filterName = "MyFilter",urlPatterns = "/*")
@Order(2)
@Component
public class MyFilter implements Filter {}
测试:
6.2、实现拦截器
拦截器(Interceptor)同 Filter 过滤器一样,它俩都是面向切面编程——AOP 的具体实现(AOP切面编程只是一种编程思想而已)。
过滤器和拦截器的区别
- 过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。(筛子)
- 拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。(关卡)
自定义拦截器
要自定义Interceptor的话,必须:
实现org.springframework.web.servlet.HandlerInterceptor接口
或继承 org.springframework.web.servlet.handler.HandlerInterceptorAdapter类,
且要重写下面三个方法:
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView)public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)
注意: ***preHandle***方法返回 true或 false。如果返回 true,则意味着请求将继续到达 Controller 被处理。
LoginInterceptor
用于过滤所有请求:
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {long startTime = System.currentTimeMillis();System.out.println("\n-------- LogInterception.preHandle --- ");System.out.println("Request URL: " + request.getRequestURL());System.out.println("Start Time: " + System.currentTimeMillis());request.setAttribute("startTime", startTime);return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("\n-------- LogInterception.postHandle --- ");System.out.println("Request URL: " + request.getRequestURL());// You can add attributes in the modelAndView// and use that in the view page}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("\n-------- LogInterception.afterCompletion --- ");long startTime = (Long) request.getAttribute("startTime");long endTime = System.currentTimeMillis();System.out.println("Request URL: " + request.getRequestURL());System.out.println("End Time: " + endTime);System.out.println("Time Taken: " + (endTime - startTime));}
}
OldLoginInterceptor
,旧连接拦截器,一旦访问这个旧的连接,就会转发到 /admin/login:
public class OldLoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("\n-------- OldLoginInterceptor.preHandle --- ");System.out.println("Request URL: " + request.getRequestURL());System.out.println("Sorry! This URL is no longer used, Redirect to /admin/login");//getContextPath()获取的是 http://localHost。。。 即uri前面的东西//这里,当访问旧的废弃链接的时候,直接跳转到 /admin/login 的位置上去response.sendRedirect(request.getContextPath()+"/admin/login");return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}
拦截后,应该是下面这个过程:
AdminInterceptor
:
public class AdminInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("\n-------- AdminInterceptor.preHandle --- ");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}
配置类配置拦截器:
拦截器的配置类需要实现WebMvcConfigurer
接口
然后,重写里面的addInterceptors
方法,来配置拦截器
配置类里,可以配置每个拦截器需要拦截的路径和忽略的路径:
注意:配置类别忘记加@Configuration
注解
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {//这里不添加 addPathPatterns(),就是所有路径都进行过滤registry.addInterceptor(new LoginInterceptor());registry.addInterceptor(new OldLoginInterceptor()).addPathPatterns("/admin/oldLogin");//excludePathPatterns是设置的忽略的路径registry.addInterceptor(new AdminInterceptor()).addPathPatterns("/admin/*").excludePathPatterns("/admin/oldLogin");}
}
定义Controller:
@Controller
public class LoginController {@RequestMapping(value = {"/","/test"})public String test(Model model) {System.out.println("\n-------- MainController.test --- ");System.out.println(" ** You are in Controller ** ");return "test";}@Deprecated@RequestMapping("/admin/oldLogin")public String oldLogin(Model model) {//下面永远不会运行到//因为早就被拦截器拦截了return "oldLogin";}@RequestMapping("/admin/login")public String login(Model model) {System.out.println("\n-------- MainController.login --- ");System.out.println(" ** You are in Controller ** ");return "login";}
}
thymeleaf模板引擎:
如果之间创建项目的时候,没有添加thymeleaf依赖
那一定要进行下面的步骤:
- 导入thymeleaf依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 开发环境,关闭thymeleaf缓存
#开发环境设置thymeleaf缓存不可用,加快响应速度
spring:thymeleaf:cache: false
test.html:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8" /><title>Spring Boot Mvc Interceptor example</title></head><body><div style="border: 1px solid #ccc;padding: 5px;margin-bottom:10px;"><a th:href="@{/}">Home</a> | <a th:href="@{/admin/oldLogin}">/admin/oldLogin (OLD URL)</a> </div><h3>Spring Boot Mvc Interceptor</h3><span style="color:blue;">Testing LogInterceptor</span><br/><br/>See Log in Console..</body>
</html>
login.html:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8" /><title>Spring Boot Mvc Interceptor example</title></head><body><div style="border: 1px solid #ccc;padding: 5px;margin-bottom:10px;"><a th:href="@{/}">Home</a> | <a th:href="@{/admin/oldLogin}">/admin/oldLogin (OLD URL)</a> </div><h3>This is Login Page</h3><span style="color:blue">Testing OldLoginInterceptor & AdminInterceptor</span><br/><br/>See more info in the Console.</body>
</html>
测试:
输入oldLogin:
回车,就会跳转到login,说明oldLogin被拦截了:
小结
- 了解了过滤器,拦截器的区别:
一个是筛子,一个是关卡
- 学习了SpringBoot中过滤器的配置:
- 创建自定义过滤器类,实现Filter接口,复习而其中三个方法
- 使用注解或者手动配置配置文件
- 注解:@WebFilter(filterName = “MyFilterWithAnnotation”, urlPatterns = “/api/*”)
- 配置文件的方式,翻阅上面的文档
- 学习了SpringBoot中拦截器的配置:
- 创建自定义拦截器,并实现
HanderInterceptor
接口- 创建拦截器配置类,实现WebMvcConfigurer接口,为每个拦截器进行配置(配置拦截路径或者忽略路径)
7、整合Mybatis
这里先给出SpringBoot项目的完整项目结构:
下面是整合步骤:
- 新建数据库表
person
:
DROP TABLE IF EXISTS `user`;
CREATE TABLE user (
`id` int(15) AUTO_INCREMENT,
`name` VARCHAR(255) DEFAULT NULL,
`pwd` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY(id)
)
- 导入Mybatis和mysql的依赖:
也可以在新建项目的时候,导入相关的模块
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.2</version>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>
- 注意Maven静态资源到处问题
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins><resources><!--此处的配置是识别到mapper.xml文件,也可以在application.properties中配置--><!--即静态资源导出问题--><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource></resources></build>
- 修改配置文件:
spring:datasource:url: jdbc:mysql://localhost:3306/springboot-mybatis?useUnicode=true&characterEncoding=utf-8username: adminpassword: 123driver-class-name: com.mysql.cj.jdbc.Driver
- 先测试一下,看看有没有配置成功:
@SpringBootTest
class SpringbootStudy3ApplicationTests {@AutowiredDataSource dataSource;@Testvoid contextLoads() throws SQLException {System.out.println(dataSource.getClass());System.out.println(dataSource.getConnection());}
}
- 编写Mapper接口:
注意:根据官方文档,mapper接口,一定要加上@Mapper
注解和@Repository
注解
@Repository
注解的功能和@Component
一样,只是@Repository
是用在Dao层的
@Mapper
@Repository //和@Component功能一样,只是用在Dao层
public interface UserMapper {List<User> queryUserList();User queryUserById(@Param("id") int id);int addUser(User user);int updateUser(User user);int deleteUser(int id);}
- 编写xml实现
这里的xml实现,是放在 resources/mybatis/mapper 下的
想要和接口绑定,还需要在配置文件中配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.faroz.mapper.UserMapper"><select id="queryUserList" resultType="User">select * from user</select><select id="queryUserById" parameterType="_int" resultType="User">select * from user where id=#{id}</select><insert id="addUser" parameterType="User">insert into user values(#{id},#{name},#{pwd})</insert><update id="updateUser">update userset name=#{name},pwd=#{pwd}where id=#{id}</update><delete id="deleteUser" parameterType="_int">delete from user where id=#{id}</delete></mapper>
- 配置Mybatis
上面的yml配置其实没有配置完,只配置了一个数据源,其实,还要再配置一下Mybatis,
比如上面的xml和接口的配置问题
spring:datasource:url: jdbc:mysql://localhost:3306/springboot-mybatis?useUnicode=true&characterEncoding=utf-8username: adminpassword: 123driver-class-name: com.mysql.cj.jdbc.Driver# 整合Mybatis
mybatis:type-aliases-package: top.faroz.pojomapper-locations: classpath:mybatis/mapper/*.xml
- 编写Controller进行测试
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserMapper mapper;@GetMapping("/list")public ResponseEntity queryUserList() {List<User> list = mapper.queryUserList();return ResponseEntity.ok(list);}@GetMapping("/list/{id}")public ResponseEntity queryUserById(@PathVariable("id")int id) {User user = mapper.queryUserById(id);return ResponseEntity.ok(user);}@PostMapping("/add")public String addUser(@RequestBody User user) {mapper.addUser(user);return "添加成功!";}@PostMapping("/update")public String updateUser(@RequestBody User user) {mapper.updateUser(user);return "修改成功!";}@GetMapping("/delete/{id}")public String deleteUser(@PathVariable("id") int id) {mapper.deleteUser(id);return "删除成功!";}
}
SpringBoot开发手册相关推荐
- springboot 2中文手册_熬夜整理了一套最新版的Java面试题和开发手册(附答案)...
12年开始写代码,前鹅长打工仔,现在就职一家创业公司,爱好就是写写技术博客,虽很水也有不少人围观,认识了不少真大佬. 昨晚得知王磊兄的推荐,连夜整理了一套「最新的 Java 面试题」,还很热乎,基本上 ...
- java string 占位符_驳《阿里「Java开发手册」中的1个bug》?
前两天写了一篇关于<阿里Java开发手册中的 1 个bug>的文章,评论区有点炸锅了,基本分为两派,支持老王的和质疑老王的. 首先来说,无论是那一方,我都真诚的感谢你们.特别是「二师兄」, ...
- SpringBoot开发微信公众号
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 在讲微信公众号开发之前,先来大概了解一下微信公众号.微信公 ...
- 驳《阿里「Java开发手册」中的1个bug》?
这是我的第 211 期分享 作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 前两天写了一篇关于<阿里Java开发手册中的 1 ...
- 一个基于SpringBoot开发的RBAC系统,非常适合新手入门JavaWeb代码审计实战的系统,长文警告,要好好学习。
嗨,大家好,我是闪石星曜CyberSecurity创始人Power7089. 欢迎大家搜索我的微信公众号:闪石星曜CyberSecurity 本文是[炼石计划@Java代码审计]内部圈子原创课程,现分 ...
- Freemarker 教程(一)-模板开发手册
Hello,大家好,我是课代表.今天又是原创分享.欢迎关注我的公众号:Java课代表,更多干货等你来看. 本文是Freemarker系列的第一篇,面向模板开发人员,主要介绍 FreeMarker 所使 ...
- HummerRisk 入门3:开发手册
本文是 HummerRisk 的开发手册,介绍项目的结构及如何配置 HummerRisk 的开发环境和开发中的注意事项,快速参与到 HummerRisk 项目的开发中来. 一.项目结构 二.配置开发环 ...
- android 设置setmultichoiceitems设置初始化勾选_阿里巴巴Java开发手册建议创建HashMap时设置初始化容量,但是多少合适呢?...
集合是Java开发日常开发中经常会使用到的,而作为一种典型的K-V结构的数据结构,HashMap对于Java开发者一定不陌生. 关于HashMap,很多人都对他有一些基本的了解,比如他和hashtab ...
- 《HTML5开发手册》——2.4 初学者“菜谱”:使用address元素提供通信信息
本节书摘来自异步社区<HTML5开发手册>一书中的第2章,第2.4节,作者: [美]Chuck Hudson , [英]Tom Leadbetter 更多章节内容可以访问云栖社区" ...
最新文章
- rac安装grid报INS-41112错误
- iphone开发之数据库CoreData
- 支付方式之线上和线下
- 北京第一个公共云计算平台即将诞生
- 运维人,你应该了解的三张武功心法图(转载)
- pcl画圆球_PCL之轨迹绘制(二)
- centos配置java环境变量_【开发笔记】-CentOS配置Java环境变量
- android程序设计背景,android – 以可编程方式设置drawable作为背景
- eps导入坐标文件_EPS一些简单地物的编辑
- 计算机博弈程序python_程序员大神们的经典编程语录
- sniffer Pro4.7.5最完整安装教程
- matlab 数据正态性检验
- OceanBase 4.0 all-in-one 版本快速尝鲜安装步骤
- java接口自动化测试-导入xslx模板进行批量检索
- pcie 对rc操作的ops
- Dbeaver连接Clickhouse无法下载/更新驱动
- 高德地图获取地址坐标
- C Primer Plus 第3章 数据和C-编程练习
- 解决ajax请求返回Json无法解析字符的问题
- Ubuntu-如何隐藏文件/文件夹
热门文章
- 多种风机功率曲线的过滤方法
- Swift WKWebView
- 非编网 制作服务器,影视编辑业视频编辑制作服务器 edius非编系统 4K非线性编辑机...
- MATLAB导入任意省市地图(Shp数据)并从EXCEL中导入经纬度数据在图上手动加点
- Java 泛型中的 PECS 原则
- 架构 | 前后端分离与前端工程化
- 如何在oracle数据库创建序列,Oracle创建和使用序列
- 为什么电脑点桌面软件跳计算机,电脑玩游戏为什么会跳桌面
- heywhale数据结构学习--线性表
- 预备打工人之SystemC学习(三) 基本语法