前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >日志切面的配置使用

日志切面的配置使用

作者头像
微醺
发布于 2019-01-17 03:14:14
发布于 2019-01-17 03:14:14
60400
代码可运行
举报
运行总次数:0
代码可运行

使用配置文件

applicationContext.xml(spring.xml)配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mc="http://www.springframework.org/schema/mvc"
       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
		        http://www.springframework.org/schema/mvc
		        http://www.springframework.org/schema/mvc/spring-mvc.xsd
		        http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd
                ">
    <import resource="spring-*.xml"></import>
    <!--日志的bean-->
    <bean id="log" class="com.teng.util.LogManager"></bean>
<!--配置切面和切入点信息-->
    <aop:config proxy-target-class="true">
        <!--
        配置切入点
        id:切入点名称
        expression:指定切入的表达式
        第一个*:代表方法的返回值类型 任意返回类型
        com.teng.service.impl  包名
        第二个*:任意类
        第三个*:任意方法名
        (..)..任意的参数类型
        execution(* com.teng.service.impl.*.*(..))
        -->
        <aop:pointcut id="pt" expression="execution(* com.teng.service.impl.*.*(..))"></aop:pointcut>
       <!--把切面和切入点关联起来 这个过程就是植入-->
        <aop:advisor advice-ref="log" pointcut-ref="pt"></aop:advisor>
    </aop:config>


    <bean id="myLog" class="com.teng.util.Log"></bean>
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="pt1" expression="execution(* com.teng.dao.impl.*.*(..))"></aop:pointcut>
       <!--自定义切面-->
        <aop:aspect  ref="myLog">
            <!--通知 aop:before前置通知-->
            <aop:before method="before" pointcut-ref="pt1"></aop:before>
            <!--aop":after-returning 后置通知 方法成功返回后通知-->
            <aop:after-returning method="after" pointcut-ref="pt1"></aop:after-returning>
            <!--抛出异常后通知-->
            <aop:after-throwing method="throwing1" pointcut-ref="pt1"></aop:after-throwing>
           <!--环绕通知-->
            <aop:around method="around" pointcut-ref="pt1"></aop:around>
        </aop:aspect>

    </aop:config>

</beans>

spring-dao.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mc="http://www.springframework.org/schema/mvc"
       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
		        http://www.springframework.org/schema/mvc
		        http://www.springframework.org/schema/mvc/spring-mvc.xsd
		        http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd
                ">
    <import resource="spring-*.xml"></import>
    <!--日志的bean-->
    <bean id="log" class="com.teng.util.LogManager"></bean>
<!--配置切面和切入点信息-->
    <aop:config proxy-target-class="true">
        <!--
        配置切入点
        id:切入点名称
        expression:指定切入的表达式
        第一个*:代表方法的返回值类型 任意返回类型
        com.teng.service.impl  包名
        第二个*:任意类
        第三个*:任意方法名
        (..)..任意的参数类型
        execution(* com.teng.service.impl.*.*(..))
        -->
        <aop:pointcut id="pt" expression="execution(* com.teng.service.impl.*.*(..))"></aop:pointcut>
       <!--把切面和切入点关联起来 这个过程就是植入-->
        <aop:advisor advice-ref="log" pointcut-ref="pt"></aop:advisor>
    </aop:config>


    <bean id="myLog" class="com.teng.util.Log"></bean>
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="pt1" expression="execution(* com.teng.dao.impl.*.*(..))"></aop:pointcut>
       <!--自定义切面-->
        <aop:aspect  ref="myLog">
            <!--通知 aop:before前置通知-->
            <aop:before method="before" pointcut-ref="pt1"></aop:before>
            <!--aop":after-returning 后置通知 方法成功返回后通知-->
            <aop:after-returning method="after" pointcut-ref="pt1"></aop:after-returning>
            <!--抛出异常后通知-->
            <aop:after-throwing method="throwing1" pointcut-ref="pt1"></aop:after-throwing>
           <!--环绕通知-->
            <aop:around method="around" pointcut-ref="pt1"></aop:around>
        </aop:aspect>

    </aop:config>

</beans>

spring-service.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mc="http://www.springframework.org/schema/mvc"
       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
		        http://www.springframework.org/schema/mvc
		        http://www.springframework.org/schema/mvc/spring-mvc.xsd"
        default-autowire="byType">

      <bean id="userService" class="com.teng.service.impl.UserServiceImpl" autowire="default">

        <!--
        autowire 属性值自动装配
        默认值 no  不装配
        byName 通过属性名装配  前提必须有有参构造
        byType 通过类型装配
        default 跟随着上级的特性
        -->
      <!--  <property name="userDao" ref="UserDao"></property>-->
        <property name="list">
            <list>
                <value>上海</value>
                <value>广州</value>
                <value>深圳</value>
            </list>

        </property>
    </bean>

    <bean id="user" class="com.teng.domain.User">
        <!--
        通过属性赋值
        基本数据类型,String:通过value赋值
        对象数据类型list:通过ref赋值
        集合类型:list:通过list赋值
        集合类型:set:通过set赋值
        -->
        <!--<property name="id" value="22"></property>-->
       <!-- <constructor-arg index="0" value="1"></constructor-arg>
        <constructor-arg index="1" value="你好"></constructor-arg>
        <constructor-arg index="2" value="hello"></constructor-arg>-->
        <constructor-arg type="int" value="22"></constructor-arg>
        <constructor-arg type="java.lang.String" value="牛"></constructor-arg>
        <constructor-arg type="java.lang.String" value="批"></constructor-arg>

    </bean>

</beans>

项目结构

UserDao接口和UserService接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.dao;
import com.teng.domain.User;
import java.util.List;
public interface UserDao {
    public void find();
    public void find(int id);
    public void find(User user);
    public void find(List list);
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.service;
import com.teng.domain.User;
import java.util.List;
public interface UserService {
    public void find();
    public void find(int id);
    public void find(User user);
    public void find(List list);
}

UserDaoImpl实现类和UserServiceImpl实现类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.dao.impl;
import com.teng.dao.UserDao;
import com.teng.domain.User;
import java.util.List;
public class UserDaoImpl implements UserDao {
    @Override
    public void find() {
            System.out.println("====ig 牛逼======");
    }
    @Override
    public void find(int id) {
        System.out.println("====ig 牛逼======");
    }
    @Override
    public void find(User user) {
        System.out.println("====ig 牛逼======");
    }
    @Override
    public void find(List list) {
        System.out.println("====ig 牛逼======");
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.service.impl;
import com.teng.dao.impl.UserDaoImpl;
import com.teng.domain.User;
import com.teng.service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService {
    private UserDaoImpl userDao;
    private List list;
    @Override
    public void find() {
        userDao.find();
    }
    @Override
    public void find(int id) {
        userDao.find(id);
    }
    @Override
    public void find(User user) {
        userDao.find(user);
    }
    @Override
    public void find(List list) {
        userDao.find(list);
    }
    public void setUserDao(UserDaoImpl userDao) {
        this.userDao = userDao;
    }
    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
}

实现的方法实行前代码和方法执行后代码

LogManager

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.util;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class LogManager implements MethodBeforeAdvice, AfterReturningAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("方法执行前日志--------ig 牛逼");
    }

    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("方法执行后日志--------ig 牛逼");
    }
}

自定义日志切面类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.util;

import org.aspectj.lang.ProceedingJoinPoint;

/*
* 自定义日志切面 不需要实现接口
* */
public class Log {
    public void before(){
        System.out.println("----before----");
    }
    public void after(){
        System.out.println("----after----");
    }
    public void around(ProceedingJoinPoint joinPoint){
        System.out.println("----around 前置-----");
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("----around 后置-----");
    }
    public void throwing1(){
        System.out.println("========throw=======");
    }
}

测试类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng;

import com.teng.domain.User;
import com.teng.service.UserService;
import com.teng.service.impl.UserServiceImpl;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.activation.FileDataSource;
import java.util.List;
/*
* spring创建对象:代理模式
* 使用者  代理商                           厂家
* user    User uer = new User()         User
*           静态代理  提前生产对象
*           动态代理   使用的时候生产对象
* */
public class TestUser {
    @Test
    public void test1(){
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("/spring.xml");
        UserService userService = (UserService) beanFactory.getBean("userService");
        userService.find();
    }
    @Test
    public void test2(){
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("/spring.xml");
       //jdk代理
        UserService userService = (UserService) beanFactory.getBean("userService");
        //cglib  代理  配置文件中
        UserServiceImpl userServiceImpl = beanFactory.getBean(UserServiceImpl.class);
        userService.find();
        /*userService.find(11);
        User user = (User) beanFactory.getBean("user");
        userService.find(user);
        List list = userServiceImpl.getList();
        userService.find(list);*/
    }
}

执行结果

使用注解

在applicationContext.xml中加上

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!--开启注解扫描功能-->
<context:annotation-config></context:annotation-config>
<!--定义注解扫描的包-->
<context:component-scan base-package="com.teng"></context:component-scan>
<!--开启aop自动代理模式-->
    <aop:aspectj-autoproxy proxy-target-class="true" />

在User类上加上@Component(value=“user”)//注入beanfactory中

UserDaoImpl和UserServiceImpl代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.dao.impl;

import com.teng.dao.UserDao;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.security.interfaces.RSAKey;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.List;

@Repository(value = "userDao")
public class UserDaoImpl implements UserDao {
    @PostConstruct//定义初始化是执行的方法
   public void init(){
       System.out.println("11111111111111");
   }
    @Override
    public void find() {
        System.out.println("=====ig  牛逼=======");
    }
    @PreDestroy//定义被销毁之前执行的方法
    public void destroy(){
        System.out.println("222222222222");
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.service.impl;

import com.teng.dao.UserDao;
import com.teng.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service(value = "userService")
public class UserServiceImpl implements UserService {
    /*
    @Resource  默认情况下通过属性名称查找 id= userDao 的bean
    如果通过名称找到,直接返回对应的bean
    如果通过名称没有找到,然后通过类型查找 UserDao UserDaoImplb
     @Resource(name = "userDao") 只通过name查找
    */
    /*@Resource(name = "userDao")
    private UserDao userDao;*/
    /*
    *  @Autowired 自动装配 先找class,如果一个接口只有一个实现类,直接找到对应实现类
    *  如果一个接口有多个实现类,再通过名称查找
    *
    *  @Autowired
    @Qualifier(value = "userDao")
    只能通过名称查找  byName
    * */
    @Autowired
    @Qualifier(value = "userDao")
    private UserDao userDao;
    @Override
    public void find() {
        userDao.find();
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

自定义切面类的注解

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.teng.util;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * Created by Administrator on 2018/11/22 0022.
 * 自定义日志切面 不需要实现接口
 */
@Aspect//标志是切面
@Component(value = "log")//注入beanfactory中
public class Log {
	// 定义在哪个层导入切面
    @Pointcut("execution(* com.teng.service.impl.*.*(..))")
     public void log(){
        System.out.println("++++++");
    }

    @Before(value = "log()")//方法执行前
    public void before(){
        System.out.println("-----before-----");
    }

    @AfterReturning(value = "log()")//方法执行后返回结果后执行
    public void after(){
        System.out.println("-----after-----");
    }
     @Around(value = "log()")//环绕
    public void around(ProceedingJoinPoint joinPoint){
        System.out.println("-------around 前置---------");
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("-------around 后置---------");
    }
}

测试结果是,在执行find方法时,执行这些方法。111111111是初始化userService时执行的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年11月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
17个场景,带你入门CSS布局
CSS 布局本质就是控制元素的位置和大小。比如这样的布局:元素宽960px,水平居中。宽960px是大小。水平居中是位置。又如这样的布局:两个元素在一行,左侧元素固定宽200px,右侧元素撑满剩余空间。固定宽200px,撑满剩余空间是大小。两个元素在一行是位置。
前端GoGoGo
2020/03/20
2.8K0
【面试题解】CSS盒子模型与margin负值
盒子模型,顾名思义,可以装东西的称为盒子,比如 div,h,li 等等。像 img,input 这种不能装东西的就不是盒子。
一尾流莺
2022/12/10
3200
【面试题解】CSS盒子模型与margin负值
CSS&HTML面经专题——(三)CSS定位/盒模型/经典布局/浮动布局与BFC
position:static | relative | absolute | fixed | center | page | sticky
玖柒的小窝
2021/10/26
2.1K0
CSS&HTML面经专题——(三)CSS定位/盒模型/经典布局/浮动布局与BFC
CSS3弹性盒布局
使用自适应的窗口弹性盒布局 可以使div总宽度等于浏览器宽度,而且可以随着浏览器的改变而改变。 1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 <head> 4 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 5 <meta http-equiv="x-ua-compatible" content="IE=edge"> 6 <meta name=
就只是小茗
2018/03/07
1.1K0
CSS3弹性盒布局
前端课程——布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .container { width: 600px; height: 400px; border: 1px solid black; margin: 0 auto; display: table; table-layout: fixed; } .left,.right{ display: table-cell; } .left { width: 200px; height: 100%; background-color: lightcoral; } .right { height: 100%; background-color: lightskyblue; margin-left: 200px; } </style> </head> <body> <div class="container"> <div class="left"></div> <div class="right"></div> </div> </body> </html>
Dreamy.TZK
2020/04/09
5080
python测试开发django-134.CSS页面布局:左侧固定,右侧自适应布局
常见的后台管理页面,左侧固定宽度展示操作菜单栏,右侧显示左侧展示管理内容。 这是一种最常见的左侧固定,右侧自适应布局方式。
上海-悠悠
2021/10/08
9880
双飞翼布局的改造 box-sizing和margin负值的应用
box-sizing + margin负值 升级双飞翼布局 一、box-sizing属性 .content-size, .border-size{ width: 200px; heig
sam dragon
2018/01/17
7160
双飞翼布局的改造 box-sizing和margin负值的应用
css经典布局——圣杯布局
圣杯布局和双飞翼布局一直是前端面试的高频考点,圣杯布局的出现是来自由 Matthew Levine 在 2006 年写的一篇文章 《In Search of the Holy Grail》。 比起双飞翼布局,它的起源不是源于对页面的形象表达。在西方,圣杯是表达“渴求之物”的意思。而双飞翼布局则是源于淘宝的UED,可以说是灵感来自于页面渲染。
全栈程序员站长
2022/07/21
2.8K0
css经典布局——圣杯布局
《CSS 世界》读书笔记-流与宽高
1. 前言 在学习 CSS 的过程中,我经常会被数不清的属性和特性弄得晕头转向。作为前端新手,经常会坐在显示器前花很多很多时间去 “追” 视觉稿,也经常会在 “为什么这个属性不生效” 和 “为什么这个属性生效了但是不是我想要的效果” 之间摇摆,直到我开始看张鑫旭老师的《CSS 世界》,才开始渐渐地走进 CSS 世界,才明白原来 CSS 的背后也是有一套 “物理” 和 “魔法” 法则。遵循着法则,很多问题也许会迎刃而解。 因为在阅读本书 CSS 的 “流” 相关内容时让我有了一种恍然大悟的感觉,所以才有了此篇
用户1097444
2022/07/12
1.4K0
《CSS 世界》读书笔记-流与宽高
前端-彻底学会CSS布局-这是最全的
其实,我们可能经常在聊组件化,咋地咋地。但是,回过头来思考一下,如果你看到一张设计稿的时候,连布局都不清不楚,谈何组件化呢。所以,我们需要在分清楚组件之前,先来分清楚布局。废话说了这么多,只是想告诉你,布局这个东西真的很重要。本篇内容概括了布局的基础+基本的PC端布局+移动端适配等内容。如果你喜欢我的文章,欢迎评论,欢迎Star~。欢迎关注我的github博客
grain先森
2019/03/29
1.1K0
前端-彻底学会CSS布局-这是最全的
一文搞定各类前端常见布局方式
缺点:若子元素脱离文档流,会导致 margin 失效,如 float、absolute、fixed
CS逍遥剑仙
2022/08/13
2.1K0
纯CSS实现左右拖拽改变布局大小 使用CSS3中resize属性 水平,垂直拖动元素,改变大小
利用浏览器非overflow:auto元素设置resize可以拉伸的特性实现无JavaScript的分栏宽度控制。
拿我格子衫来
2022/01/24
5.3K0
纯CSS实现左右拖拽改变布局大小 使用CSS3中resize属性  水平,垂直拖动元素,改变大小
不可忽视的CSS布局
CSS布局是一个前端必备的技能,HTML如果说是结构之美,CSS就是视觉之美可以给用户不一样的体验的效果和视觉冲击。如果一个大方美观的布局,用户第一眼看到会很舒服,不仅提高了用户的视觉效果也提高了用户的体验效果。随着现在设备种类的增多,各种大小不一,奇形怪状的设备使得前端开发的压力不断增大,越来越多的UI框架层出不群,我们就会忽略了最基本的CSS,下面总结了一些经常用到的CSS布局,一起学习和进步。
小丑同学
2020/09/21
6240
css布局 - 工作中常见的两栏布局案例及分析
  突然想到要整理这么一篇平时工作中相当常见但是我们又很忽视的布局的多种处理方法。临时就在我经常浏览的网站上抓的相对应的截图。(以后看到其他类型的我再补充)
xing.org1^
2019/01/28
3K0
前端常用布局方案总结
若元素为行内块级元素,可以通过为其父元素设置text-align: center 实现水平居中。
越陌度阡
2022/05/06
2.8K0
前端常用布局方案总结
HTML & CSS页面布局之定位
默认情况下,HTML元素都在标准流中呈现和展示。我们之前把元素分为块级元素,行内元素,行内块级元素,他们的特性是块级独占一行,行内和行内块级可以在一行内共存,这些特性都是针对标准流的。总结一下就是,标准流中元素只能在水平或垂直方向上排版。如果元素是块级元素, 那么就会垂直排版,如果元素是行内元素/行内块级元素, 那么就会水平排版。
用户5997198
2020/05/12
5.6K0
Html和CSS布局技巧(转)
水平居中的页面布局中最为常见的一种布局形式,多出现于标题,以及内容区域的组织形式,下面介绍四种实现水平居中的方法(注:下面各个实例中实现的是child元素的对齐操作,child元素的父容器是parent元素)
山河木马
2019/03/05
4.9K0
百度Web前端技术学院(1)-HTML, CSS基础
百度前端学院的第一次任务笔记,HTML、CSS 基础。主要有 CSS 工作原理,选择器的使用,常用属性,行高属性,盒模型与定位,最后根据设计图实现 4 个页面。
零式的天空
2022/03/22
1.1K0
三. CSS layout(布局)
网页是一个多层的结构,一层摞着一层,通过CSS可以分别为每一层来设置样式,作为用户来讲只能看到最顶上一层,这些层中,最底下的一层称为文档流,文档流是网页的基础, 我们所创建的元素默认都是在文档流中进行排列,
小海怪的互联网
2020/09/22
2.3K0
回顾div+css几种经典布局
什么是三列布局 经典的三栏布局:左右量栏固定,中间宽度自适应 可以利用浮动,定位,fiex布局,gird布局等方法来实现 以下是几种可以实现三列布局的方法,各有优缺点
不愿意做鱼的小鲸鱼
2022/09/24
1.8K0
回顾div+css几种经典布局
相关推荐
17个场景,带你入门CSS布局
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档