springmvc学习笔记(简介及使用)

工作之余, 回顾了一下springmvc的相关内容, 这次也为后面复习什么的做个标记, 也希望能与大家交流学习, 通过回帖留言等方式表达自己的观点或学习心得.

本文如若有误, 也敬请大家不吝赐教.

1 mvc框架通常要做哪些事情

  1. 将URL映射到Java类或Java方法
  2. 封装用户提交的数据
  3. 处理请求, 调用相关的业务处理, 并封装响应的数据
  4. 将要相应的数据进行渲染

2 springmvc优点和特点

  1. 与spring无缝集成(IoC, AOP)
  2. 约定优于配置
  3. 性能较struts2好
  4. 设计中的角色或职责划分明确
  5. Restful
  6. JUnit测试
  7. 异常处理
  8. 本地化, 国际化
  9. 数据验证, 类型转换等
  10. 拦截器
  11. 使用的人已经相当多, 使用的公司也相当多
  12. 简单, 便捷, 易学

3 springmvc处理请求流程

springmvc框架基于请求驱动, 所有设计都围绕一个中央Servlet展开, 它负责将请求分发给各处理器(页面控制器, Controller). 下图中展示了springmvc处理请求的流程, 图中的Front Controller(前端控制器)正是springmvc的DispatcherServlet; Controller称为处理器或应用控制器或页面控制器, 由它来处理具体的请求, 返回模型数据; View Template为具体视图, 用于展示数据, 响应请求.

具体处理请求步骤:

  1. 用户发送请求, 被前端控制器拦截, 前端控制器根据请求的信息选择相应的页面控制器, 并将请求委托给此页面控制器来处理.
  2. 页面控制器接收到请求后, 首先收集并绑定请求参数到一个命令对象(表单对象)中, 并进行验证转换等操作, 然后将命令对象(表单对象)委托给业务对象进行处理, 最后返回一个ModelAndView对象.
  3. 前端控制器根据返回的视图名, 选择相应的视图进行渲染, 并将模型数据传入到视图中以便展示.
  4. 前端控制器将响应结果返回给用户.

至此, 整个请求流程结束. 当然还有一些细节的问题, 需要我们了解, 比如: 前端控制器如何选择页面控制器, 前端控制器如何根据页面控制器返回的视图名选择相应的视图进行渲染, 等等. 带着这些问题, 我们将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);
}
}
}
}
  1. 步骤①, DispatcherServlet作为前端控制器, 统一的请求接收点, 控制全局的请求流程. 接收到用户请求, 自己不做处理, 而是将请求委托给其他的处理器进行处理.
  2. 步骤②③, DispatcherServlet通过HandlerMapping(处理映射器), 将请求映射为一个HandlerExecutionChain对象, 其中包括了页面控制器和对其配置的拦截器.
  3. 步骤④, DispatcherServlet通过获得的Handler(处理器, 页面控制器, Controller), 查找一个合适的HandlerAdapter(处理器适配器), 通过这个HandlerAdapter调用Handler实际处理请求的方法.
  4. 步骤⑤, 提取请求中的模型数据, 调用Handler实际处理请求的方法. 在调用方法时, 填充参数过程中, spring会根据配置做一些工作, 如: 数据转换, 数据格式化, 数据验证等.
  5. 步骤⑥⑦, Handler执行完成后, 将返回一个ModelAndView对象给DispatherServlet. ModelAndView对象中包含逻辑视图名或逻辑视图名和模型.
  6. 步骤⑧, 根据ModelAndView对象选择一个合适的ViewResolver(视图解析器).
  7. 步骤⑨, ViewResolverModelAndView中的逻辑视图名解释成View对象. ViewResolver也是接口, 同样采用了策略模式, 这样就很容易切换其他的视图类型.
  8. 步骤⑩⑪, 渲染视图时, 将Model数据传入视图中, 这里的Model数据是一个Map, 容易与各种视图类型相结合.
  9. 步骤⑫, 最后, 由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;

方法参数为HttpServletRequestHttpServletResponse, 请求处理完成后, 返回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, 具体是通过HandlerAdaptersupports方法, 找到匹配的HandlerAdapter之后, 会使用自身定义的策略, 确定处理器的具体方法, 并处理传入参数, 然后执行自身的handle方法, 而在handle中运用反射机制调用处理器的具体处理方法.

处理器的类型可以是任何对象类型, 这就使得, 来自第三方框架的处理器可以在无编码的前提下集成进来, 也支持基于注解的、不需要实现任何接口的处理器类型.







原文地址: http://www.cnblogs.com/lzj0616/p/6753406.html

springmvc学习笔记(简介及使用)的更多相关文章

  1. 史上最全的SpringMVC学习笔记

    SpringMVC学习笔记---- 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于Spring ...

  2. springmvc学习笔记--REST API的异常处理

    前言: 最近使用springmvc写了不少rest api, 觉得真是一个好框架. 之前描述的几篇关于rest api的文章, 其实还是不够完善. 比如当遇到参数缺失, 类型不匹配的情况时, 直接抛出 ...

  3. springmvc学习笔记---面向移动端支持REST API

    前言: springmvc对注解的支持非常灵活和飘逸, 也得web编程少了以往很大一坨配置项. 另一方面移动互联网的到来, 使得REST API变得流行, 甚至成为主流. 因此我们来关注下spring ...

  4. SpringMVC:学习笔记(8)——文件上传

    SpringMVC--文件上传 说明: 文件上传的途径 文件上传主要有两种方式: 1.使用Apache Commons FileUpload元件. 2.利用Servlet3.0及其更高版本的内置支持. ...

  5. springmvc学习笔记(常用注解)

    springmvc学习笔记(常用注解) 1. @Controller @Controller注解用于表示一个类的实例是页面控制器(后面都将称为控制器). 使用@Controller注解定义的控制器有如 ...

  6. SpringMVC学习笔记之二(SpringMVC高级参数绑定)

    一.高级参数绑定 1.1 绑定数组 需求:在商品列表页面选中多个商品,然后删除. 需求分析:功能要求商品列表页面中的每个商品前有一个checkbok,选中多个商品后点击删除按钮把商品id传递给Cont ...

  7. springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定

    springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...

  8. springmvc学习笔记(19)-RESTful支持

    springmvc学习笔记(19)-RESTful支持 标签: springmvc springmvc学习笔记19-RESTful支持 概念 REST的样例 controller REST方法的前端控 ...

  9. springMVC 学习笔记(一):springMVC 入门

    springMVC 学习笔记(一):spring 入门 什么是 springMVC springMVC 是 spring 框架的一个模块,springMVC 和 spring 无需通过中间整合层进行整 ...

随机推荐

  1. wemall app商城源码中基于PHP的ThinkPHP惯例配置文件代码

    wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...

  2. 算法模板——Dinic网络最大流 2

    实现功能:同Dinic网络最大流 1 这个新的想法源于Dinic费用流算法... 在费用流算法里面,每次处理一条最短路,是通过spfa的过程中就记录下来,然后顺藤摸瓜处理一路 于是在这个里面我的最大流 ...

  3. RabbitMQ-从基础到实战(3)— 消息的交换

    1.简介 在前面的例子中,每个消息都只对应一个消费者,即使有多个消费者在线,也只会有一个消费者接收并处理一条消息,这是消息中间件的一种常用方式.还有另外一种方式,生产者生产一条消息,广播给所有的消费者 ...

  4. Java第一次作业

    (一)学习总结 1.在java中通过Scanner类完成控制台的输入,Scanner类实现基本数据输入的方法是什么? import java.util.Scanner; System.out.prin ...

  5. ICC_lab总结——ICC_lab2:设计规划

    PS:字丑,禁止转载!!! 首先先写出大概的流程,然后是一些教材的理论知识总结,最后是进行lab2的一些流程概述. 教材的理论知识总结主要是:数字集成电路物理设计学习总结--布图规划和布局 --> ...

  6. BootStrap入门教程 (三)

    本文转自 http://www.cnblogs.com/ventlam/archive/2012/06/05/2524966.html 上讲回顾:Bootstrap的基础CSS(Base CSS)提供 ...

  7. 无图无定位新版css步骤条兼容ie6+

    <ul class="ui-step list-unstyled"> <li class="step-item"><b class ...

  8. css3特效

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title> ...

  9. Excel图表-"DNA"图

    p{ font-size: 15px; } .alexrootdiv>div{ background: #eeeeee; border: 1px solid #aaa; width: 99%; ...

  10. 老李分享:loadrunner的java user脚本开发

    老李分享:loadrunner的java user脚本开发 poptest在性能测试loadrunner的课程里,以web协议为主,同时也讲解其他协议的脚本开发,对于一个性能测试工程师需要掌握一个以上 ...