当前位置: 首页 > news >正文

【SpringBoot】统一功能处理

目录

🎃1 拦截器

🎀1.1 拦截器的代码实现

🎨1.2 拦截器的实现原理

🧶2 拦截器应用——登录验证

🦺3 异常统一处理

🎭4 统一数据返回格式

🧤4.1 为什么需要统一数据返回格式

🧣4.2 统一返回对象

👘4.3 统一数据处理(强制执行)


本篇文章介绍 Spring Boot 的统一功能处理模块,也就是 AOP 的实战环节。

1 拦截器

没有登录的情况下,会跳转到登录页面。

1.1 拦截器的代码实现

Spring 提供了具体的实现拦截器:HandlerInterceptor,拦截器的实现分为以下两个步骤:

1. 创建自定义拦截器,实现 HandlerInterceptor 接口,重写 preHandle 方法。(执行具体方法之前的预处理)。

2. 将自定义拦截器加入 WebMvcConfigurer 的 addInterceptors 方法中。

package com.example.demo.configuration;import com.example.demo.common.AppVar;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;/*** 自定义拦截器*/
@Component
public class UserInterceptor implements HandlerInterceptor {/*** 返回 true -> 拦截器验证成功,继续执行后续的方法*     false -> 拦截器验证失败,不会执行后续的目标方法* @param request* @param response* @param handler* @return* @throws*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("do UserInterceptor"); // 拦截时候会打印// 业务方法HttpSession session = request.getSession(false);if(session != null &&session.getAttribute(AppVar.SESSION_KEY) != null){// 用户已经登录了return true; // 继续执行后续流程}// 未登录的情况,跳转到 百度response.sendRedirect("https://www.baidu.com");return false;}
}
package com.example.demo.common;/*** 全局变量*/
public class AppVar {// Session Keypublic static final String SESSION_KEY = "SESSION_KEY";
}

package com.example.demo.configuration;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 将自定义拦截器加入到系统配置* 有两种写法* 一是 new 一个 UserInterceptor 对象* 二是 注入的方式*/
@Configuration
public class AppConfig implements WebMvcConfigurer {@Autowiredprivate UserInterceptor userInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// registry.addInterceptor(new UserInterceptor());registry.addInterceptor(userInterceptor).addPathPatterns("/**") // 拦截所有请求.excludePathPatterns("/user/reg") // 登录页面不拦截.excludePathPatterns("/user/login") // 注册页面不拦截;}
}

 * 一级路由,** 所有路由。

/user 就是一级路由,/user/reg 是二级路由。

addPathPatterns 表示需要拦截的 URL,** 表示拦截所有方法

excludePathPattern 表示需要排除的 URL 

package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/getuser")public String getUser(){System.out.println("do getUser()");return "getuser";}@RequestMapping("/reg")public String reg(){System.out.println("do reg()");return "reg";}@RequestMapping("/login")public String getlogin(){System.out.println("do login()");return "login";}
}

输出:

do UserInterceptor
do reg()
do login()

1.2 拦截器的实现原理

正常情况下的调用顺序:

有了拦截器之后,在调用 controller 之前,会执行拦截器,如果为 true,则继续执行后续程序,如果为 false,则跳转相关页面。

2 拦截器应用——登录验证

package com.example.demo.configuration;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 将自定义拦截器加入到系统配置* 有两种写法* 一是 new 一个 UserInterceptor 对象* 二是 注入的方式*/
@Configurationpublic class AppConfig implements WebMvcConfigurer {@Autowiredprivate UserInterceptor userInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// registry.addInterceptor(new UserInterceptor());registry.addInterceptor(userInterceptor).addPathPatterns("/**") // 拦截所有请求.excludePathPatterns("/user/reg") // 登录页面不拦截.excludePathPatterns("/reg.html").excludePathPatterns("/login.html").excludePathPatterns("/css/**").excludePathPatterns("/editor.md/**").excludePathPatterns("/img/**").excludePathPatterns("/js/**").excludePathPatterns("/user/login") // 注册页面不拦截.excludePathPatterns("/image/**") // image 文件下所有的图片格式拦截;}
}

除了注册页面、登录页面之外,其余页面都会跳转到百度。

3 异常统一处理

    @RequestMapping("/reg")public String reg(){System.out.println("do reg()");Object obj = null;System.out.println(obj.hashCode());return "reg";}

如果每个页面都出现异常,可不可以统一处理呢?

出现的所有异常按照统一的格式返回: 

package com.example.demo.common;import lombok.Data;/*** 统一返回对象*/
@Data
public class ResultAjax {private int code;  // 状态码private String msg; // 状态码的描述信息private Object data; // 返回数据
}

异常统一处理时,需要两个注解。一个是 @ControllerAdvice / @RestControllerAdvice ,另一个是 @ExceptionHandler(Exception.class) 统一返回对象。

package com.example.demo.configuration;import com.example.demo.common.ResultAjax;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;@RestControllerAdvice
public class ExceptionAdvice {@ExceptionHandler(NullPointerException.class)public ResultAjax doNullPointerException(NullPointerException e){ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(-1);resultAjax.setMsg("空指针异常:"+e.getMessage());resultAjax.setData(null);return resultAjax;}
}

再举一个算术异常的例子:

由于所有的异常都继承自 Exception,所以  @ExceptionHandler(Exception.class) 里面的异常类不用写那么详细也可以:

    @RequestMapping("/login")public String login(){System.out.println("do login()");int num = 10 / 0;return "login";}
    @ExceptionHandler(Exception.class)public ResultAjax doException(Exception e){ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(-1);resultAjax.setMsg("异常:"+e.getMessage());resultAjax.setData(null);return resultAjax;}

4 统一数据返回格式

4.1 为什么需要统一数据返回格式

统⼀数据返回格式的优点有很多,⽐如以下⼏个:

1. ⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据。

2. 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就⾏了,因为所有接⼝都是这样返回 的。

3. 有利于项⽬统⼀数据的维护和修改。

4. 有利于后端技术部⻔的统⼀规范的标准制定,不会出现稀奇古怪的返回内容。

4.2 统一返回对象

对 ResultAjax 这个类进行改造,添加两种方法,一是成功之后返回的数据,二是失败之后返回的数据。

package com.example.demo.common;import lombok.Data;/*** 统一返回对象*/
@Data
public class ResultAjax {private int code;  // 状态码private String msg; // 状态码的描述信息private Object data; // 返回数据/*** 成功时返回* @param data* @return*/public static ResultAjax success(Object data){ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(200);resultAjax.setMsg("");resultAjax.setData(data);return resultAjax;}public static ResultAjax success(String msg, Object data){ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(200);resultAjax.setMsg(msg);resultAjax.setData(data);return resultAjax;}public static ResultAjax fail(int code, String msg){ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(code);resultAjax.setMsg(msg);resultAjax.setData(null);return resultAjax;}public static ResultAjax fail(int code, String msg, Object data){ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(code);resultAjax.setMsg(msg);resultAjax.setData(data);return resultAjax;}}
package com.example.demo.controller;import com.example.demo.common.ResultAjax;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/getuser")public ResultAjax getUser(){System.out.println("do getUser()");return ResultAjax.success("getuser");}@RequestMapping("/reg")public ResultAjax reg(){System.out.println("do reg()");return ResultAjax.success("reg");}@RequestMapping("/login")public ResultAjax login(){System.out.println("do login()");return ResultAjax.success("login");}
}

4.3 统一数据处理(强制执行)

如果就是有人不按要求返回 ResultAjax 这一格式呢?比如下面这样:

    @RequestMapping("getnum")public int getNum(){System.out.println("getNum()");return 1;}

这时就可以对返回的数据进行统一处理,这是强制执行的。

使用:

1. @ControllerAdvice 

2. 实现 ResponseBodyAdvice 接口,并重写它的两个方法,supports 必须返回 true,beforeBodyWrite 方法中进行重新判断和重写操作。

package com.example.demo.configuration;import com.example.demo.common.ResultAjax;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;@ControllerAdvice
public class ResponAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType,MediaType selectedContentType,Class selectedConverterType,ServerHttpRequest request,ServerHttpResponse response) {// 已经包装好的对象// body 是 ResultAjax 的格式if(body instanceof ResultAjax){return body;}// 对字符串进行判断和处理// 重新封装成 ResultAjax 的格式return ResultAjax.success(body);}
}

    @RequestMapping("/getstr")public String getStr(){System.out.println("getStr()");return "whoooooo~~";}

 如果返回的是 String,而不是 int 类型,会报错。在把 String 转化成 json格式的时候报错了。所以对于返回类型是 String 的话,需要单独处理。不使用 String 解析引擎,而是手动转成 json。

package com.example.demo.configuration;import com.example.demo.common.ResultAjax;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;@ControllerAdvice
public class ResponAdvice implements ResponseBodyAdvice {
//    springboot 框架自动注入@Autowiredprivate ObjectMapper objectMapper;@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType,MediaType selectedContentType,Class selectedConverterType,ServerHttpRequest request,ServerHttpResponse response) {// 已经包装好的对象// body 是 ResultAjax 的格式if(body instanceof ResultAjax){return body;}// 对字符串进行判断和处理// 手动转换成 json 格式if(body instanceof String){ResultAjax resultAjax = ResultAjax.success(body);try {return objectMapper.writeValueAsString(resultAjax);} catch (JsonProcessingException e) {e.printStackTrace();}}return ResultAjax.success(body);}
}

如果返回的是对象呢? 

    @RequestMapping("/usermsg")public User usermsg(){User user = new User();user.setId(263);user.setName("柳飘飘");user.setPassword("96134");return user;}


相关文章:

【SpringBoot】统一功能处理

目录 🎃1 拦截器 🎀1.1 拦截器的代码实现 🎨1.2 拦截器的实现原理 🧶2 拦截器应用——登录验证 🦺3 异常统一处理 🎭4 统一数据返回格式 🧤4.1 为什么需要统一数据返回格式 🧣4.2 统…...

分布式数据库-架构真题(二十六)

构件组装成软件系统的过程分为三个不同的层次()。(2018年) 初始化、互连和集成连接、集成和演化定制、集成和扩展集成、扩展和演化 答案:C (2018年)CORBA服务端构件模型中,&#x…...

MyWebServer开发日记-socket

打算把 tinyWebServer 重写成跨平台(Windows and Linux)的。 这里首先需要跨平台的 sokcet,主要参考 尹圣雨 的 TCP/IP 网络编程 来着: 代码写的有些笨,欢迎批评: 首先是一个 socket 类,主要…...

图书管理信息系统分析与设计

一、系统开发的可行性分析 (一)系统背景.必要性及意义 随着社会经济的迅速发展和科学技术的全面进步,计算机事业的飞速发展,以计算机与通信技术为基础的信息系统正处于蓬勃发展的时期。随着经济文化水平的显著提高,人…...

Charles基础使用指南

##Charles 基本使用指南 Charles 在本地构建一个HTTP代理服务器,可以实现对HTTP、HTTPS请求的抓取,也就是我们常说的抓包,以及对请求响应的修改等。 Charles 官网地址 https://www.charlesproxy.com/ ###一、移动端的抓包实现 1. PC端开启…...

Android12之/proc/pid/status参数含义(一百六十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...

UMA 2 - Unity Multipurpose Avatar☀️三.给UMA设置默认服饰Recipes

文章目录 🟥 项目基础配置🟧 给UMA配置默认服饰Recipes🟨 设置服饰Recipes属性🟥 项目基础配置 将 UMA_DCS 预制体放到场景中创建空物体,添加DynamicCharacterAvatar 脚本,选择 HumanMaleDCS作为我们的基本模型配置默认Animator 🟧 给UMA配置默认服饰Recipes 服饰Re…...

uniapp-小程序登录授权框

微信官方文档 不弹出授权框原因 因为版本问题,目前的最新的版本是不支持 wx.getUserInfo 去主动弹出授权框 只能引导用户去点击 butten 去授权 解决方法 我的思路是参考了其他的微信微信小程序, 就是跳转到我的页面的时候 在钩子函数内去触发一个封装的模态框,状…...

Unity 性能优化Shader分析处理函数:ShaderUtil.GetShaderGlobalKeywords用法

Unity 性能优化Shader分析处理函数:ShaderUtil.GetShaderGlobalKeywords用法 点击封面跳转下载页面 简介 Unity 性能优化Shader分析处理函数:ShaderUtil.GetShaderGlobalKeywords用法 在Unity开发中,性能优化是一个非常重要的方面。一个常见…...

第一百四十一回 如何添加程序启动页

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了如何解决BLE包中的错误的内容,本章回中将介绍如何添加程序启动页.闲话休提,让我们一起Talk Flutter吧。 概念介绍 程序启动页就是点击手机桌面上的程序启动图标后显示的页面,也叫s…...

从零开始的PICO教程(4)--- UI界面绘制与响应事件

从零开始的PICO教程(4)— UI界面绘制与响应事件 文章目录 从零开始的PICO教程(4)--- UI界面绘制与响应事件一、前言1、大纲2、教程示例 二、具体步骤1、PICO VR环境配置2、XR的UI Canvas画布创建与调整(1)C…...

IntelliJ IDEA 远程调试 Tomcat

准备工作 明确远程服务器的 IP 地址,比如我是:192.168.92.128 关掉服务器防火墙:service iptables stop 本地 Remote Server 配置 添加 Remote Server,如下图 复制 Remote Server 自动生成的 JVM 参数,等下有用&…...

谷粒商城----认证服务

一、短信验证码(阿里云短信服务) Data ConfigurationProperties(prefix "spring.cloud.alicloud.sms") Component public class SmsComponent {private String host;private String path;private String skin;private String sign;private S…...

Mediasoup源码介绍

一、Mediasoup 整体结构 整个Mediasoup库通过Nodejs管理,比如整体逻辑、worker、router、producer、consumer...都是通过JS进行管理的。 其底层的数据传输是通过C部分进行控制的,通过NodeJs来控制C部分,以实现整体的数据传输效 二、Mediasou…...

GIS入门,WKT格式详解

WKT介绍 WKT是Well-known Text的缩写,它是一种用于描述地理空间几何对象的文本格式。 WKT是一种开放的国际标准,由Open Geospatial Consortium(OGC)定义和维护。 WKT是一种标准的表示方法,可以用来描述点、线、面等地理空间对象的形状和位置。通过使用一系列的坐标点和关…...

Qt之postEvent

基本介绍 postEvent方法所属类为QCoreApplication,完整声明如下: [static] void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority Qt::NormalEventPriority) 该方法的作用是将要发送的事件推送到对应线程的事件队列中&…...

1976~2020年青藏高原典型冰川及冰湖遥感监测数据集

冰川面积是反应气候变化最直接的指标之一。在全球变暖的大背景下,对于评估冰川融化造成的生态、全球气候变化和水资源价值评价等问题十分重要。本文针对受西风和印度洋夏季风影响下的青藏高原冰川及其末端冰湖的变化特征,制作了近44年来时相相对连续的冰…...

时序预测 | MATLAB实现LSSVM最小二乘支持向量机时间序列预测未来

时序预测 | MATLAB实现LSSVM最小二乘支持向量机时间序列预测未来 目录 时序预测 | MATLAB实现LSSVM最小二乘支持向量机时间序列预测未来预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现LSSVM时间序列预测未来(最小二乘支持向量机); 2.运行环境Mat…...

windows10 使用WSL2安装原生docker

1.升级WSL2 我的 win10 wsl默认版本是1,先要升级WSL2不然不支持systemd(后台守护进程) 双击直接安装就行,安装包网上都能找到: Microsoft.WSL_1.3.17.0_x64_ARM64.msixbundle 执行 wsl --version 显示这样成功了: C:\Users\xx>wsl --version WSL …...

jupylab pandas按条件批量处理xls数据

批量处理xls表数据 引入相关包 import pandas as pd import xlrd import numpy as np# 去掉jupyleb警告 import warnings warnings.filterwarnings("ignore")from IPython.core.interactiveshell import InteractiveShell InteractiveShell.ast_node_interactivity…...

RJ45水晶头网线顺序出错排查

线序 网线水晶头RJ45常用的线序标准ANSI / TIA-568定义了T568A与T568B两种线序,一般使用T568B,水晶头8个孔对应的8条线颜色如下图: 那1至8的编号,是从水晶头哪一面为参考呢,如下图,是水晶头金手指一面&am…...

【洛谷 P1115】最大子段和 题解(贪心算法)

最大子段和 题目描述 给出一个长度为 n n n 的序列 a a a,选出其中连续且非空的一段使得这段和最大。 输入格式 第一行是一个整数,表示序列的长度 n n n。 第二行有 n n n 个整数,第 i i i 个整数表示序列的第 i i i 个数字 a i …...

uni-app--》基于小程序开发的电商平台项目实战(一)

🏍️作者简介:大家好,我是亦世凡华、渴望知识储备自己的一名在校大学生 🛵个人主页:亦世凡华、 🛺系列专栏:uni-app 🚲座右铭:人生亦可燃烧,亦可腐败&#xf…...

入门人工智能 —— 学习一门编程语言 python 基础代码编写和运算符介绍(1)

入门人工智能 —— 学习一门编程语言 python(1) 入门流程1.安装pythonwindowslinux ubuntu 代码编写打印输出结果 基本加减法介绍基本运算符 随着人工智能技术的快速发展,越来越多的年轻人开始关注这个领域。作为入门者,学习人工智…...

【java安全】CommonsBeanUtils1

文章目录 【java安全】CommonsBeanUtils1前言Apache Commons BeanutilsBeanComparator如何调用BeanComparator#compare()方法?构造POC完整POC 调用链 【java安全】CommonsBeanUtils1 前言 在之前我们学习了java.util.PriorityQueue,它是java中的一个优…...

JVM优化(OOM,内存溢出),查看线程快照,堆内存情况等问题

1:堆大小 新生代 老年代,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ) 2:-Xmn参数总是应当小于-Xmx参数,否则就会触发OOM错误 3:jvm优化与查看gc回收情况&#x…...

git 给分支添加描述

需求:分支多了不知道当前分支的用处可以使用git br用来描述 效果: 全局安装命令 npm i -g git-br 项目内使用 git br 给f-230825-4-zhou分支备注 git config branch.f-230825-4-zhou.description 用来开发第四迭代需求 再次git br查看效果...

SpringBoot+Vue 整合websocket实现简单聊天窗口

效果图 1 输入临时名字充当账号使用 2 进入聊天窗口 3 发送消息 &#xff08;复制一个页面&#xff0c;输入其他名字&#xff0c;方便展示效果&#xff09; 4 其他窗口效果 代码实现 后端SpringBoot项目&#xff0c;自行创建 pom依赖 <dependency><groupId…...

PCB layout在布线上的设计规范有哪些?

PCB Layout是一项技术活&#xff0c;也是经验活&#xff0c;良好的PCB Layout布线可帮助工程师确保最终的电路板性能、可靠性和制造质量&#xff0c;因此是很多电子工程师的学习重点&#xff0c;下面我们来盘点下PCB Layout关于布线的规范有哪些。 1、地管的引脚接地越短越好&a…...

喜报丨迪捷软件入选浙江省2023年省级产业数字化服务商

近日&#xff0c;根据《关于组织开展2023年度省级产业数字化服务商申报工作的通知》要求&#xff0c;省经信厅公布2023年省级产业数字化服务商名单&#xff0c;浙江迪捷软件科技有限公司榜上有名。 省级产业数字化服务商上榜名单的评选在企业申报、地方推荐、专家评审、综合评估…...

做影视会员网站/电商网站入口

**前言**UG是目前市场上功能最全面的工业产品设计工具&#xff0c;它不但拥有现今CAD/CAM软件中功能最强大的Parasolid实体建模核心技术&#xff0c;更是提供了高效能的曲面构建能力&#xff0c;能够完成复杂的造型设计。UG提供工业标准的人机界面&#xff0c;不但易学易用&…...

网站开发公司属于什么行业/在线资源搜索引擎

版权声明&#xff1a;欢迎转载&#xff0c;请注明沉默王二原创。 https://blog.csdn.net/qing_gee/article/details/43447681 init 6 重启Linux。free -m查看内存大小&#xff0c;已M为单位。df -h查看硬盘情况&#xff0c;包括大小和分区。cat /proc/cpuinfo查看CPU信息。file…...

在线crm厂商/广州推广seo

这篇文章主要介绍了 python 中使用 xlrd、xlwt 操作 excel 表格详解, python 操作 excel 主要用到 xlrd 和 xlwt 这两个库&#xff0c;即 xlrd 是读 excel&#xff0c;xlwt 是写 excel 的库, 需要的朋友可以参考下 python 操作 excel 主要用到 xlrd 和 xlwt 这两个库&#xff0…...

网页设计实训内容/seo营销推广公司

转载于:https://www.cnblogs.com/jasonlixuetao/p/5557845.html...

赣州专业做网站/网站推广排名优化

问题设置&#xff1a;我有一个不平衡的数据集,其中98&#xff05;的数据属于A类,2&#xff05;属于B类.我训练了一个DecisionTreeClassifier(来自sklearn),class_weights设置为与以下设置平衡&#xff1a;dtc_settings {criterion: entropy,min_samples_split: 100,min_sample…...

window7 iis建立网站/学电脑培训班

ice internal compiler error...