过滤器、监听器、Bootstrap
过滤器
过滤器的基本概念
Java Web的三种组件
组件 | 作用 |
---|---|
Servlet | 运行在服务器上的Java小程序,接收用户的请求并且做出响应 |
Filter | 过滤器,用于集中处理一些公共的功能,对用户的请求进行修改和拦截。 |
Listener | 监听器,用于监听作用域的创建和销毁,监听作用域中值修改等操作 |
过滤器的基本概念
在Web开发时对用户请求和响应的数据进行过滤
过滤器的作用
Web资源:服务器上的JSP,Servlet,网页,图片等
过滤器是运行在用户请求与Web资源之间,可以对用户的请求进行修改和拦截。
过滤器的使用场景
-
处理全站的乱码。
-
用户权限的验证,如果没有登录的用户对请求进行拦截。
-
过滤整个网站不健康,敏感的内容。
示例:编写过滤器
开发过滤器的步骤
- 创建一个类,实现接口:javax.servlet.Filter接口
- 实现接口中所有的方法
- 配置过滤器:使用web.xml 或 使用注解 @WebFilter
过滤器的示例代码
注意:不要在浏览器上去访问过滤器。过滤器来过滤请求的,过滤器在匹配过滤路径时会自动调用。
注解说明
@WebFilter注解属性 | 说明 |
---|---|
filterName | 过滤器的名字 |
urlPatterns | 过滤的地址,可以配置多个,也可以使用通配符 |
value | 指定过滤的资源地址 |
Servlet的代码
@WebFilter("/demo1")
public class Demo1Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 执行过滤的功能
* @param request 请求对象
* @param response 响应对象
* @param chain 过滤链
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("过滤器:请求的时候执行");
// 对请求放行,需要调用过滤键的方法。如果没有调用这个方法,则请求被拦截
chain.doFilter(request, response);
System.out.println("过滤器:响应的时候执行");
}
@Override
public void destroy() {
}
}
使用注解的方式
@WebFilter("/demo1")
使用配置文件的方式
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--使用配置的方式配置过滤器-->
<filter>
<!--过滤器的名字-->
<filter-name>demo1</filter-name>
<!--过滤器的类全名-->
<filter-class>com.xxx.filter.Demo1Filter</filter-class>
</filter>
<!--过滤地址的映射-->
<filter-mapping>
<!--过滤器的名字,与上面的名字一样-->
<filter-name>demo1</filter-name>
<!--过滤的地址,必须以/开头 -->
<url-pattern>/demo1</url-pattern>
</filter-mapping>
</web-app>
过滤器的执行流程
过滤器的执行特点
如果浏览器访问的地址正好匹配过滤器的地址,就会自动调用过滤器。过滤器并不是主动去访问的。
过滤器的执行流程
- 用户发送请求,请求的是Web资源
- 如果过滤器的过滤地址匹配web资源的访问地址,就会自动执行过滤器的doFilter()方法
- 如果执行过滤器的过滤方法,就会执行其中的chain.doFilter()方法,执行这个方法放行请求。如果没有执行这个方法,则是拦截请求。
- 放行后才到达web资源,到达web资源。响应回来的时候,还会再次经过过滤器,最后返回给用户。
过滤器的生命周期
过滤器加载的时机
-
Servlet的生命周期的方法:
init() 第一次访问Servlet时执行
service() 浏览器的每次访问都会执行
destory() 服务器关闭时执行
生命周期的方法
Filter接口中的方法 | 作用和执行次数 |
---|---|
void init(FilterConfig filterConfig) | 服务器启动时创建过滤器对象, 并执行init初始化,执行1次 |
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | 当过滤路径匹配,每次的请求都会执行(多次) |
public void destroy() | 服务器关闭时执行销毁的方法,执行一次 |
示例:生命周期的过程
示例代码
@WebFilter("/demo01")
public class Demo02Filter implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.println("filter init");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("filter doFilter");
chain.doFilter(req, resp);
}
public void destroy() {
System.out.println("filter destory");
}
}
过滤器映射的访问路径
Servlet中与过滤器中映射路径的区别
-
Servlet:映射地址就是它的访问地址
-
Filter:映射地址是它过滤的地址
如果请求的URL地址不存在,但是匹配过滤的地址,还是会执行过滤器
在Filter中URL的过滤方式
按格式有2种:
- 以/开头: /代表web目录
- 以扩展名结尾: *.do
匹配方式 | 匹配哪些资源 | 示例 |
---|---|---|
以/开头 | 精确匹配 | /demo1 |
目录匹配 | /admin/* 过滤某个目录下所有web资源 | |
以扩展名结尾 | 拦截以某个扩展名结尾的资源 | *.do *.action |
如:/admin/*.html
Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> /admin/*.html in filter mapping
这种配置过滤器地址的方式是错误的,不能两者同时出现。
过滤多个地址的写法
过滤器匹配多个地址 | 说明 |
---|---|
urlPatterns = {"/demo1", “/demo2”} | 同时过滤demo1和demo2 |
urlPatterns = {"/admin/*", “*.html”} | 过滤admin目录下所有的资源和所有的html页面 过滤的地址是所有过滤地址的并集,不是交集 |
配置文件的方式
<filter>
<filter-name>demo2</filter-name>
<filter-class>com.xxx.filter.Demo2Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>demo2</filter-name>
<!--过滤多个地址-->
<url-pattern>/demo1</url-pattern>
<url-pattern>/demo2</url-pattern>
</filter-mapping>
过滤器的三种拦截方式
默认的拦截方式
在Servlet3.0以后,拦截方式有5种,常用的三种。
- REQUEST:对来自于浏览器上直接的请求进行拦截(默认)
- FORWARD:对服务器端的转发进行拦截
- INCLUDE:对包含的请求进行拦截
来自转发的请求被拦截
1). 在index.jsp转发到HelloServlet
2). 过滤器的配置
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- 转发 --%>
<jsp:forward page="/demo1"/>
</body>
</html>
配置方式1:注解的方式
@WebFilter(filterName = "Demo2Filter", urlPatterns = "/demo1",
dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.REQUEST, DispatcherType.INCLUDE})
配置方式2:web.xml文件
<filter>
<filter-name>demo2</filter-name>
<filter-class>com.xxx.filter.Demo2Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>demo2</filter-name>
<!--过滤多个地址-->
<url-pattern>/demo1</url-pattern>
<url-pattern>/demo2</url-pattern>
<!--配置拦截方式-->
<dispatcher>INCLUDE</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
示例:使用过滤器过滤全局汉字乱码问题
编写过滤器,过滤所有Servlet中使用POST方法提交的汉字的编码。
开发步骤
- 有2个HTML页面,1个是login.html,有表单,登录名。1个register.html,有表单,有注册的名字。都使用POST提交用户名使用汉字提交。
- 有2个Servlet,一个是LoginServlet登录,一个是RegisterServlet注册
- 使用过滤器,对所有的Servlet的POST方法进行过滤。
- 在没有使用过滤器之前,每个Servlet必须加上汉字编码:request.setCharacterEncoding(字符集); 字符集与网页的编码要一致
示例代码
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="login" method="post">
登录名:<input type="text" name="user"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
<h2>用户注册</h2>
<form action="register" method="post">
注册名:<input type="text" name="name"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
LoginServlet.java
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 得到表单提交的数据
String username = request.getParameter("user");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.print("登录成功,用户名是:" + username);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
RegisterServlet.java
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.print("注册成功,用户名是:" + name);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
EncodeFilter.java
/*
对所有POST方法请求参数进行编码
*/
@WebFilter(filterName = "EncodingFilter", urlPatterns = "/*")
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// 强转成子接口
HttpServletRequest request = (HttpServletRequest) req;
// 注:POST要大写
if ("POST".equals(request.getMethod())) {
// 如果是POST方法,就对汉字进行编码的操作
request.setCharacterEncoding("utf-8");
}
// 放行
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
过滤器链FilterChain的使用
过滤器链的概念
在浏览器发送请求到达web资源之前可以经过多个过滤器,这多个过滤器就组成了一个过滤器链。
FilterChain接口中的方法
void doFilter(ServletRequest request, ServletResponse response)
如果调用这个方法就放行,否则请求就被拦截
示例:过滤器链
需求
创建两个过滤器OneFilter和TwoFilter,访问ResourceServlet,每个过滤器的请求和响应各输出一句话,观察过滤器的执行过程。
第一个过滤器
/**
* 第一个过滤器
*/
@WebFilter(filterName = "OneFilter", urlPatterns = "/demo1")
public class OneFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("第1个过滤器:请求");
chain.doFilter(req, resp); //放行
System.out.println("第1个过滤器:响应");
}
public void init(FilterConfig config) throws ServletException {
}
}
第二个过滤器
/*
第二个过滤器
*/
@WebFilter(filterName = "TwoFilter", urlPatterns = "/demo1")
public class TwoFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("第2个过滤器:请求");
chain.doFilter(req, resp);
System.out.println("第2个过滤器:响应");
}
public void init(FilterConfig config) throws ServletException {
}
}
Web资源
@WebServlet("/demo1")
public class Demo1HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Web资源:Servlet到达");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
过滤器链的执行顺序
- 使用注解的配置方式
按过滤器类名的顺序排序
-
使用web.xml的配置方式
<!--如果是配置,则按web.xml中出现的先后顺序--> <filter> <filter-name>one</filter-name> <filter-class>com.xxx.filter.OneFilter</filter-class> </filter> <filter-mapping> <filter-name>one</filter-name> <url-pattern>/demo1</url-pattern> </filter-mapping> <filter> <filter-name>two</filter-name> <filter-class>com.xxx.filter.TwoFilter</filter-class> </filter> <filter-mapping> <filter-name>two</filter-name> <url-pattern>/demo1</url-pattern> </filter-mapping>
示例:用户权限的过滤器
使用过滤器进行权限的控制,实现正确的访问
- add.jsp 添加数据,需要登录才可访问
- update.jsp 修改数据,需要登录才可访问
- list.jsp 查询数据,登录或不登录都可以访问
- login.jsp 登录页面,登录或不登录都可以访问
项目结构
实现步骤
- 在web下创建4个页面:admin/add.jsp,admin/update.jsp,login.jsp,list.jsp。
- login.jsp上使用${msg},显示登录失败信息。
- 创建LoginServlet, 判断用户名密码是否正确,如果正确,则在会话域中保存用户信息。登录成功跳转到add.jsp,登录失败则在请求域中写入登录失败的信息,转发到login.jsp。
- 没有登录的用户不能访问add.jsp,update.jsp。使用过滤器解决:创建AuthorFilter
- 判断如果会话域中没有用户信息,则重定向到登录页面。
- 如果会话域中有用户的信息,表示登录成功,继续放行访问后续的Web资源。
示例代码
LoginServlet
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.得到用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
// 2.判断用户名和密码是否正确
if ("admin".equals(username) && "123".equals(password)) {
// 3.如果正确,表示登录成功,将用户的信息保存在会话域中。
HttpSession session = request.getSession();
session.setAttribute("user", username);
// 4.跳转到add.jsp
response.sendRedirect(request.getContextPath() + "/admin/add.jsp");
}
// 5.登录失败跳转到login.jsp,并且提示错误信息
else {
request.setAttribute("msg","用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
AuthorFilter
/**
* 只过滤/admin/*所有的资源,注:如果过滤地址写错,会死循环
*/
@WebFilter(filterName = "AuthorFilter", urlPatterns = "/admin/*")
public class AuthorFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// 1.从会话域中得到用户的信息,判断是否登录
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession();
String user = (String) session.getAttribute("user");
// 2.如果用户信息为空,表示没有登录,重定向到登录页面
if (user == null) {
HttpServletResponse response = (HttpServletResponse) resp;
// 得到客户端的IP地址
System.out.println(new Timestamp(System.currentTimeMillis()) + ",拦截到了非法的访问:" + request.getRemoteAddr());
response.sendRedirect(request.getContextPath() + "/login.jsp");
} else {
// 3.否则表示已经登录,放行
chain.doFilter(req, resp);
}
}
public void init(FilterConfig config) throws ServletException {
}
}
监听器
监听器的概述
作用
- 监听作用域的创建和销毁
- 监听作用域中值变化情况
监听器接口
ServletContextListener监听器
ServletContextListener监听器的概述
-
作用:监听上下文域的创建和销毁
-
上下文域的创建时机:服务器启动的时候
-
上下文域的销毁时机:服务器关闭的时候
因此监听上下文域的创建和销毁,就是监听程序的启动和关闭
ServletContextListener接口中的方法
接口中的方法 | 功能 | 执行次数 |
---|---|---|
void contextDestroyed(ServletContextEvent sce) | 上下文域销毁的时候执行 | 1次 |
void contextInitialized(ServletContextEvent sce) | 上下文域创建的时候执行 | 1次 |
ServletContextEvent事件对象的方法
ServletContextEvent中的方法 | 功能 |
---|---|
ServletContext getServletContext() | 得到上下文对象 |
示例:ServletContextListener的应用
监听器的开发步骤
- 编写一个类实现ServletContextListener接口
- 重写接口中所有的方法:初始化,销毁方法
- 在web.xml中配置或使用注解:@WebListener
代码
监听器
@WebListener
public class MyContextListener implements ServletContextListener {
// 上下文创建时候执行1次
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println(new Timestamp(System.currentTimeMillis()) + ",创建了上下文对象:" + event.getServletContext());
}
// 上下文销毁的时候执行1次
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println(new Timestamp(System.currentTimeMillis()) + ",销毁上下文对象:" + event.getServletContext());
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--监听器:只需要指定类全名-->
<listener>
<listener-class>com.xxx.listener.MyContextListener</listener-class>
</listener>
</web-app>
执行效果
ServletContextAttributeListener监听器
ServletContextAttributeListener监听器的作用
- 作用:监听上下文域中数据的增删改操作
- 时机:ServletContext在进行一下3个操作时
- 增加数据: setAttribute()
- 删除数据: removeAttribute()
- 修改数据: setAttribute() 属性名相同
ServletContextAttributeListener接口中的方法
接口中的方法 | 功能 |
---|---|
void attributeAdded(ServletContextAttributeEvent event) | 添加属性的时候调用的方法 |
void attributeRemoved(ServletContextAttributeEvent event) | 删除属性的时候调用的方法 |
void attributeReplaced(ServletContextAttributeEvent event) | 修改属性的时候调用的方法 |
ServletContextAttributeEvent对象中的方法
ServletContextAttributeEvent对象中的方法 | 功能 |
---|---|
String getName() | 得到值变化的属性名 |
Object getValue() | 得到值变化的属性值 |
ServletContextAttributeListener监听器的示例
开发步骤
- 编写一个类实现ServletContextAttributeListener接口
- 重写接口中三个方法:添加,修改,删除
- 使用web.xml配置或@WebListener注解
示例代码
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 得到上下文域
ServletContext application = getServletContext();
// 向上下文域添加属性
application.setAttribute("user","xiaoming");
// 向上下文域修改属性
application.setAttribute("user","xiaohong");
// 向上下文域删除属性
application.removeAttribute("user");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
监听器
/*
1. 编写一个类实现ServletContextListener接口
2. 重写接口中所有的方法:初始化,销毁方法
3. 在web.xml中配置或使用注解:@WebListener
*/
//@WebListener
public class MyContextListener implements ServletContextListener, ServletContextAttributeListener {
// 上下文创建时候执行1次
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println(new Timestamp(System.currentTimeMillis()) + ",创建了上下文对象:" + event.getServletContext());
}
// 上下文销毁的时候执行1次
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println(new Timestamp(System.currentTimeMillis()) + ",销毁上下文对象:" + event.getServletContext());
}
// 属性添加
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
System.out.println("添加了属性,属性名:" + event.getName());
System.out.println("添加了属性,属性值:" + event.getValue());
}
// 属性的删除
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
System.out.println("删除了属性,属性名:" + event.getName());
System.out.println("删除了属性,属性值:" + event.getValue());
}
// 属性的修改
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
System.out.println("修改了属性,属性名:" + event.getName());
System.out.println("修改前的属性值:" + event.getValue());
//直接从作用域中去取出修改后的值
System.out.println("修改后的属性值:" + event.getServletContext().getAttribute(event.getName()));
}
}
案例:ServletContextListener的应用
技术点
在url中要设置allowMultiQueries=true参数,表示可以在一个配置中执行多条SQL语句。多条SQL语句使用分号隔开
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="default">
<!--环境变量-->
<environment id="default">
<!--事务管理器-->
<transactionManager type="JDBC"/>
<!--数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?allowMultiQueries=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--映射器-->
<mappers>
<mapper resource="com/xxx/dao/SystemDao.xml"/>
</mappers>
</configuration>
步骤
-
创建SystemDao类,创建initTables()初始化表的方法,clearTables()删除所有表的操作。
-
创建和删除表
-- 创建表 CREATE TABLE dept (id INT PRIMARY KEY AUTO_INCREMENT, dept_name VARCHAR(10)); CREATE TABLE emp (id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), birthday DATE, dep_id INT); -- 删除表 DROP TABLE emp; DROP TABLE dept;
-
在监听器中创建成员变量SystemDao,在Web创建的时候调用initTables方法,并输出信息。
-
在Web退出的时候调用clearTables方法,删除表,并输出信息。
代码
测试数据
-- 插入部门信息
insert into dept values(null,'开发部');
insert into dept values(null,'销售部');
-- 插入员工信息
insert into emp values(null,'小明','2001-01-11',1);
insert into emp values(null,'小红','2002-02-12',1);
SystemDao
public interface SystemDao {
@Update("create table dept (id int primary key auto_increment, dept_name varchar(10));\n" +
"create table emp (id int primary key auto_increment, name varchar(20), birthday date, dep_id int, foreign key (dep_id) references dept(id));")
void initTables();
@Update("drop table emp;\n" +
"drop table dept;")
void clearTables();
}
MyServletContextListener
@WebListener
public class MyContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("项目启动创建所有表");
SqlSession sqlSession = MybatisUtils.getSession();
SystemDao mapper = sqlSession.getMapper(SystemDao.class);
mapper.initTables();
sqlSession.commit();
sqlSession.close();
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("项目关闭删除所有表");
SqlSession sqlSession = MybatisUtils.getSession();
SystemDao mapper = sqlSession.getMapper(SystemDao.class);
mapper.clearTables();
sqlSession.commit();
sqlSession.close();
}
}
Bootstrap
Bootstrap框架的概述和优点
什么是Bootstrap
bootstrap中文官网:http://www.bootcss.com
Bootstrap一个前端的框架,提高前端的开发效率,制作出更加专业,漂亮的页面。基于html、css、js技术。
Bootstrap的优势
- 自Bootstrap3起,框架包含了贯穿于整个库的移动设备优先的样式。能够自适应于台式机、平板电脑和手机。
- Bootstrap支持所有的主流浏览器。如:Internet Explorer、 Firefox、 Opera、 Google Chrome、Safari。
- 只要具备 HTML 和 CSS 的基础知识,就可以使用Bootstrap。
什么是响应式设计
传统的网页
电脑上和手机上看到的是不同的页面
响应式设计网页
电脑和手机看到的是同一个页面,根据屏幕尺寸不同,网页自动有不同布局
响应式布局特点
同一个网页在不同的屏幕上,会自动适应,拥有不同的布局.
Bootstrap的下载和介绍
下载
bootstrap中文官网:http://www.bootcss.com
Bootstrap包含的内容
- 设置全局 CSS 样式;基本的 HTML 元素均可以通过 class 设置样式并得到增强效果;还有先进的栅格系统。
- 组件:无数可复用的组件,包括字体图标、下拉菜单、导航、警告框、弹出框等更多功能。
- JavaScript插件:jQuery 插件为 Bootstrap 的组件赋予了“生命”。可以简单地一次性引入所有插件,或者逐个引入到你的页面中。
http://www.bootcss.com,下载用于生产环境的Bootstrap
目录结构
压缩版与标准版的介绍
功能上是一样的
- 标准版:代码可读性比较好,通常用于开发。
- 压缩版:文件小,通常用于工作环境。
创建Bootstrap的模板
步骤
- 复制解压出来的三个文件夹到项目中:css,js, fonts
- 复制jquery框架:jquery-3.2.1.min.js复制到js目录下
- 复制文档中的:"起步->基本模板"中代码到网页,修改网页的内容
此模板文件只要创建1次即可,以后可以重用
模板的代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<!-- 对IE浏览器的兼容-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 设置视口参数,视口就是浏览器的显示区域,让视口宽度等于屏幕宽度,缩放比例为1-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap模板</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="js/bootstrap.min.js"></script>
</head>
<body>
</body>
</html>
栅格系统的介绍
表格
<table>
<tr bgcolor="gray">
<td>姓名</th>
<td>电话</th>
<td>地址</th>
</tr>
</table>
Bootstrap提供了一套响应式、移动设备优先的流式栅格系统
栅格系统用于通过一系列的行(row)与列(column)的组合来创建页面布局,一行会自动分为最多12格。你的内容就可以放入这些创建好的布局中。
Bootstrap 栅格系统的工作原理
<div class="container">
<div class="row">
<div class="col-md-4">
1列占4格子
</div>
<div class="col-md-4">
1列占4格子
</div>
<div class="col-md-4">
1列占4格子
</div>
</div>
</div>
栅格的参数
超小屏幕 手机 (<768px) | 小屏幕 平板 (≥768px) | 中等屏幕 (≥992px) | 大屏幕 (≥1200px) | |
---|---|---|---|---|
类前缀 | .col-xs- | .col-sm- | .col-md- | .col-lg- |
两种容器
两种容器的类样式名 | 说明 |
---|---|
container | 具有固定宽度的容器 |
container-fluid | 具有100%宽度的容器 |
代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<!--对IE浏览器的兼容-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--设置视口参数,视口就是浏览器的显示区域,让视口宽度等于屏幕宽度,缩放比例为1-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap两种容器</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="js/bootstrap.min.js"></script>
<style>
div {
border: 1px solid red;
height: 100px;
}
</style>
</head>
<body>
<div class="container">
container 固定宽度的容器
</div>
<div class="container-fluid">
container-fluid 100%宽度
</div>
</body>
</html>
栅格系统有关的类样式名
栅格系统 | 描述 | 类似于表格 |
---|---|---|
.container | 固定宽度容器 | table |
.container-fluid | 100%宽度的容器 | table |
.row | 表示1行,1行最多12格 | tr |
.col-xx-n xx | 表示1列,1列可以占多格 .col-sm-3 在小屏幕上这1列占3格 .col-lg-6 在大屏幕上这1列占6格 | td |
栅格系统的布局示例
示例1:基本结构,一列四个格子
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<!--设置网页编码为utf-8-->
<meta charset="utf-8">
<!--兼容ie-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--视口,虚拟的界面,适应手机-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>基本布局</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!--注意一定要先引入jQuery后引入bootstrap-->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
<style>
.row div {
border: 1px solid red;
height: 100px;
}
</style>
</head>
<body>
<h1>基本布局</h1>
<div class="container">
<!--一行-->
<div class="row">
<!--一列-->
<div class="col-md-4">
一列四个格子
</div>
<div class="col-md-4">
一列四个格子
</div>
<div class="col-md-4">
一列四个格子
</div>
</div>
<!--一行-->
<div class="row">
<!--一列-->
<div class="col-md-4">
一列四个格子
</div>
<div class="col-md-4">
一列四个格子
</div>
<div class="col-md-4">
一列四个格子
</div>
</div>
</div>
</body>
</html>
示例2:不同屏幕的适配
不同的设备上显示不同数量的列:中等屏幕占3格,小屏幕占4格,超小屏幕占6格
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<!--对IE浏览器的兼容-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--设置视口参数,视口就是浏览器的显示区域,让视口宽度等于屏幕宽度,缩放比例为1-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap栅格系统</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。也可以根据需要只加载单个插件。 -->
<script src="js/bootstrap.min.js"></script>
<style>
.row div {
border: 1px solid red;
height: 100px;
}
</style>
</head>
<body>
<!--容器-->
<div class="container">
<!--表示1行-->
<div class="col-xs-6 col-sm-4 col-md-3">
超小屏幕占6格,小屏幕占4格,中等屏幕占3格
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
</div>
</div>
</body>
</html>
全局CSS样式:按钮
代码
<div class="container">
<h2>按钮</h2>
<input type="button" value="普通按钮" class="btn btn-default">
<button type="submit" class="btn btn-default">提交按钮</button>
<a href="#" class="btn btn-default">链接</a>
<h2>预定义按钮</h2>
<input type="button" value="蓝色按钮" class="btn btn-primary">
<input type="button" value="红色按钮" class="btn btn-danger">
<input type="button" value="绿色按钮" class="btn btn-success">
</div>
全局CSS样式:表格
表格的类样式
不同行的颜色 (可以加在tr或td上)
示例代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<!--对IE浏览器的兼容-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--设置视口参数,视口就是浏览器的显示区域,让视口宽度等于屏幕宽度,缩放比例为1-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap表格</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。也可以根据需要只加载单个插件。 -->
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h3>人</h3>
<table class="table table-striped table-bordered table-hover">
<tr class="success">
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>电话</th>
</tr>
<tr>
<td>1</td>
<td>小明</td>
<td>男</td>
<td>19509869504</td>
</tr>
<tr>
<td>2</td>
<td class="danger">小红</td>
<td>女</td>
<td>13938475687</td>
</tr>
<tr>
<td>3</td>
<td class="warning">小白</td>
<td>男</td>
<td>18501029504</td>
</tr>
</table>
</div>
</body>
</html>