SpringMvc(五)(springmvc五层结构)

  本篇文章为你整理了SpringMvc(五)(springmvc五层结构)的详细内容,包含有springmvc五大组件和工作过程 springmvc五层结构 SpringMvc(五),希望能帮助你了解 SpringMvc(五)。

  

public class AlipayConfig {

 

   // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号

   public static String app_id = "";

   // 商户应用私钥,您的PKCS8格式RSA2私钥

   public static String merchant_private_key = "";

   // 对应APPID下的支付宝公钥。

   public static String alipay_public_key = "";

   // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问

   public static String notify_url = "http://localhost:8080(/项目名,没有的不需要)/Alipay/notify_url.do";

   // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问

   public static String return_url = "http://localhost:8080(/项目名,没有的不需要)/Alipay/alipay_return.do";

   // 签名方式

   public static String sign_type = "RSA2";

   // 字符编码格式

   public static String charset = "UTF-8";

   // 支付宝网关

   public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

  

 

  1.2.2配置信息来源

  登录自己已经入驻的支付宝账号:https://open.alipay.com/develop/sandbox/app

  1.2.2.1 APPID

  1.2.2.2 公钥,私钥

  1.3 支付控制层

  

/**

 

   * 支付宝支付

  @Controller

  @RequestMapping("/Alipay")

  public class AlipayController {

   * 生成订单直接跳转支付宝付款

   @RequestMapping("/to_alipay.do")

   public void toAlipay(HttpServletResponse response, HttpServletRequest request) throws Exception{

   AlipayClient alipayClient = new DefaultAlipayClient(

   AlipayConfig.gatewayUrl, AlipayConfig.app_id,

   AlipayConfig.merchant_private_key, "json", AlipayConfig.charset,

   AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

   // 取购买人名称

   String in_name = request.getParameter("in_name");

   // 取手机号

   String in_phone = request.getParameter("in_phone");

   // 创建唯一订单号

   int random = (int) (Math.random() * 10000);

   String dateStr = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

   // 订单号拼接规则:手机号后四位+当前时间后四位+随机数四位数

   String out_trade_no = in_phone.substring(7) + dateStr.substring(10)

   + random;

   // 拼接订单名称

   String subject = in_name + "的订单";

   // 取付款金额

   String total_amount = request.getParameter("in_money");

   // 设置请求参数

   AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();

   alipayRequest.setReturnUrl(AlipayConfig.return_url);//支付成功响应后跳转地址

   alipayRequest.setNotifyUrl(AlipayConfig.notify_url);//异步请求地址

   /*FAST_INSTANT_TRADE_PAY 二维码瞬时支付

   * out_trade_no 订单号 total_amount 订单金额 subject 订单名称

   alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no

   + "\"," + "\"total_amount\":\"" + total_amount + "\","

   + "\"subject\":\"" + subject + "\"," + "\"body\":\""

   + ""+ "\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

   String result = "请求无响应";

   // 请求

   try {

   //通过阿里客户端,发送支付页面请求

   result = alipayClient.pageExecute(alipayRequest).getBody();

   response.setContentType("text/html;charset=UTF-8");

   response.setCharacterEncoding("UTF-8");

   response.getWriter().println(result);

   response.getWriter().flush();

   } catch (AlipayApiException e) {

   e.printStackTrace();

   } finally {

   response.getWriter().close();

  
@RequestMapping("/alipay_return.do")

   public String alipayReturn(HttpServletRequest request, Map String, Object map) throws Exception{

   // 响应信息

   String msg = "";

   // 请在这里编写您的程序(以下代码仅作参考)

   if (verifyAlipayReturn(request)) {//验签成功后执行的自定义业务代码

   // 商户订单号

   String out_trade_no = new String(request.getParameter(

   "out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

   // 支付宝交易号

   String trade_no = new String(request.getParameter("trade_no")

   .getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

   // 付款金额

   String total_amount = new String(request.getParameter(

   "total_amount").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

   msg = "支付宝交易号:" + trade_no + " br/ 商户订单号"

   + out_trade_no + " br/ 付款金额:" + total_amount;

   } else {

   msg = "验签/支付失败";

   map.put("msg", msg);

   return "forward:/success.jsp"; //支付完成后,跳转的页面

   * 支付宝异步通知

   * @param request

   * @param response

   * @throws Exception

   @RequestMapping("/notify_url.do")

   public void alipayNotify(HttpServletRequest request,HttpServletResponse response)

   throws Exception {

   // ——请在这里编写您的程序(以下代码仅作参考)——

   * 实际验证过程建议商户务必添加以下校验: 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,

   * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),

   * 3、校验通知中的seller_id(或者seller_email)

   * 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)

   * 4、验证app_id是否为该商户本身。

   if (verifyAlipayReturn(request)) {// 验证成功

   // 商户订单号

   String out_trade_no = new String(request.getParameter(

   "out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

   System.out.println(out_trade_no);

   // 支付宝交易号

   String trade_no = new String(request.getParameter("trade_no")

   .getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

   System.out.println(trade_no);

   // 交易状态

   String trade_status = new String(request.getParameter(

   "trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

   if (trade_status.equals("TRADE_FINISHED")) {

   // 判断该笔订单是否在商户网站中已经做过处理

   // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序

   // 如果有做过处理,不执行商户的业务程序

   // 注意:

   // 退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知

   } else if (trade_status.equals("TRADE_SUCCESS")) {

   // 判断该笔订单是否在商户网站中已经做过处理

   // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序

   // 如果有做过处理,不执行商户的业务程序

   // 注意:

   // 付款完成后,支付宝系统发送该交易状态通知

   } else {// 验证失败

   response.setContentType("text/html;charset=UTF-8");

   response.setCharacterEncoding("UTF-8");

   response.getWriter().println("验签/支付失败!");

   response.getWriter().flush();

   response.getWriter().close();

   // 调试用,写文本函数记录程序运行情况是否正常

   // String sWord = AlipaySignature.getSignCheckContentV1(params);

   // AlipayConfig.logResult(sWord);

   * @author zhukang

   * @date 2021-04-23

   * @return

   * @description 验证支付宝的反馈信息

   private boolean verifyAlipayReturn(HttpServletRequest request) throws UnsupportedEncodingException {

   // 获取支付宝回调反馈的信息

   Map String, String params = new HashMap ();

   Map String, String[] requestParams = request.getParameterMap();

   for (Iterator String iter = requestParams.keySet().iterator(); iter

   .hasNext();) {

   String name = iter.next();

   String[] values = requestParams.get(name);

   String valueStr = "";

   for (int i = 0; i values.length; i++) {

   valueStr = (i == values.length - 1) ? valueStr + values[i]

   : valueStr + values[i] + ",";

   // 乱码解决,这段代码在出现乱码时使用

   valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

   params.put(name, valueStr);

   boolean signVerified = false;

   try {// 调用SDK验证签名

   signVerified = AlipaySignature.rsaCheckV1(params,

   AlipayConfig.alipay_public_key, AlipayConfig.charset,

   AlipayConfig.sign_type);

   } catch (AlipayApiException e) {

   e.printStackTrace();

   return signVerified;

  

 

  1.4 测试访问

  直接访问 Alipay/to_alipay.do 这个请求即可(参数根据实际操作进行添加);

  2、关键字过滤

  2.1 关键字文件 sensitivewords.txt

  

小笨蛋

 

  ...(根据实际需求添加关键字)

  

 

  2.2 关键字工具类

  2.2.1 关键字初始化

  

 

 

   * Created On : 2022/7/26.

   * p

   * Author : zhukang

   * p

   * Description: 敏感词初始化类

  public class SensitiveWordInit {

   // 敏感词集合

   public static Map sensitiveWordMap;

   // 初始化敏感词

   public Map initSensitiveWord(){

   System.out.println("------- 系统启动,从文件中读取敏感字,存入sensitiveWordMap -------");

   try {

   // 读取敏感词文件,将敏感词加入HashMap

   addSensitiveWordToHashMap(readSensitiveWordFile());

   } catch (Exception e){

   e.printStackTrace();

   return sensitiveWordMap;

   * @author : zhukang

   * @date : 2022/7/26

   * @param : [java.util.Set java.lang.String ]

   * @return : java.util.Map

   * @description : 将HashSet中的敏感词,存入HashMap中

   private void addSensitiveWordToHashMap(Set String wordSet) {

   // 初始化敏感词容器,减少扩容操作

   sensitiveWordMap = new HashMap(wordSet.size());

   for (String word : wordSet) {

   Map nowMap = sensitiveWordMap;

   for (int i = 0; i word.length(); i++) {

   // 转换成char型

   char keyChar = word.charAt(i);

   // 获取

   Object tempMap = nowMap.get(keyChar);

   // 如果存在该key,直接赋值

   if (tempMap != null) {

   // 一个一个放进Map中

   nowMap = (Map) tempMap;

   // 不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个

   else {

   // 设置标志位,不是最后一个

   Map String, String newMap = new HashMap String, String

   // 没有这个key,就把(isEnd,0) 放在Map中

   newMap.put("isEnd", "0");

   // 添加到集合

   nowMap.put(keyChar, newMap);

   //指向当前map,继续遍历

   nowMap = newMap;

   // 最后一个

   if (i == word.length() - 1) {

   nowMap.put("isEnd", "1");

   * @author : zhukang

   * @date : 2022/7/26

   * @param : []

   * @return : java.util.Set java.lang.String

   * @description : 读取敏感词库文件,存入HashMap中

   private Set String readSensitiveWordFile() {

   // 敏感词集合

   Set String wordSet = null;

   //敏感词库

   // 获取输入流,读取resources目录下的static目录中的敏感词文件(一个敏感词一行)

   InputStream inputStream = new ClassPathResource("sensitivewords.txt").getInputStream();

   // 读取文件输入流

   InputStreamReader read = new InputStreamReader(inputStream, "UTF-8");

   // 高效读取

   BufferedReader br = new BufferedReader(read);

   // 创建set集合,存储读取的敏感字

   wordSet = new HashSet ();

  
public void init() {

   // 从数据库查询敏感词,转换为set集合 将敏感词库加入到HashMap中,确定有穷自动机DFA

   sensitiveWordMap = new com.kgc.weddingshop.utils.SensitiveWordInit().initSensitiveWord();

   System.out.println("------ " + sensitiveWordMap + "------");

   * @param : [java.lang.String]

   * @return : boolean true 包含;false 不包含

   * @author : zhukang

   * @date : 2022/7/26

   * @description : 是否包含敏感词(默认按最小匹配规则来,只要有敏感词就ok),最小匹配规则

   public boolean isContainSensitiveWordMin(String txt) {

   return isContainSensitiveWord(txt, MIN_MATCH_TYPE);

   * @param : [java.lang.String, int]

   * @return : boolean

   * @author : zhukang

   * @date : 2022/7/26

   * @description : 是否包含敏感词(默认按指定匹配规则来,只要有敏感词就ok)

   * 如果敏感词库为:

   * * 傻叉

   * * 傻叉人

   * * 大傻叉

   * * 初始化之后为:{傻={叉={人={isEnd=1}, isEnd=1}, isEnd=0}, 大={傻={叉={isEnd=1}, isEnd=0}, isEnd=0}}

   * * 1、按最小规则匹配, 匹配 傻叉 的时候,匹配到叉,就为最后一个了 直接break。如果输入的敏感词是傻叉人,命中的只是傻叉,而不是傻叉人

   * * 2、按最大规则匹配, 匹配 傻叉 的时候,匹配到叉,已经为最后一个,但是按照最大规则,会继续匹配人,命中的是傻叉人

   * * 3、如果关键词是傻叉猫,两种匹配规则都会匹配到傻叉,会命中,如果输入的是傻叉人猫,按最小规则匹配是傻叉,按最大规则匹配傻叉人,只是匹配敏感词不同

   public boolean isContainSensitiveWord(String txt, int matchType) {

   if (txt == null "".equals(txt)) {

   return false;

   for (int i = 0; i txt.length(); i++) {

   int matchFlag = this.checkSensitiveWords(txt, i, matchType);

   if (matchFlag 0) {

   return true;

   return false;

   * @param : 待判断文本 起始位置 匹配类型: 1 最小匹配原则;2 最大匹配原则

   * @return : int 大于0表示包含敏感词且表示敏感词匹配长度,否则不包含

   * @author : zhukang

   * @date : 2022/7/26

   * @description : 校验是否包含敏感词

   private static int checkSensitiveWords(String txt, int beginIndex, int matchType) {

   // 敏感词结束标识位:用于敏感词只有1位的情况

   boolean flag = false;

   // 匹配标识数默认为0

   int matchFlag = 0;

   // 从内存中,获取敏感词库

   Map nowMap = sensitiveWordMap;

   for (int i = beginIndex; i txt.length(); i++) {

   // 获取第一个字符

   char word = txt.charAt(i);

   // 获取指定key,判断当前字符是不是一个敏感词的开头

   nowMap = (Map) nowMap.get(word);

   // 不存在,直接返回

   if (nowMap == null) {

   break;

   // 根据排列组合的匹配,如果出现在敏感词库中,即找到相应key,匹配标识+1

   matchFlag++;

   // 如果已经匹配到词库中完整的敏感词, 改匹配结束标识,并根据匹配规则判断,是否继续

   if ("1".equals(nowMap.get("isEnd"))) {

   // 结束标志位为true,已经命中到了一个完整敏感词

   flag = true;

   // 最小规则,直接返回, 最大规则还需继续查找

   if (matchType == MIN_MATCH_TYPE) {

   break;

   // 长度必须大于等于1,为词,敏感词只有1个字的情况

   if (matchFlag 2 !flag) {

   matchFlag = 0;

   return matchFlag;

  
public Set String getSensitiveWords(String txt, Integer matchType) {

   Set String sensitiveWords = new HashSet ();

   for (int i = 0; i txt.length(); i++) {

   Integer length = checkSensitiveWords(txt, i, matchType);

   if (length 0) {

   sensitiveWords.add(txt.substring(i, i + length));

   // 循环i会+1,所以需-1

   i = i + length - 1;

   return sensitiveWords;

   * @param : txt,文本 matchType 匹配类型: 1 最小匹配原则;2 最大匹配原则

   * @return : 替换字符

   * @author : zhukang

   * @date : 2022/7/26

   * @description : 替换敏感词

   public String replaceSensitiveWords(String txt, Integer matchType, String replaceStr) {

   if (txt == null "".equals(txt)) {

   return txt;

   // 获取所有敏感词

   Set String sensitiveWords = getSensitiveWords(txt, matchType);

   Iterator String iterator = sensitiveWords.iterator();

   String replaceString = "";

   while (iterator.hasNext()) {

   String sWord = iterator.next();

   replaceString = getReplaceString(replaceStr, sWord.length());

   txt = txt.replaceAll(sWord, replaceString);

   return txt;

   * @param : replaceStr 替换字符

   * @return : 敏感字长度

   * @author : zhukang

   * @date : 2022/7/26

   * @description : 替换为指定字符,没有指定替换字符,默认*

   private static String getReplaceString(String replaceStr, Integer length) {

   // 指定替换字符为*

   if (replaceStr == null) {

   replaceStr = "*";

   // 可变字符串对象

   StringBuffer replaceString = new StringBuffer();

   // 循环遍历,替换内容

   for (int i = 0; i length; i++) {

   replaceString.append(replaceStr);

   return replaceString.toString();

  

 

  2.3 关键字过滤 控制层

  

/**

 

   * Created On : 2022/7/26.

   * p

   * Author : zhukang

   * p

   * Description: 敏感词测试入口

  @Controller

  public class SensitiveWordController {

   @Autowired

   private SensitiveWordFilterUtil sensitiveWordFilterUtil;

   * @author : zhukang

   * @date : 2022/5/17

   * @param : [java.lang.String]

   * @return : com.kgc.sbt.util.RequestResult java.lang.String

   * @description : 测试搜索中的敏感词,并指定规则

   @RequestMapping(value = "/testSensitiveWord", produces = {"application/json;charset=utf-8"})

   @ResponseBody

   public String testSensitiveWord(@RequestParam String searchKey, @RequestParam int matchType){

   // 校验搜索关键字中,是否包含敏感词,如果包含,提示错误

   if(sensitiveWordFilterUtil.isContainSensitiveWord(searchKey, matchType)){

   System.out.println(String.format("------ 命中敏感词,搜索关键字:%s ------", searchKey));

   System.out.println(String.format("------ 命中敏感字为:%s ------", sensitiveWordFilterUtil.getSensitiveWords(searchKey, matchType)));

   return "搜索失败,命中敏感词!";

   return "搜索成功!";

  

 

  3、SSM项目 知识点

  3.1 SpringMvc 重定向后,中文乱码

  3.1.1 RedirectAttributes attributes

  将参数,放入RedirectAttributes 中,在重定向的时候,会自动拼接参数,并且不会乱码;

  

@RequestMapping("/test")

 

  public String delAllViewHistory(//attributes 请求,自动拼接参数

   RedirectAttributes attributes){

   attributes.addAttribute("test","测试");

   return "redirect:/viewHistory/viewViewHistoryList";

  

 

  3.2 location.href 会暴露参数问题

  解决方法:创建一个form表单,进行post方法提交;

  

//创建一个 form 表单,并提交

 

  var form = $(" form

  form.attr("style","display:none");

  form.attr("target","");

  form.attr("method","post");

  //请求地址

  form.attr("action","${pageContext.request.contextPath}/user/modUserInfo");

  //请求参数

  var input1 = $(" input

  var input2 = $(" input

  input1.attr("type","hidden");

  input1.attr("name","uid");

  input1.attr("value","${sessionScope.loginUser.uid}");

  input2.attr("type","hidden");

  input2.attr("name","password");

  input2.attr("value",$password.val());

  //在body标签中追加form 表单

  $("body").append(form);

  form.append(input1);

  form.append(input2);

  //表单体提交

  form.submit();

  //移除表达

  form.remove();

  

 

  3.3 mysql 查询日期操作 ,今天,本周,本月,本季度,今年

  

-- 今天

 

  select to_days(now()) -- 738788 天

  -- 本周

  select yearweek(now(),1) -- 202239 周, 第二个参数,是因为,中国人喜欢将周一当作一周的第一天

  -- 本月

  select date_format(now(),%Y%m) -- 202209 月

  -- 本季度

  select quarter(now()) -- 3 季度 quarter

  -- 今年

  select year(now()) -- 2022 年 year

  -- 日期格式化

  select DATE_FORMAT(now(),%Y-%m-%d)

  

 

  3.4 头像点击上传

  3.4.1 jsp

  3.4.1.1 头像修改表单

  

 %-- 头像修改 form start --% 

 

   form action="${pageContext.request.contextPath}/user/headImg" method="post" enctype="multipart/form-data" id="userHeadImgForm"

   input type="file" name="userHeaderImg" id="userHeaderPic" /

   /form

   %-- 头像修改 form end --%

  

 

  3.4.1.2 头像展示

  

 %-- 头像 展示 start --% 

 

   img id="userHeaderImg"

   src="${pageContext.request.contextPath}/${sessionScope.loginUser.uhead}"/

   /h3

   %-- 头像 展示 end --%

  

 

  3.4.1.3 点击头像触发 图片选择input 头像选择

  

//============ 头像更换 start ================

 

  $(function (){

   // 点击头像图片,触发文件预点击

   $("#userHeaderImg").click(function (){

   $("#userHeaderPic").click();

   // 当文件域内容改变,实现头像预览

   $("#userHeaderPic").change(function () {

   // 获取上传文件对象

   var file = $(this)[0].files[0];

   // 判断类型

   var imageType = /^image\//;

   if (file === undefined !imageType.test(file.type)) {

   alert("请选择图片!");

   return;

   // 判断大小

   if (file.size 512000) {

   alert("图片大小不能超过500K!");

   return;

   // 读取文件URL,预览文件

   var reader = new FileReader();

   // 读取文件

   reader.readAsDataURL(file);

   // 阅读文件完成后触发的事件

   reader.onload = function () {

   // 读取的URL结果:this.result

   $("#userHeaderImg").attr("src", this.result);

   // alert("图片上传");

   $("#userHeadImgForm").submit();

   // TODO 还可以不预览,直接异步ajax发送请求到后台,上传文件,然后返回页面显示头像,并将图片的路径防止页面隐藏域,提交表单记录头像的地址

  //============ 头像更换 end ================

  

 

  3.4.2 控制层

  1.获取头像文件流,并保存图片;

  2.将图片地址保存到用户的头像中;

  3.刷新session中的用户信息;

  

@RequestMapping("/headImg")

 

  public String headImg(HttpSession session,

   @RequestParam("userHeaderImg") MultipartFile multipartFile,

   Map String, String map) throws IOException {

   // 获取上传的头像文件名称

   String targetFileName = multipartFile.getOriginalFilename();

   System.out.println("------ 上传文件名:" + targetFileName + " ------");

   // 重新定义新的文件名,要保留上传文件的类型

   targetFileName = UUID.randomUUID().toString().substring(0, 8) + targetFileName.substring(targetFileName.indexOf("."));

   System.out.println("------ 新的文件名:" + targetFileName + " ------");

   // 上传文件,要保存服务器上的真实路径中,idea项目发布,默认不会放到目标tomcat中,放在本地项目的target目录中

   String realFilePath = session.getServletContext().getRealPath("img/about");

   System.out.println("------ 服务器真实路径:" + realFilePath + " ------");

   // 目标文件目录可能不存在,不能人为干预,必须程序主动处理

   File targetFilePath = new File(realFilePath);

   if(!targetFilePath.exists()){

   // 目标不存在,主动创建

   if(targetFilePath.mkdirs()){

   System.out.println("------ 上传目录创建成功 ------");

   // 创建目标文件对象

   File targetFile = new File(targetFilePath + "/" + targetFileName);

   // 文件上传到服务器,只需要一步,组件自动支持功能

   multipartFile.transferTo(targetFile);

   // 数据库存入头像信息

   targetFileName = "img/about/"+targetFileName;

   //获取当前登录用户对象

   User loginUser = (User)session.getAttribute(CommConstant.SYS_SESSION_LOGINUSER);

   //换头像

   loginUser.setUhead(targetFileName);

   //重置 session 中的 用户对象

   session.setAttribute(CommConstant.SYS_SESSION_LOGINUSER,loginUser);

   // 调用 修改用户信息 方法,修改用户信息

   User userForm = new User();

   userForm.setUid(loginUser.getUid());

   userForm.setUhead(loginUser.getUhead());

   userService.modUserInfo(userForm);

   //放入修改成功提示信息,可以不提示(操作过后感觉,不返回效果好些,看时机需求)

   map.put("modUserInfoMsg","用户头像修改成功!");

   return "/personCenter";

  

 

  以上就是SpringMvc(五)(springmvc五层结构)的详细内容,想要了解更多 SpringMvc(五)的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: