国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

三步實(shí)現(xiàn)SpringBoot全局日志記錄,整合Echarts實(shí)現(xiàn)數(shù)據(jù)大屏

這篇具有很好參考價值的文章主要介紹了三步實(shí)現(xiàn)SpringBoot全局日志記錄,整合Echarts實(shí)現(xiàn)數(shù)據(jù)大屏。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。


?? 注重版權(quán),轉(zhuǎn)載請注明原作者和原文鏈接文章來源地址http://www.zghlxwxcb.cn/news/detail-837365.html

  • 小袁博客:https://boke.open-yuan.com/
  • 小袁博客后臺:https://boke.open-yuan.com/back-manager/
  • 更多項(xiàng)目內(nèi)容關(guān)注小紅書??OpenYuan開袁 http://xhslink.com/I9zNaC
  • 有需求可以在小袁博客首頁加我微信或者QQ

效果展示

免費(fèi)的api接口網(wǎng)站,# SpringBoot教學(xué),spring boot,echarts,后端,java,vue.js
免費(fèi)的api接口網(wǎng)站,# SpringBoot教學(xué),spring boot,echarts,后端,java,vue.js

MySQL

建表

CREATE TABLE `access_log` (
  `access_log_id` bigint NOT NULL AUTO_INCREMENT,
  `access_time` datetime NOT NULL COMMENT '訪問時間',
  `access_ip` varchar(30) NOT NULL COMMENT '訪問IP',
  `api_group` varchar(50) NOT NULL DEFAULT '默認(rèn)' COMMENT '接口分組',
  `req_url` varchar(100) NOT NULL COMMENT '請求URL',
  `req_method` varchar(10) NOT NULL COMMENT '請求方式',
  `os` varchar(100) NULL DEFAULT NULL COMMENT '操作系統(tǒng)',
  `browser` varchar(50) NULL DEFAULT NULL COMMENT '瀏覽器',
  `lsp` varchar(15) NULL DEFAULT NULL COMMENT '運(yùn)營商',
  `country` varchar(15) NULL DEFAULT NULL COMMENT '國家',
  `province` varchar(15) NULL DEFAULT NULL COMMENT '省',
  `city` varchar(15) NULL DEFAULT NULL COMMENT '城市',
  PRIMARY KEY (`access_log_id`)
) COMMENT='訪問日志表';

后端

POJO實(shí)體

@Data
@TableName(value = "access_log")
public class AccessLog implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 訪問日志ID  
     */
    @TableId(type = IdType.AUTO)
    private Long accessLogId;

    /**
     * 訪問時間  
     */
    private Date accessTime;

    /**
     * 訪問IP  
     */
    private String accessIp;

    /**
     * 接口分組  
     */
    private String apiGroup;

    /**
     * 請求URL  
     */
    private String reqUrl;

    /**
     * 請求方式  
     */
    private String reqMethod;

    /**
     * 操作系統(tǒng)  
     */
    private String os;

    /**
     * 瀏覽器  
     */
    private String browser;

    /**
     * 運(yùn)營商  
     */
    private String lsp;

    /**
     * 國家  
     */
    private String country;

    /**
     * 省  
     */
    private String province;

    /**
     * 城市  
     */
    private String city;
}

Mapper接口

@Repository
public interface AccessLogMapper extends BaseMapper<AccessLog> {
    
}

自定義注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {

    /**
     * 給接口分組
     */
    String apiGroup() default "默認(rèn)";
}

案例:

@Log(apiGroup = "文章模塊")
@RestController
@RequestMapping("/article")
public class ArticleController {
    ......
}

攔截器

ps:https://api.vvhan.com/api/getIpInfo?ip=[你的IP],這個網(wǎng)址是一個免費(fèi)獲取國家、省、市、運(yùn)營商的地址
當(dāng)然這種對IP地址的解析應(yīng)該是放在定時任務(wù)中,每天晚上定時解析日志IP,如果解析IP的API掛了,接口會受到影響,我這里只是為了方便寫在這里

@Slf4j
@Component
public class AccessLogInterceptor implements HandlerInterceptor {
    
    @Autowired
    private AccessLogMapper accessLogMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        
        try {
            // 獲取客戶端真是IP地址,這種網(wǎng)上很多現(xiàn)成代碼
            String accessIp = NetUtil.getRemoteHost(request);
            // 獲取User-Agent
            String requestUserAgent = request.getHeader("User-Agent");
            // 獲取瀏覽器用戶標(biāo)識
            UserAgent userAgent = UserAgentUtil.parse(requestUserAgent);
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Log logAnnotation = handlerMethod.getMethod().getDeclaringClass().getAnnotation(Log.class);

            AccessLog accessLog = new AccessLog();
            accessLog.setAccessIp(accessIp);
            accessLog.setAccessTime(new Date());
            if (logAnnotation != null) {
                accessLog.setApiGroup(logAnnotation.apiGroup());
            }
            accessLog.setReqUrl(request.getRequestURI());
            accessLog.setReqMethod(request.getMethod());
            accessLog.setOs(userAgent.getOs().getName());
            accessLog.setBrowser(userAgent.getBrowser().getName());

            // 解析IP
            try {
                String ipParseStr = HttpUtil.get("https://api.vvhan.com/api/getIpInfo?ip=" + accessIp);
                JSONObject ipParseJson = JSONUtil.parseObj(ipParseStr);
                if (ipParseJson.getBool("success")) {
                    JSONObject infoJson = ipParseJson.getJSONObject("info");
                    accessLog.setLsp(infoJson.getStr("lsp"));
                    accessLog.setCountry(infoJson.getStr("country"));
                    accessLog.setProvince(infoJson.getStr("prov"));
                    accessLog.setCity(infoJson.getStr("city"));
                }
            } catch (Exception e) {
                accessLog.setLsp("未知");
                accessLog.setCountry("未知");
                accessLog.setProvince("未知");
                accessLog.setCity("未知");
            }
            accessLogMapper.insert(accessLog);
        } catch (Exception e) {
            log.error("", e);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

注冊攔截器

@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
    
    @Autowired
    private AccessLogInterceptor accessLogInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注冊全局日志攔截器
        registry.addInterceptor(accessLogInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/static/**")
                .excludePathPatterns("/error");

        // 其他攔截器......
    }
}

測試

到這里就完成一個簡單的全局日志攔截器了,隨便發(fā)幾個請求測試一下,成功記錄入庫!
免費(fèi)的api接口網(wǎng)站,# SpringBoot教學(xué),spring boot,echarts,后端,java,vue.js

進(jìn)階——整合Echarts實(shí)現(xiàn)數(shù)據(jù)大屏

數(shù)據(jù)VO實(shí)體

瀏覽器訪問占比情況VO
@Data
public class AccessBrowserGroupVo {
    
    private String browser;
    
    private Integer count;
}
運(yùn)營商訪問占比情況VO
@Data
public class AccessLspGroupVo {
    
    private String lsp;
    
    private Integer count;
}
各省份訪問情況VO
@Data
public class AccessProvinceGroupVo {
    
    private String province;
    
    private Integer count;
}
每天訪問情況VO
@Data
public class AccessTimeGroupVo {
    
    private String accessTime;
    
    private Integer count;
}

查詢SQL

瀏覽器訪問統(tǒng)計(jì)
<select id="countBrowserGroupAccess" resultType="com.xiaoyuan.common.vo.logs.AccessBrowserGroupVo">
  select browser, count(*) as count from access_log group by browser
</select>
運(yùn)營商訪問統(tǒng)計(jì)
<select id="countLspGroupAccess" resultType="com.xiaoyuan.common.vo.logs.AccessLspGroupVo">
  select lsp, count(*) as count from access_log group by lsp
</select>
各省份訪問統(tǒng)計(jì)
<select id="countProvinceGroupAccess" resultType="com.xiaoyuan.common.vo.logs.AccessProvinceGroupVo">
  select province, count(*) as count from access_log group by province order by count desc limit 15
</select>
近15天內(nèi)訪問統(tǒng)計(jì)
<select id="countTimeGroupAccess" resultType="com.xiaoyuan.common.vo.logs.AccessTimeGroupVo">
    SELECT
        date_match.date_c as access_time,
        IFNULL( count, 0 ) as count
    FROM
        (
            SELECT
                DATE_FORMAT( @now := date_sub( @now, INTERVAL 1 DAY ), '%Y-%m-%d' ) AS date_c
            FROM
                ( SELECT @now := date_add( CURDATE(), INTERVAL 1 DAY ) FROM access_log LIMIT 15 ) date_match
            ORDER BY
                date_c
        ) date_match
            LEFT JOIN (
            SELECT
                DATE_FORMAT( access_time, '%Y-%m-%d' ) AS access_time,
                count(*) AS count
            FROM
                access_log
            WHERE
                    access_time >= (
                    SELECT
                        date_sub( curdate(), INTERVAL 15 DAY ))
            GROUP BY
                DATE_FORMAT( access_time, '%Y-%m-%d' )
        ) acc ON acc.access_time = date_match.date_c
</select>

后端業(yè)務(wù)

封裝統(tǒng)一接口返回
/**
 * FileName:    R
 * Author:      小袁
 * Date:        2022/3/12 12:23
 * Description: 統(tǒng)一結(jié)果返回的類
 */
@Data
public class R<T> {

    private Boolean success;

    private Integer code;

    private String message;

    private T data;

    // 成功靜態(tài)方法
    public static <T> R<T> success() {
        R<T> r = new R<>();
        r.setSuccess(true);
        r.setCode(HttpStatusEnum.SUCCESS.getCode());
        r.setMessage(HttpStatusEnum.SUCCESS.getName());
        return r;
    }

    public static <T> R<T> success(String message) {
        R<T> r = new R<>();
        r.setSuccess(true);
        r.setCode(HttpStatusEnum.SUCCESS.getCode());
        r.message(message);
        return r;
    }

    public static <T> R<T> success(T object) {
        R<T> r = new R<>();
        r.setData(object);
        r.setSuccess(true);
        r.setCode(HttpStatusEnum.SUCCESS.getCode());
        r.setMessage(HttpStatusEnum.SUCCESS.getName());
        return r;
    }

    public static <T> R<T> success(String msg, T object) {
        R<T> r = new R<>();
        r.setData(object);
        r.setCode(HttpStatusEnum.SUCCESS.getCode());
        r.setMessage(msg);
        return r;
    }

    // 失敗靜態(tài)方法
    public static <T> R<T> fail() {
        R<T> r = new R<>();
        r.setSuccess(false);
        r.setCode(HttpStatusEnum.FAIL.getCode());
        r.setMessage(HttpStatusEnum.FAIL.getName());
        return r;
    }

    public static <T> R<T> fail(String msg) {
        R<T> r = new R<>();
        r.setSuccess(false);
        r.setCode(HttpStatusEnum.FAIL.getCode());
        r.setMessage(msg);
        return r;
    }

    public static <T> R<T> fail(HttpStatusEnum httpStatusEnum) {
        R<T> r = new R<>();
        r.setSuccess(false);
        r.setCode(httpStatusEnum.getCode());
        r.setMessage(httpStatusEnum.getName());
        return r;
    }

    public R<T> message(String message){
        this.setMessage(message);
        return this;
    }

    public R<T> code(Integer code){
        this.setCode(code);
        return this;
    }

    public R<T> data(T data){
        this.setData(data);
        return this;
    }
}
封裝客戶端響應(yīng)碼
/**
 * FileName:    Code
 * Author:      小袁
 * Date:        2022/5/1 23:29
 * Description: 客戶端響應(yīng)狀態(tài)碼
 */
public enum HttpStatusEnum implements BaseCodeEnum {

    SUCCESS(200, "成功"),
    FAIL(20001, "失敗"),
    INTERNAL_SERVER_ERROR(500, "服務(wù)器異常"),

    private final Integer code;
    private final String name;

    HttpStatusEnum(int code, String msg) {
        this.code = code;
        this.name = msg;
    }

    @Override
    public Integer getCode() {
        return this.code;
    }

    @Override
    public String getName() {
        return this.name;
    }
}
Mapper接口
@Repository
public interface AccessLogMapper extends BaseMapper<AccessLog> {

    List<AccessLspGroupVo> countLspGroupAccess();

    List<AccessBrowserGroupVo> countBrowserGroupAccess();

    List<AccessProvinceGroupVo> countProvinceGroupAccess();

    List<AccessTimeGroupVo> countTimeGroupAccess();
}
Service接口
public interface AccessLogService extends IService<AccessLog> {

    List<AccessLspGroupVo> countLspGroupAccess();

    List<AccessBrowserGroupVo> countBrowserGroupAccess();

    List<AccessProvinceGroupVo> countProvinceGroupAccess();

    List<AccessTimeGroupVo> countTimeGroupAccess();
}
Service實(shí)現(xiàn)類
@Slf4j
@Service
public class AccessLogServiceImpl extends ServiceImpl<AccessLogMapper, AccessLog> implements AccessLogService {
    
    @Override
    public List<AccessLspGroupVo> countLspGroupAccess() {
        return this.baseMapper.countLspGroupAccess();
    }

    @Override
    public List<AccessBrowserGroupVo> countBrowserGroupAccess() {
        return this.baseMapper.countBrowserGroupAccess();
    }

    @Override
    public List<AccessProvinceGroupVo> countProvinceGroupAccess() {
        return this.baseMapper.countProvinceGroupAccess();
    }

    @Override
    public List<AccessTimeGroupVo> countTimeGroupAccess() {
        return this.baseMapper.countTimeGroupAccess();
    }
}
Controller接口
@RestController
@RequestMapping("/stat/access")
public class AccessStatController {
    
    @Autowired
    private AccessLogService accessLogService;

    /**
     * 查詢15天內(nèi)的訪問次數(shù)情況-折線圖
     */
    @GetMapping("/query_line_by_day")
    public R<List<AccessTimeGroupVo>> queryAccessLogByTimeGroup() {
        return R.success(accessLogService.countTimeGroupAccess());
    }

    /**
     * 查詢省份訪問占比-柱形圖
     */
    @GetMapping("/query_col_by_province")
    public R<List<AccessProvinceGroupVo>> queryAccessLogByProvinceGroup() {
        return R.success(accessLogService.countProvinceGroupAccess());
    }

    /**
     * 查詢運(yùn)營商訪問占比-餅圖
     */
    @GetMapping("/query_pie_by_lsp")
    public R<List<AccessLspGroupVo>> queryAccessLogByLspGroup() {
        return R.success(accessLogService.countLspGroupAccess());
    }

    /**
     * 查詢?yōu)g覽器訪問占比-餅圖
     */
    @GetMapping("/query_pie_by_browser")
    public R<List<AccessBrowserGroupVo>> queryAccessLogByBrowserGroup() {
        return R.success(accessLogService.countBrowserGroupAccess());
    }
}

前端配置

安裝axios、echarts
npm install axios
npm install echarts
封裝request
import axios from 'axios'
import { Message, MessageBox,} from 'element-ui'
import store from '../store'
import { getToken } from '@/utils/auth'
import router from '@/router'

// 創(chuàng)建axios實(shí)例
const service = axios.create({
  baseURL: process.env.BASE_API, // api 的 base_url
  // timeout: 5000 // 請求超時時間
})

// request攔截器
service.interceptors.request.use(
  config => {
    if (store.getters.token) {
     config.headers['token'] = getToken()
    }
    return config
  },
  error => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
  }
)

// response 攔截器
service.interceptors.response.use(
  response => {
    /**
     * code為非200是拋錯 可結(jié)合自己業(yè)務(wù)進(jìn)行修改
     */
    const res = response.data

    const url = response.config.url

    if (res.code !== 200) {
      if (url.indexOf("/login") < 0 && res.code === 40005) {
        store.dispatch('FedLogOut').then(() => {
          router.push(`/login`)
        })
        Message({
          message: res.message,
          type: 'warning',
          duration: 2 * 1000,
        })

        return Promise.resolve(res)
      }else if (res.code >= 40000) {
        Message({
          message: res.message,
          type: 'error',
          duration: 3 * 1000
        })
        return Promise.resolve(res)
      }else {
        Message({
          message: res.message,
          type: 'error',
          duration: 5 * 1000
        })
        return Promise.reject(new Error(res.message || 'Error'))
      }
    } else {
      return res
    }
  },
  error => {
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service
定義API
import request from "../../utils/request";

export default {
  getAccessStatByTime() {
    return request({
      url: '/stat/access/query_line_by_day',
      method: 'get'
    })
  },

  getAccessStatByProvince() {
    return request({
      url: '/stat/access/query_col_by_province',
      method: 'get'
    })
  },

  getAccessStatByLsp() {
    return request({
      url: '/stat/access/query_pie_by_lsp',
      method: 'get'
    })
  },

  getAccessStatByBrowser() {
    return request({
      url: '/stat/access/query_pie_by_browser',
      method: 'get'
    })
  },
}
封裝echarts
<template>
  <div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>

<script>
import * as echarts from 'echarts'
export default {
  name: 'echart',
  props: {
    className: {
      type: String,
      default: 'chart'
    },
    id: {
      type: String,
      default: 'chart'
    },
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '2.5rem'
    },
    options: {
      type: Object,
      default: ()=>({})
    }
  },
  data () {
    return {
      chart: null
    }
  },
  watch: {
    options: {
      handler (options) {
        // 設(shè)置true清空echart緩存
        this.chart.setOption(options, true)
      },
      deep: true
    }
  },
  mounted () {
    // echarts.registerTheme('tdTheme', tdTheme); // 覆蓋默認(rèn)主題
    this.initChart();
  },
  beforeDestroy () {
    this.chart.dispose()
    this.chart = null
  },
  methods: {
    initChart () {
      // 初始化echart
      this.chart = echarts.init(this.$el)
      this.chart.setOption(this.options, true)
    }
  }
}
</script>

<style>
body {
  margin: 0;
  padding: 0;
}
</style>
餅圖-瀏覽器訪問占比
<template>
  <div>
    <Echart :options="options"
      id="lspEcharts"
      height="300px"
      width="100%"/>
  </div>
</template>

<script>
  import statAccess from "@/api/stat/statAccess";
  import Echart from "@/components/Echart/index.vue";

  export default {
    components: {
      Echart
    },
    data() {
      return {
        options: {},
        lspData: []
      }
    },
    methods: {
      initData() {
        statAccess.getAccessStatByBrowser().then(res => {
          this.lspData = res.data.map(obj => {
            return {
              name: obj.browser,
              value: obj.count
            }
          })
          this.executeDraw()
        })
      },
      executeDraw() {
        this.options = {
          title: {
            text: '瀏覽器訪問占比',
            left: 'center',
            textStyle: {
              color: '#FDF5E6'
            }
          },
          tooltip: {
            trigger: 'item'
          },
          legend: {
            orient: 'vertical',
            left: 'left',
            top: '20%',
            textStyle: {
              color: '#FDF5E6'
            }
          },
          series: [
            {
              name: '訪問次數(shù)',
              type: 'pie',
              radius: '90%',
              top: '20%',
              data: this.lspData,
              label: {
                color: '#FDF5E6'
              },
              emphasis: {
                itemStyle: {
                  shadowBlur: 10,
                  shadowOffsetX: 0,
                  shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
              }
            }
          ]
        }
      }
    },
    mounted() {
      this.initData()
    }
  }
</script>
餅圖-運(yùn)營商訪問占比
<template>
  <div>
    <Echart :options="options"
            id="lspEcharts"
            height="300px"
            width="100%"/>
  </div>
</template>

<script>
import statAccess from "@/api/stat/statAccess";
import Echart from "@/components/Echart/index.vue";

export default {
  components: {
    Echart
  },
  data() {
    return {
      options: {},
      lspData: []
    }
  },
  methods: {
    initData() {
      statAccess.getAccessStatByLsp().then(res => {
        this.lspData = res.data.map(obj => {
          return {
            name: obj.lsp,
            value: obj.count
          }
        })
        this.executeDraw()
      })
    },
    executeDraw() {
      this.options = {
        title: {
          text: '運(yùn)營商訪問占比',
          left: 'center',
          textStyle: {
            color: '#FDF5E6'
          }
        },
        tooltip: {
          trigger: 'item'
        },
        legend: {
          orient: 'vertical',
          left: 'left',
          top: '20%',
          textStyle: {
            color: '#FDF5E6'
          }
        },
        series: [
          {
            name: '訪問次數(shù)',
            type: 'pie',
            radius: '90%',
            top: '20%',
            data: this.lspData,
            label: {
              color: '#FDF5E6'
            },
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
              }
            }
          }
        ]
      }
    }
  },
  mounted() {
    this.initData()
  }
}
</script>
折線圖-每天訪問量情況
<template>
  <div>
    <Echart :options="options"
            id="timeEcharts"
            height="400px"
            width="100%"/>
  </div>
</template>

<script>
import statAccess from "@/api/stat/statAccess";
import Echart from "@/components/Echart/index.vue";

export default {
  components: {
    Echart
  },
  data() {
    return {
      options: {},
      xAxis: [],
      yAxis: []
    }
  },
  methods: {
    initData() {
      statAccess.getAccessStatByTime().then(res => {
        let x = []
        let y = []
        for (let i = 0; i < res.data.length; i++) {
          x.push(res.data[i].accessTime)
          y.push(res.data[i].count)
        }
        this.xAxis = x
        this.yAxis = y
        this.executeDraw()
      })
    },
    executeDraw() {
      this.options = {
        title: {
          show: true,
          text: '小袁博客15天內(nèi)訪問情況統(tǒng)計(jì)',
          left: 'center',
          textStyle: {
            color: '#FDF5E6'
          }
        },
        legend: {
          show: true,
          left: '1%',
          textStyle: {
            color: '#FDF5E6'
          }
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'line' }
        },
        grid:{
          left:"1%",
          right:"1%",
          bottom:"1%",
          containLabel:true,
        },
        xAxis: {
          type: 'category',
          data: this.xAxis,
          boundaryGap: ['5%', '5%',],//坐標(biāo)軸兩邊留白
          axisLabel: {
            color: '#FDF5E6'
          },
          axisLine: {//坐標(biāo)軸
            lineStyle:{
              opacity: 0.01,//設(shè)置透明度就可以控制顯示不顯示
            },
          },
          splitLine: {//網(wǎng)格線
            lineStyle:{
              color: '#eeeeee',
            },
          },
          axisTick: {//刻度線
            show: false,//去掉刻度線
          },
        },
        yAxis: {
          type: 'value',
          name:'次         ',//是基于Y軸線對齊,用空格站位讓坐標(biāo)軸名稱與刻度名稱對齊
          axisLabel: {
            color: '#eee'
          },
          nameTextStyle: {
            color:'#444e65',
            align:'left',//文字水平對齊方式
            verticalAlign:'middle',//文字垂直對齊方式
          },
          axisTick: {//刻度線
            show: false,//去掉刻度線
          },
          axisLine: {//坐標(biāo)軸線
            lineStyle:{
              opacity: 0,//透明度為0
            },
          },
          splitLine: {//網(wǎng)格線
            show: true,//網(wǎng)格線
            lineStyle:{
              color: 'rgba(211, 211, 211, 0.5)',
            },
          },
        },
        series: [
          {
            data: this.yAxis,
            smooth: true,
            type: 'line',
            name: '訪問次數(shù)',
            itemStyle: {//折線拐點(diǎn)標(biāo)志的樣式。
              normal: {
                color: '#98F5FF',
              },
            },
          }
        ]
      }
    }
  },
  mounted() {
    this.initData()
  }
}
</script>
柱狀圖-各省份訪問情況
<template>
  <div>
    <Echart :options="options"
            id="lspEcharts"
            height="300px"
            width="100%"/>
  </div>
</template>

<script>
import statAccess from "@/api/stat/statAccess";
import Echart from "@/components/Echart/index.vue";

export default {
  components: {
    Echart
  },
  data() {
    return {
      options: {},
      axis: [],
      series: []
    }
  },
  methods: {
    initData() {
      statAccess.getAccessStatByProvince().then(res => {
        let x = []
        let y = []
        for (let i = 0; i < res.data.length; i++) {
          x.push(res.data[i].province)
          y.push(res.data[i].count)
        }
        this.axis = x
        this.series = y
        this.executeDraw()
      })
    },
    executeDraw() {
      this.options = {
        tooltip: {},
        title: {
          text: '各城市訪問情況占比',
          left: 'center',
          textStyle: {
            color: '#FDF5E6'
          }
        },
        grid:{
          left: "1%",
          right: "1%",
          bottom: "1%",
          containLabel: true,
        },
        legend: {
          show: true,
          left: '1%',
          textStyle: {
            color: '#FDF5E6'
          }
        },
        xAxis: {
          data: this.axis,
          axisLine: {
            show: false,
          },
          axisLabel: {
            color: '#FDF5E6'
          }
        },
        yAxis: {
          // 網(wǎng)格樣式
          splitLine: {
            show: false,
          },
          axisLabel: {
            color: '#FDF5E6'
          }
        },
        series: [{
          name: '訪問量',
          type: 'bar',
          data: this.series,
          barWidth: 15,
          itemStyle: {
            color: {
              type:'linear',
              x: 0,
              y: 0,
              x2: 0,
              y2: 1,
              colorStops: [
                {
                  offset: 0,
                  color: 'rgba(255, 130, 71, 1)',
                },
                {
                  offset: 1,
                  color: 'rgba(255, 130, 71, 0.5)',
                },
              ],
              globaCoord: false,
            },
            barBorderRadius: [5, 5, 0, 0], // (順時針左上,右上,右下,左下)
          },
        }],
      }
    }
  },
  mounted() {
    this.initData()
  }
}
</script>
首頁

直接引入

<template>
  <div class="dashboard-container">
    <div class="dashboard-bg"></div>
    <div class="echart-div">
      <el-row :gutter="1" class="item">
      <el-col :span="8">
        <BrowserPie></BrowserPie>
      </el-col>
      <el-col :span="16">
        <TimeLine></TimeLine>
      </el-col>
      </el-row>
      <el-row style="margin-top: 35px" class="item">
        <el-col span="8">
          <LspPie></LspPie>
        </el-col>
        <el-col span="16">
          <ProvinceCol></ProvinceCol>
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<script>
import LspPie from "./components/LspPie.vue";
import ProvinceCol from "./components/ProvinceCol.vue";
import BrowserPie from "./components/BrowserPie.vue";
import TimeLine from "./components/TimeLine.vue";

export default {
  components: {
    LspPie,
    ProvinceCol,
    BrowserPie,
    TimeLine
  },
  name: 'home',
  data() {
    return {
    }
  },
  mounted() {
  },
  methods: {
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
.dashboard {
  &-container {
    .echart-div {
      padding: 30px;
    }
  }
  &-text {
    font-size: 22px;
    line-height: 46px;
  }
  .personal {
    .box-card-header {
      position: relative;
      height: 220px;
      img {
        width: 100%;
        height: 100%;
        transition: all 0.2s linear;
        &:hover {
          transform: scale(1.1, 1.1);
          filter: contrast(130%);
        }
      }
    }
  }
}
.dashboard {
  &-bg {
    background-image: url('../../assets/img/home_bg.png');
    background-size: cover;
    background-repeat: no-repeat;
    background-attachment: fixed; /* 可選,固定背景圖片 */
    background-position: center; /* 可選,設(shè)置背景圖片位置 */
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    filter: blur(1px);
  }
}
</style>

結(jié)束

到這里整篇文章就結(jié)束了,我們重新捋一下整個流程

  • 全局過濾器攔截請求
  • 對請求信息進(jìn)行解析入庫
  • 定義API接口
  • 前端引入axios、echarts
  • 編寫圖形Vue組件
  • 前后端數(shù)據(jù)交互

?? 注重版權(quán),轉(zhuǎn)載請注明原作者和原文鏈接

  • 小袁博客:https://boke.open-yuan.com/
  • 小袁博客后臺:https://boke.open-yuan.com/back-manager/
  • 更多項(xiàng)目內(nèi)容關(guān)注小紅書??OpenYuan開袁 http://xhslink.com/I9zNaC
  • 有需求可以在小袁博客首頁加我微信或者QQ

到了這里,關(guān)于三步實(shí)現(xiàn)SpringBoot全局日志記錄,整合Echarts實(shí)現(xiàn)數(shù)據(jù)大屏的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • SpringBoot(57) 整合Plumelog實(shí)現(xiàn)日志查詢

    SpringBoot(57) 整合Plumelog實(shí)現(xiàn)日志查詢

    一、前言 Plumelog 一個簡單易用的java分布式日志組件 https://gitee.com/plumeorg/plumelog 二、docker-compose一鍵搭建日志服務(wù) plumelog + elasticsearch + redis tips: 詳情可查看 https://gitee.com/zhengqingya/docker-compose 訪問地址:ip地址:8891 賬號:admin 密碼:admin docker-compose.yml 三、SpringBoot整合Plumelog 1、

    2023年04月24日
    瀏覽(13)
  • 【二十八】springboot整合logback實(shí)現(xiàn)日志管理

    【二十八】springboot整合logback實(shí)現(xiàn)日志管理

    ????????本章節(jié)是記錄logback在springboot項(xiàng)目中的簡單使用,本文將會演示如何通過logback將日志記錄到日志文件或輸出到控制臺等管理操作。將會從以下幾個方面進(jìn)行講解。最后實(shí)現(xiàn)將特定級別的特定日志保存到日志文件。 一、依賴 以上版本只是測試時使用,實(shí)際版本根據(jù)

    2024年02月20日
    瀏覽(30)
  • SpringBoot應(yīng)用整合并使用Docker安裝ELK實(shí)現(xiàn)日志收集

    SpringBoot應(yīng)用整合并使用Docker安裝ELK實(shí)現(xiàn)日志收集

    ELK即Elasticsearch、Logstash、Kibana,組合起來可以搭建線上日志系統(tǒng),本文主要講解使用ELK來收集SpringBoot應(yīng)用產(chǎn)生的日志。 Elasticsearch:用于存儲收集到的日志信息; Logstash:用于收集日志,SpringBoot應(yīng)用整合了Logstash以后會把日志發(fā)送給Logstash,Logstash再把日志轉(zhuǎn)發(fā)給Elasticsearch; Kiban

    2023年04月08日
    瀏覽(20)
  • SpringBoot實(shí)現(xiàn)文件記錄日志,日志文件自動歸檔和壓縮

    SpringBoot實(shí)現(xiàn)文件記錄日志,日志文件自動歸檔和壓縮

    ?? @ 作者: Eric ?? @ 主頁: https://blog.csdn.net/weixin_47316183?type=blog ?? @ 主題: SpringBoot實(shí)現(xiàn)文件記錄日志,日志文件自動歸檔和壓縮 ?? @ 創(chuàng)作時間: 2023年08月06日 Logback 是一個Java日志框架,它是 log4j 的后繼者,被廣泛用于應(yīng)用程序中記錄日志。 Logger(日志記錄器): L

    2024年02月14日
    瀏覽(21)
  • SpringBoot項(xiàng)目如何優(yōu)雅的實(shí)現(xiàn)操作日志記錄

    SpringBoot項(xiàng)目如何優(yōu)雅的實(shí)現(xiàn)操作日志記錄

    在實(shí)際開發(fā)當(dāng)中,對于某些關(guān)鍵業(yè)務(wù),我們通常需要記錄該操作的內(nèi)容,一個操作調(diào)一次記錄方法,每次還得去收集參數(shù)等等,會造成大量代碼重復(fù)。 我們希望代碼中只有業(yè)務(wù)相關(guān)的操作,在項(xiàng)目中使用注解來完成此項(xiàng)功能。 通常就是使用Spring中的AOP特性來實(shí)現(xiàn)的,那么在

    2024年01月18日
    瀏覽(23)
  • SpringBoot整合echarts,前后端邏輯

    ?官方網(wǎng)站:https://echarts.apache.org/examples/zh/index.html 0.安裝echarts 1.編寫html 用來顯示圖表,觸發(fā)顯示圖標(biāo)的按鈕 2.引入echart 四版本 五版本 3.編寫調(diào)用方法 編寫方法getDataSta(),用來獲取后端數(shù)據(jù) 4.編寫JS showChart():用來獲取后端傳來的數(shù)據(jù) 其中格式必須為json數(shù)組格式 setChart(

    2024年02月05日
    瀏覽(13)
  • SpringBoot增加全局traceId日志追蹤

    增加Filter處理請求,生成traceId保存到TreadLocal中(slf4j的MDC) 增加返回AOP切面,返回?cái)?shù)據(jù)之前把traceId寫到返回實(shí)體里 日志logback.xml文件配置增加traceId打印 注意:線程池執(zhí)行和其他服務(wù)請求會丟失traceId,需要再做包裝,這里不實(shí)現(xiàn)

    2024年01月25日
    瀏覽(18)
  • 1、springboot中使用AOP切面完成全局日志

    1、springboot中使用AOP切面完成全局日志 可選擇在控制臺輸出日志或者收集日志信息存儲進(jìn)數(shù)據(jù)庫中 1、在配置 AOP 切面之前,我們需要了解下 aspectj 相關(guān)注解的作用: @Aspect :作用是把當(dāng)前類標(biāo)識為一個切面、供容器讀取 @Pointcut :(哪些方法或者類需要進(jìn)行AOP織入)定義一個

    2024年02月02日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包