springmvc学习笔记(简介及使用)
springmvc学习笔记(简介及使用)
工作之余, 回顾了一下springmvc的相关内容, 这次也为后面复习什么的做个标记, 也希望能与大家交流学习, 通过回帖留言等方式表达自己的观点或学习心得.
本文如若有误, 也敬请大家不吝赐教.
1 mvc框架通常要做哪些事情
- 将URL映射到Java类或Java方法
- 封装用户提交的数据
- 处理请求, 调用相关的业务处理, 并封装响应的数据
- 将要相应的数据进行渲染
2 springmvc优点和特点
- 与spring无缝集成(IoC, AOP)
- 约定优于配置
- 性能较struts2好
- 设计中的角色或职责划分明确
- Restful
- JUnit测试
- 异常处理
- 本地化, 国际化
- 数据验证, 类型转换等
- 拦截器
- 使用的人已经相当多, 使用的公司也相当多
- 简单, 便捷, 易学
3 springmvc处理请求流程
springmvc框架基于请求驱动, 所有设计都围绕一个中央Servlet展开, 它负责将请求分发给各处理器(页面控制器, Controller). 下图中展示了springmvc处理请求的流程, 图中的Front Controller(前端控制器)正是springmvc的DispatcherServlet
; Controller称为处理器或应用控制器或页面控制器, 由它来处理具体的请求, 返回模型数据; View Template为具体视图, 用于展示数据, 响应请求.
具体处理请求步骤:
- 用户发送请求, 被前端控制器拦截, 前端控制器根据请求的信息选择相应的页面控制器, 并将请求委托给此页面控制器来处理.
- 页面控制器接收到请求后, 首先收集并绑定请求参数到一个命令对象(表单对象)中, 并进行验证转换等操作, 然后将命令对象(表单对象)委托给业务对象进行处理, 最后返回一个
ModelAndView
对象. - 前端控制器根据返回的视图名, 选择相应的视图进行渲染, 并将模型数据传入到视图中以便展示.
- 前端控制器将响应结果返回给用户.
至此, 整个请求流程结束. 当然还有一些细节的问题, 需要我们了解, 比如: 前端控制器如何选择页面控制器, 前端控制器如何根据页面控制器返回的视图名选择相应的视图进行渲染, 等等. 带着这些问题, 我们将springmvc处理请求的流程图转换为架构图讨论一下.
先上一段主要代码哈,
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
/**
* 处理实际的请求分发到处理器.
* 要获得具体的Handler, 需要先使用servlet的HandlerMappings.
* 要获得HandlerAdpter, 需要先在servlet加载的各HandlerAdapter中查找, 找到第一个支持此Handler的Adapter.
* 所有的HTTP方法都通过这个方法来处理的. 这个方法中, 由HandlerAdapter或Handler自己来决定哪些方法可以被调用.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
// 检查请求是否为multipart(文件上传)
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
// 图中2,3两步, 通过HandlerMappsing映射, 获取处理请求的Handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 图中步骤4, 将Handler包装成Adapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 前置拦截器
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 图中5,6,7步骤, 由HandlerAdapter调用真正的处理器处理请求, 并返回ModelAndView对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 后置拦截器
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
// 图中8,9,10,11步骤, 处理Handler的处理结果, 这个结果可能是一个ModelAndView对象, 还可能是一个异常
// 第8,9步, 由viewResolver解析视图
// viewResolver.resolveViewName(viewName, locale)
// 第10, 11步, 传入Model, 并渲染视图
// view.render(mv.getModelInternal(), request, response);
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
// 完成时拦截器
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
- 步骤①,
DispatcherServlet
作为前端控制器, 统一的请求接收点, 控制全局的请求流程. 接收到用户请求, 自己不做处理, 而是将请求委托给其他的处理器进行处理. - 步骤②③,
DispatcherServlet
通过HandlerMapping
(处理映射器), 将请求映射为一个HandlerExecutionChain
对象, 其中包括了页面控制器和对其配置的拦截器. - 步骤④,
DispatcherServlet
通过获得的Handler(处理器, 页面控制器, Controller), 查找一个合适的HandlerAdapter
(处理器适配器), 通过这个HandlerAdapter
调用Handler实际处理请求的方法. - 步骤⑤, 提取请求中的模型数据, 调用Handler实际处理请求的方法. 在调用方法时, 填充参数过程中, spring会根据配置做一些工作, 如: 数据转换, 数据格式化, 数据验证等.
- 步骤⑥⑦, Handler执行完成后, 将返回一个
ModelAndView
对象给DispatherServlet
.ModelAndView
对象中包含逻辑视图名或逻辑视图名和模型. - 步骤⑧, 根据
ModelAndView
对象选择一个合适的ViewResolver(视图解析器). - 步骤⑨,
ViewResolver
将ModelAndView
中的逻辑视图名解释成View
对象. ViewResolver
也是接口, 同样采用了策略模式, 这样就很容易切换其他的视图类型. - 步骤⑩⑪, 渲染视图时, 将
Model
数据传入视图中, 这里的Model数据是一个Map, 容易与各种视图类型相结合. - 步骤⑫, 最后, 由
DispatcherServlet
将最终的响应结果返回给用户.
通过这些步骤, springmvc依赖几个对象共同完成了请求到响应的工作流程, 对于开发者来说, 这些对象是不可见的, 开发者只需要关心Handler处理器(页面控制器)中对请求的处理业务即可.
4 第一个示例 Hello World
4.1 创建一个web工程
此示例项目使用maven管理, pom.xml依赖包配置如下:
<!-- spring版本 -->
<org.springframework.version>4.2.3.RELEASE</org.springframework.version>
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
<!-- 将commons-loggin换成了下面的logback -->
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- spring-mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.6.1</version>
</dependency>
4.2 spring监听配置及springmvc前端控制器DispatcherServlet配置
在web.xml文件中, 加入spring监听以及DispatcherServlet
前端控制器相关配置, 如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- springmvc前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 使此前端控制器拦截所有请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
对于DispatcherServlet
的配置,
- load-on-startup: 启动容器时初始化
DispatcherServlet
- url-pattern: 说明哪些请求会被
DispatcherServlet
所处理 - contextConfigLocation: springmvc配置文件, 默认文件为/WEB-INF/[servletName]-servlet.xml
4.3 applicationContext.xml、springmvc-servlet.xml、logback.xml
applicationContext.xml为根上下文配置文件, 暂未做bean的定义.
logback.xml为日志配置文件, 不做描述.
然后是springmvc的上下文配置springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 处理映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 视图解释器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
<!-- 定义一个bean, 即处理器(或控制器), 映射"/hello"请求 -->
<bean name="/hello" class="com.lizj.controller.HelloController"></bean>
</beans>
配置文件中, 配置了一个处理映射器BeanNameUrlHandlerMapping
, 这样可以Bean的name属性为url进行查找; 同时配置了处理器适配器SimpleControllerHandlerAdapter
, 以完成对处理器中实际处理方法的调用; 配置了视图解析器InternalResourceViewResolver
来解析视图, 将视图展示给用户.
最后定义了页面控制器HelloController
, 将其映射到了请求"/hello"上.
4.4 页面控制器HelloController
package com.lizj.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
/**
* HelloController作为一个页面控制器, 是一个实现Controller接口的页面控制器
* 它可以处理一个单一请求
*/
public class HelloController implements Controller {
/**
* 实现Controller接口中定义的方法
* 此方法返回一个ModelAndView对象,
* 此对象中, 包含着视图名和模型
*/
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("message", "everyone");
mv.setViewName("/WEB-INF/jsp/hello.jsp");
return mv;
}
}
在spring2.5以前的版本, 要实现一个页面控制器中通过实现Controller
接口, 此接口中有一个必定要实现的方法:
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
方法参数为HttpServletRequest
和HttpServletResponse
, 请求处理完成后, 返回ModelAndView
对象. 但是它只能处理一个单一的请求. 后面的示例中, 会介绍利用注解来定义Controller.
4.5 hello.jsp
在路径/WEB-INF/jsp下新建hello.jsp文件, 其主要代码如下:
<body>
Hello ${requestScope.message} <br>
</body>
访问页面, 显示Hello everyone, 表示访问成功.
4.6 基于注解的Controller示例
spring2.5引入了注解, 以@Controller
和@RequestMapping
定义处理器, 通过这种方式实现的处理器既不需要继承某个父类, 也不需要实现某个接口.
修改HelloController.java类, 如下:
package com.lizj.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* 基于注解的控制器
* 并可以接收多个请求
* @Controller注解表示此类是一个控制器
*/
Controller
public class HelloController {
/** 计数 */
private int count = 0;
/**
* RequestMapping注解用来映射请求的URL和方法
* 此处映射请求"/hello"
*/
@RequestMapping(value="/hello")
public ModelAndView hello() {
ModelAndView mv = new ModelAndView();
mv.addObject("message", "everyone");
mv.setViewName("/WEB-INF/jsp/hello.jsp");
System.out.println("count: " + count++);
return mv;
}
/**
* 映射请求"/hi"
*/
@RequestMapping(value="/hi")
public ModelAndView hi(String param) {
ModelAndView mv = new ModelAndView();
mv.addObject("message", param);
mv.setViewName("/WEB-INF/jsp/hi.jsp");
return mv;
}
}
@Controller
: 标识类为处理器类(页面控制器).
@RequestMapping
: 处理请求地址映射, 可映射到类, 也可映射到方法.
value="/hello"表示请求/hello由此方法处理
修改springmvc-servlet.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- spring自动扫描包路径com.lizj.controller下的所有包和类 -->
<context:component-scan base-package="com.lizj.controller"></context:component-scan>
<!-- annotation处理映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<!-- annotation处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
<!-- 视图解释器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
</beans>
由于使用了注解, 所以不再使用配置文件来定义bean. spring将自动扫描指定路径下的类, 查找基于注解的控制器类.
此配置文件中还定义了注解类型的处理映射器RequestMappingHandlerMapping
, 根据请求处理映射. 注解类型的控制器适配器RequestMappingHandlerAdapter
, 由它来完成@RequestMapping
注解方法的调用.
其实, 处理映射器和处理器适配器的使用可以更简便, 这里在是为了把springmvc所有组件都展示出来.
从两个示例中可以看出, 实现Controller
接口的页面控制器只能处理一个单一请求, 而@Controller
注解的页面控制器可以支持多个请求, 并且支持多样的方法名和方法签名, 更加灵活.
需要注意的是, 页面控制器是一个spring容器中的bean, 默认单例, 所以要注意在页面控制器类中使用成员变量的场景. 示例代码中的
count
成员变量就是为了说明这个问题.
4.7 关于...
4.7.1 上下文关系
在springmvc中, 每个DispatcherServlet
实例都会持有一个自己的上下文对象WebApplicationContext
, 而它又继承了根上下文(Root WebApplicationContext
), 从而继承了根上下文中定义的bean. 这些bean可以在DispatcherServlet
实例中被重载, 也可以在DispatcherServlet
实例定义新的bean.
当应用中只需要一个DispatcherServlet
时, 只配置一个根context对象也是可行的
此时, DispatcherServlet
初始化参数中, 可以配置一个空的contextConfigLocation来实现, 如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- springmvc前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 使此前端控制器拦截所有请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
4.7.2 HandlerMapping(处理映射器)
HandlerMapping
是个接口, 那就是可扩展的. 它的作用就是根据请求信息, 获取具体处理这个请求的处理器. 这个过程需要两个步骤: 一是注册处理器到HandlerMapping
中, 二是根据请求信息从已注册的处理器中查找对应的处理器.
在HandlerMapping
接口的实现中, 都定义了请求与处理器之间的映射关系. 比如BeanNameUrlHandlerMapping
定义了URLs和bean的name属性之间的映射关系, 而RequestMappingHandlerMapping
则主要是根据注解@RequestMapping
维护映射关系的.
对于HandlerMapping
接口中定义的方法
public abstract HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
返回值的类型为HandlerExecutionChain
, 从命名上也可以看出, 它是一个执行链, 这与struts2的设计是一样的, 实际的Action被许多一层层包装着. 从HandlerExecutionChain
原码可以看出, 一堆拦截器和一个实际的处理器. 在调用真正的处理器之前, 会遍历所有拦截器, 调用其preHandle
方法, 然后再调用真正的处理器对象.
4.7.3 HandlerAdapter(处理器适配器)
springmvc是通过HandlerAdapter
调用实际的处理器以及处理方法的.
HandlerAdapter
从命名上可以看出, 是适配器模式的应用, 为的就是可以使用不同类型的处理器, 比如实现Controller
接口的处理器或者通过注解@Controller
声明的处理器. 换句话说, 每种类型的处理器, 都会对应一个与自身类型匹配的处理器适配器. 它是个接口, 允许扩展. DispatcherServlet
访问处理器都是通过这个接口, 所以DispatcherServlet
不能包含针对任一类型处理器的特有代码.
DispatcherServlet
会根据处理器的类型查找HandlerAdapter
, 具体是通过HandlerAdapter
的supports
方法, 找到匹配的HandlerAdapter
之后, 会使用自身定义的策略, 确定处理器的具体方法, 并处理传入参数, 然后执行自身的handle
方法, 而在handle
中运用反射机制调用处理器的具体处理方法.
处理器的类型可以是任何对象类型, 这就使得, 来自第三方框架的处理器可以在无编码的前提下集成进来, 也支持基于注解的、不需要实现任何接口的处理器类型.
原文地址: http://www.cnblogs.com/lzj0616/p/6753406.html
springmvc学习笔记(简介及使用)的更多相关文章
- 史上最全的SpringMVC学习笔记
SpringMVC学习笔记---- 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于Spring ...
- springmvc学习笔记--REST API的异常处理
前言: 最近使用springmvc写了不少rest api, 觉得真是一个好框架. 之前描述的几篇关于rest api的文章, 其实还是不够完善. 比如当遇到参数缺失, 类型不匹配的情况时, 直接抛出 ...
- springmvc学习笔记---面向移动端支持REST API
前言: springmvc对注解的支持非常灵活和飘逸, 也得web编程少了以往很大一坨配置项. 另一方面移动互联网的到来, 使得REST API变得流行, 甚至成为主流. 因此我们来关注下spring ...
- SpringMVC:学习笔记(8)——文件上传
SpringMVC--文件上传 说明: 文件上传的途径 文件上传主要有两种方式: 1.使用Apache Commons FileUpload元件. 2.利用Servlet3.0及其更高版本的内置支持. ...
- springmvc学习笔记(常用注解)
springmvc学习笔记(常用注解) 1. @Controller @Controller注解用于表示一个类的实例是页面控制器(后面都将称为控制器). 使用@Controller注解定义的控制器有如 ...
- SpringMVC学习笔记之二(SpringMVC高级参数绑定)
一.高级参数绑定 1.1 绑定数组 需求:在商品列表页面选中多个商品,然后删除. 需求分析:功能要求商品列表页面中的每个商品前有一个checkbok,选中多个商品后点击删除按钮把商品id传递给Cont ...
- springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定
springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...
- springmvc学习笔记(19)-RESTful支持
springmvc学习笔记(19)-RESTful支持 标签: springmvc springmvc学习笔记19-RESTful支持 概念 REST的样例 controller REST方法的前端控 ...
- springMVC 学习笔记(一):springMVC 入门
springMVC 学习笔记(一):spring 入门 什么是 springMVC springMVC 是 spring 框架的一个模块,springMVC 和 spring 无需通过中间整合层进行整 ...
随机推荐
- 1821: [JSOI2010]Group 部落划分 Group
1821: [JSOI2010]Group 部落划分 Group Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1308 Solved: 627[Su ...
- CoreAnimation 寄宿图
#CoreAnimation 寄宿图 寄宿图:图层中所包含的图 by:旭宝爱吃鱼 针对于寄宿图我在这里只讨论contents属性以及Custom Drawing. contents content:内 ...
- RobotFramework中解析中文报错UnicodeDecodeError
在RobotFramework中解析一段包含中文的字符串时遇到下面的报错: FAIL : UnicodeDecodeError: 'ascii' codec can't decode byte 0xe ...
- HTML5学习笔记<六>: HTML5框架, 背景和实体
HTML5框架 1. 框架标签(frame): 框架对于页面的设计有着很大的作用 2. 框架集标签(<frameset>): 框架集标签定义如何将窗口分割为框架 每个frameset定义一 ...
- C++基础——C面向过程与C++面向对象编程01_圆面积求解
#include "iostream";//包含C++的头文件using namespace std;//使用命名空间std标准的命名空间(在这个命名空间中定义了很多标准定义)vo ...
- MCMC(三)MCMC采样和M-H采样
MCMC(一)蒙特卡罗方法 MCMC(二)马尔科夫链 MCMC(三)MCMC采样和M-H采样 MCMC(四)Gibbs采样(待填坑) 在MCMC(二)马尔科夫链中我们讲到给定一个概率平稳分布$\pi$ ...
- Alamofire源码解读系列(十)之序列化(ResponseSerialization)
本篇主要讲解Alamofire中如何把服务器返回的数据序列化 前言 和前边的文章不同, 在这一篇中,我想从程序的设计层次上解读ResponseSerialization这个文件.更直观的去探讨该功能是 ...
- Spring execution表达式
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) th ...
- Luogu2723丑数Humble Numbers【归并排序】
Luogu2723丑数Humble Numbers 题目背景 对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S.这个正整数集合包 ...
- Ubuntu下php网站运行环境搭建
第一步:查看是否安装lamp相关软件: dpkg -s 软件名称,比如php.mysql.apache. dpkg-query -l 软件名称 要列出你系统中安装的所有包,输入下面的命令:dpkg - ...