web(过滤器、监听器、Bootstrap)

过滤器、监听器、Bootstrap

过滤器

过滤器的基本概念

Java Web的三种组件

组件作用
Servlet运行在服务器上的Java小程序,接收用户的请求并且做出响应
Filter过滤器,用于集中处理一些公共的功能,对用户的请求进行修改和拦截。
Listener监听器,用于监听作用域的创建和销毁,监听作用域中值修改等操作

在这里插入图片描述

过滤器的基本概念

在Web开发时对用户请求和响应的数据进行过滤

过滤器的作用

Web资源:服务器上的JSP,Servlet,网页,图片等

过滤器是运行在用户请求与Web资源之间,可以对用户的请求进行修改和拦截。
在这里插入图片描述

过滤器的使用场景

  1. 处理全站的乱码。

  2. 用户权限的验证,如果没有登录的用户对请求进行拦截。

  3. 过滤整个网站不健康,敏感的内容。

示例:编写过滤器

开发过滤器的步骤

  1. 创建一个类,实现接口:javax.servlet.Filter接口
  2. 实现接口中所有的方法
  3. 配置过滤器:使用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>

过滤器的执行流程

过滤器的执行特点

如果浏览器访问的地址正好匹配过滤器的地址,就会自动调用过滤器。过滤器并不是主动去访问的。

过滤器的执行流程

  1. 用户发送请求,请求的是Web资源
  2. 如果过滤器的过滤地址匹配web资源的访问地址,就会自动执行过滤器的doFilter()方法
  3. 如果执行过滤器的过滤方法,就会执行其中的chain.doFilter()方法,执行这个方法放行请求。如果没有执行这个方法,则是拦截请求。
  4. 放行后才到达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种:

  1. 以/开头: /代表web目录
  2. 以扩展名结尾: *.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种,常用的三种。

  1. REQUEST:对来自于浏览器上直接的请求进行拦截(默认)
  2. FORWARD:对服务器端的转发进行拦截
  3. 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方法提交的汉字的编码。
在这里插入图片描述

开发步骤

  1. 有2个HTML页面,1个是login.html,有表单,登录名。1个register.html,有表单,有注册的名字。都使用POST提交用户名使用汉字提交。
  2. 有2个Servlet,一个是LoginServlet登录,一个是RegisterServlet注册
  3. 使用过滤器,对所有的Servlet的POST方法进行过滤。
  4. 在没有使用过滤器之前,每个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);
    }
}

过滤器链的执行顺序

  1. 使用注解的配置方式
   按过滤器类名的顺序排序
  1. 使用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 登录页面,登录或不登录都可以访问

项目结构

在这里插入图片描述
在这里插入图片描述

实现步骤

  1. 在web下创建4个页面:admin/add.jsp,admin/update.jsp,login.jsp,list.jsp。
  2. login.jsp上使用${msg},显示登录失败信息。
  3. 创建LoginServlet, 判断用户名密码是否正确,如果正确,则在会话域中保存用户信息。登录成功跳转到add.jsp,登录失败则在请求域中写入登录失败的信息,转发到login.jsp。
  4. 没有登录的用户不能访问add.jsp,update.jsp。使用过滤器解决:创建AuthorFilter
    1. 判断如果会话域中没有用户信息,则重定向到登录页面。
    2. 如果会话域中有用户的信息,表示登录成功,继续放行访问后续的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 {

    }
}

监听器

监听器的概述

作用

  1. 监听作用域的创建和销毁
  2. 监听作用域中值变化情况

监听器接口

在这里插入图片描述

ServletContextListener监听器

ServletContextListener监听器的概述

  1. 作用:监听上下文域的创建和销毁

  2. 上下文域的创建时机:服务器启动的时候

  3. 上下文域的销毁时机:服务器关闭的时候

    因此监听上下文域的创建和销毁,就是监听程序的启动和关闭

ServletContextListener接口中的方法

接口中的方法功能执行次数
void contextDestroyed(ServletContextEvent sce)上下文域销毁的时候执行1次
void contextInitialized(ServletContextEvent sce)上下文域创建的时候执行1次

ServletContextEvent事件对象的方法

ServletContextEvent中的方法功能
ServletContext getServletContext()得到上下文对象

示例:ServletContextListener的应用

监听器的开发步骤
  1. 编写一个类实现ServletContextListener接口
  2. 重写接口中所有的方法:初始化,销毁方法
  3. 在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监听器的作用

  1. 作用:监听上下文域中数据的增删改操作
  2. 时机:ServletContext在进行一下3个操作时
    1. 增加数据: setAttribute()
    2. 删除数据: removeAttribute()
    3. 修改数据: setAttribute() 属性名相同

ServletContextAttributeListener接口中的方法

接口中的方法功能
void attributeAdded(ServletContextAttributeEvent event)添加属性的时候调用的方法
void attributeRemoved(ServletContextAttributeEvent event)删除属性的时候调用的方法
void attributeReplaced(ServletContextAttributeEvent event)修改属性的时候调用的方法

ServletContextAttributeEvent对象中的方法

ServletContextAttributeEvent对象中的方法功能
String getName()得到值变化的属性名
Object getValue()得到值变化的属性值

ServletContextAttributeListener监听器的示例

开发步骤
  1. 编写一个类实现ServletContextAttributeListener接口
  2. 重写接口中三个方法:添加,修改,删除
  3. 使用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>

步骤

  1. 创建SystemDao类,创建initTables()初始化表的方法,clearTables()删除所有表的操作。

  2. 创建和删除表

    -- 创建表
    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;
    
  3. 在监听器中创建成员变量SystemDao,在Web创建的时候调用initTables方法,并输出信息。

  4. 在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的优势

  1. 自Bootstrap3起,框架包含了贯穿于整个库的移动设备优先的样式。能够自适应于台式机、平板电脑和手机
  2. Bootstrap支持所有的主流浏览器。如:Internet Explorer、 Firefox、 Opera、 Google Chrome、Safari。
  3. 只要具备 HTML 和 CSS 的基础知识,就可以使用Bootstrap。

什么是响应式设计

传统的网页

电脑上和手机上看到的是不同的页面

响应式设计网页

电脑和手机看到的是同一个页面,根据屏幕尺寸不同,网页自动有不同布局

响应式布局特点

同一个网页在不同的屏幕上,会自动适应,拥有不同的布局.

Bootstrap的下载和介绍

下载

bootstrap中文官网:http://www.bootcss.com
在这里插入图片描述

Bootstrap包含的内容

  1. 设置全局 CSS 样式;基本的 HTML 元素均可以通过 class 设置样式并得到增强效果;还有先进的栅格系统。
  2. 组件:无数可复用的组件,包括字体图标、下拉菜单、导航、警告框、弹出框等更多功能。
  3. JavaScript插件:jQuery 插件为 Bootstrap 的组件赋予了“生命”。可以简单地一次性引入所有插件,或者逐个引入到你的页面中。

http://www.bootcss.com,下载用于生产环境的Bootstrap

目录结构

在这里插入图片描述

压缩版与标准版的介绍

在这里插入图片描述
功能上是一样的

  • 标准版:代码可读性比较好,通常用于开发。
  • 压缩版:文件小,通常用于工作环境。

创建Bootstrap的模板

步骤

  1. 复制解压出来的三个文件夹到项目中:css,js, fonts
  2. 复制jquery框架:jquery-3.2.1.min.js复制到js目录下
  3. 复制文档中的:"起步->基本模板"中代码到网页,修改网页的内容

此模板文件只要创建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-fluid100%宽度的容器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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值