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|
  1. Application.java是项目的启动类
  2. domain目录主要用于实体(Entity)与数据访问层(Repository)
  3. service 层主要是业务类代码
  4. controller 负责页面访问控制
  5. 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);}
}
  1. @RestController **将返回的对象数据直接以 JSON 或 XML 形式写入 HTTP 响应(Response)中。**绝大部分情况下都是直接以 JSON 形式返回给客户端,很少的情况下才会以 XML 形式返回。转换成 XML 形式还需要额为的工作,上面代码中演示的直接就是将对象数据直接以 JSON 形式写入 HTTP 响应(Response)中。关于@Controller@RestController 的对比,我会在下一篇文章中单独介绍到(@Controller +@ResponseBody= @RestController)。
  2. @RequestMapping :上面的示例中没有指定 GET 与 PUT、POST 等,因为**@RequestMapping默认映射所有HTTP Action**,你可以使用@RequestMapping(method=ActionType)来缩小这个映射。
  3. @PostMapping实际上就等价于 @RequestMapping(method = RequestMethod.POST),同样的 @DeleteMapping ,@GetMapping也都一样,常用的 HTTP Action 都有一个这种形式的注解所对应。
  4. @PathVariable :取url地址中的参数。@RequestParam url的查询参数值。
  5. @RequestBody:可以将 *HttpRequest* body 中的 JSON 类型数据反序列化为合适的 Java 类型。

  1. ResponseEntity: 表示整个HTTP Response:状态码,标头和正文内容。我们可以使用它来自定义HTTP Response 的内容(作用)。

测试:

使用postman进行测试:

小结

学习了:

@GetMapping,@DeleteMapping,@PostMapping等注解

@PathVariable用来获取URL中的参数地址

@RequestParamurl查询中的参数(但这种方式,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 的方法,这个方法实现了对用户请求的过滤。具体流程大体是这样的:

  1. 用户发送请求到 web 服务器,请求会先到过滤器;
  2. 过滤器会对请求进行一些处理比如过滤请求的参数、修改返回给客户端的 response 的内容、判断是否让用户访问该接口等等。
  3. 用户请求响应完毕。
  4. 进行一些自己想要的其他操作。

编写过滤器

这里我们自定义一个过滤器:

@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***方法返回 truefalse。如果返回 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依赖

那一定要进行下面的步骤:

  1. 导入thymeleaf依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  1. 开发环境,关闭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>&nbsp;&nbsp; | &nbsp;&nbsp;<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>&nbsp;&nbsp; | &nbsp;&nbsp;<a th:href="@{/admin/oldLogin}">/admin/oldLogin (OLD URL)</a>  </div><h3>This is Login Page</h3><span style="color:blue">Testing OldLoginInterceptor &amp; AdminInterceptor</span><br/><br/>See more info in the Console.</body>
</html>

测试:

输入oldLogin:

回车,就会跳转到login,说明oldLogin被拦截了:

小结

  • 了解了过滤器,拦截器的区别:

一个是筛子,一个是关卡

  • 学习了SpringBoot中过滤器的配置:
  1. 创建自定义过滤器类,实现Filter接口,复习而其中三个方法
  2. 使用注解或者手动配置配置文件
    • 注解:@WebFilter(filterName = “MyFilterWithAnnotation”, urlPatterns = “/api/*”)
    • 配置文件的方式,翻阅上面的文档
  • 学习了SpringBoot中拦截器的配置:
  1. 创建自定义拦截器,并实现HanderInterceptor接口
  2. 创建拦截器配置类,实现WebMvcConfigurer接口,为每个拦截器进行配置(配置拦截路径或者忽略路径)

7、整合Mybatis

这里先给出SpringBoot项目的完整项目结构:

下面是整合步骤:

  1. 新建数据库表 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)
)
  1. 导入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>
  1. 注意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>
  1. 修改配置文件:
spring:datasource:url: jdbc:mysql://localhost:3306/springboot-mybatis?useUnicode=true&characterEncoding=utf-8username: adminpassword: 123driver-class-name: com.mysql.cj.jdbc.Driver
  1. 先测试一下,看看有没有配置成功:
@SpringBootTest
class SpringbootStudy3ApplicationTests {@AutowiredDataSource dataSource;@Testvoid contextLoads() throws SQLException {System.out.println(dataSource.getClass());System.out.println(dataSource.getConnection());}
}

  1. 编写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);}
  1. 编写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>
  1. 配置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
  1. 编写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开发手册相关推荐

  1. springboot 2中文手册_熬夜整理了一套最新版的Java面试题和开发手册(附答案)...

    12年开始写代码,前鹅长打工仔,现在就职一家创业公司,爱好就是写写技术博客,虽很水也有不少人围观,认识了不少真大佬. 昨晚得知王磊兄的推荐,连夜整理了一套「最新的 Java 面试题」,还很热乎,基本上 ...

  2. java string 占位符_驳《阿里「Java开发手册」中的1个bug》?

    前两天写了一篇关于<阿里Java开发手册中的 1 个bug>的文章,评论区有点炸锅了,基本分为两派,支持老王的和质疑老王的. 首先来说,无论是那一方,我都真诚的感谢你们.特别是「二师兄」, ...

  3. SpringBoot开发微信公众号

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 在讲微信公众号开发之前,先来大概了解一下微信公众号.微信公 ...

  4. 驳《阿里「Java开发手册」中的1个bug》?

    这是我的第 211 期分享 作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 前两天写了一篇关于<阿里Java开发手册中的 1 ...

  5. 一个基于SpringBoot开发的RBAC系统,非常适合新手入门JavaWeb代码审计实战的系统,长文警告,要好好学习。

    嗨,大家好,我是闪石星曜CyberSecurity创始人Power7089. 欢迎大家搜索我的微信公众号:闪石星曜CyberSecurity 本文是[炼石计划@Java代码审计]内部圈子原创课程,现分 ...

  6. Freemarker 教程(一)-模板开发手册

    Hello,大家好,我是课代表.今天又是原创分享.欢迎关注我的公众号:Java课代表,更多干货等你来看. 本文是Freemarker系列的第一篇,面向模板开发人员,主要介绍 FreeMarker 所使 ...

  7. HummerRisk 入门3:开发手册

    本文是 HummerRisk 的开发手册,介绍项目的结构及如何配置 HummerRisk 的开发环境和开发中的注意事项,快速参与到 HummerRisk 项目的开发中来. 一.项目结构 二.配置开发环 ...

  8. android 设置setmultichoiceitems设置初始化勾选_阿里巴巴Java开发手册建议创建HashMap时设置初始化容量,但是多少合适呢?...

    集合是Java开发日常开发中经常会使用到的,而作为一种典型的K-V结构的数据结构,HashMap对于Java开发者一定不陌生. 关于HashMap,很多人都对他有一些基本的了解,比如他和hashtab ...

  9. 《HTML5开发手册》——2.4 初学者“菜谱”:使用address元素提供通信信息

    本节书摘来自异步社区<HTML5开发手册>一书中的第2章,第2.4节,作者: [美]Chuck Hudson , [英]Tom Leadbetter 更多章节内容可以访问云栖社区" ...

最新文章

  1. rac安装grid报INS-41112错误
  2. iphone开发之数据库CoreData
  3. 支付方式之线上和线下
  4. 北京第一个公共云计算平台即将诞生
  5. 运维人,你应该了解的三张武功心法图(转载)
  6. pcl画圆球_PCL之轨迹绘制(二)
  7. centos配置java环境变量_【开发笔记】-CentOS配置Java环境变量
  8. android程序设计背景,android – 以可编程方式设置drawable作为背景
  9. eps导入坐标文件_EPS一些简单地物的编辑
  10. 计算机博弈程序python_程序员大神们的经典编程语录
  11. sniffer Pro4.7.5最完整安装教程
  12. matlab 数据正态性检验
  13. OceanBase 4.0 all-in-one 版本快速尝鲜安装步骤
  14. java接口自动化测试-导入xslx模板进行批量检索
  15. pcie 对rc操作的ops
  16. Dbeaver连接Clickhouse无法下载/更新驱动
  17. 高德地图获取地址坐标
  18. C Primer Plus 第3章 数据和C-编程练习
  19. 解决ajax请求返回Json无法解析字符的问题
  20. Ubuntu-如何隐藏文件/文件夹

热门文章

  1. 多种风机功率曲线的过滤方法
  2. Swift WKWebView
  3. 非编网 制作服务器,影视编辑业视频编辑制作服务器 edius非编系统 4K非线性编辑机...
  4. MATLAB导入任意省市地图(Shp数据)并从EXCEL中导入经纬度数据在图上手动加点
  5. Java 泛型中的 PECS 原则
  6. 架构 | 前后端分离与前端工程化
  7. 如何在oracle数据库创建序列,Oracle创建和使用序列
  8. 为什么电脑点桌面软件跳计算机,电脑玩游戏为什么会跳桌面
  9. heywhale数据结构学习--线性表
  10. 预备打工人之SystemC学习(三) 基本语法