從 0 到 1 認識 Spring MVC:核心思想與基本用法(下)

文章目錄

    • 📕4. 響應
        • ??4.1 返回靜態頁面
        • ??4.2 返回數據@ResponseBody?
        • ??4.3 返回HTML代碼片段?
        • ??4.4 返回JSON
        • ??4.5 設置狀態碼
        • ??4.6 設置Header(了解)
    • 📕5. 案例練習
        • ??5.1 加法計算器
        • ??5.2 用戶登錄
        • ??5.3 留言板
    • 📕6. lombok介紹
    • 📕7. 應用分層
        • ??7.1 使用三層架構進行分層
        • ??7.2 應用分層的好處

上接:從 0 到 1 認識 Spring MVC:核心思想與基本用法(上)

📕4. 響應

在我們前面的代碼例子中,都已經設置了響應數據,Http響應結果可以是數據,也可以是靜態頁面,也可以針對響應設置狀態碼,Header信息等。

??4.1 返回靜態頁面

創建前端頁面 index.html(注意路徑)?
在這里插入圖片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Index頁面</title>
</head>
<body>Hello,Spring MVC,我是Index頁面.
</body>
</html>
@RestController
public class indexController(){@RequestMapping("/index")public String index(){return "/index.html";}
}

在這里插入圖片描述
結果卻發現, 頁面未正確返回, http響應把"/index.html" 當做了http響應正文的數據? 那Spring MVC如何才能識別出來 index.html 是一個靜態頁面, 并進行返回呢??

我們需要把 @RestController 改為 @Controller

@RestController 和 @Controller 有著什么樣的關聯和區別呢??

之前我們介紹了MVC模式,后端會返回視圖,這是早期時的概念?。隨著互聯網的發展,目前項目開發流行"前后端分離"模式, Java主要是用來做后端項目的開發,所以也就 不再處理前端相關的內容了。MVC的概念也逐漸發生了變化,View不再返回視圖,而是返回顯示視圖時需要的數據。如果想返回視圖的話, 只需要把@ResponseBody 去掉就可以了, 也就是@Controller ?

所以前面使用的@RestController 其實是返回的數據.? @RestController = @Controller + @ResponseBody
@Controller : 定義一個控制器, Spring 框架啟動時加載, 把這個對象交給Spring管理.?
@ResponseBody : 定義返回的數據格式為非視圖, 返回一個 text/html 信息?

??4.2 返回數據@ResponseBody?
@Controller
@ResponseBody
public class indexController(){@RequestMapping("/index")public String index(){return "/index.html";}
}

加上@ResponseBody 注解, 該方法就會把 “/index.html” 當做一個數據返回給前端.?

在這里插入圖片描述

@ResponseBody 既是類注解,又是方法注解?。
如果作用在類上,表示該類的所有方法,返回的都是數據,如果作用在方法上,表示該方法返回的是數據。也就是說: 在類上添加@ResponseBody 就相當于在所有的方法上添加了@ResponseBody 注解。同樣,如果類上有@RestController 注解時 : 表示所有的方法上添加了@ResponseBody 注解,也就是當前類下所有的方法返回值做為響應數據?。

??4.3 返回HTML代碼片段?

后端返回數據時, 如果數據中有HTML代碼, 也會被瀏覽器解析?

@RestMapping("/return/html")
@ReponseBody
public class returnHtml(){public String return(){return "<h1>Hello,HTML~<h1>";}
}

在這里插入圖片描述
通過Fiddler觀察響應結果, Content-Type 為text/html

響應中的 Content-Type 常見取值有以下幾種:?

  1. text/html : body 數據格式是 HTML?
  2. text/css : body 數據格式是 CSS?
  3. application/javascript : body 數據格式是 JavaScript?
  4. application/json : body 數據格式是 JSON?
??4.4 返回JSON

Spring MVC 也可以返回JSON?,后端方法返回結果為對象。

@RequestMapping("/m11")public Map<String,String> m11(){Map<String,String> hash = new HashMap<>();hash.put("name","zhuxulong");hash.put("name1","lijiufang");return hash;}

在這里插入圖片描述
通過Fiddler觀察響應結果, Content-Type 為 application/json

??4.5 設置狀態碼

Spring MVC會根據我們方法的返回結果自動設置響應狀態碼, 程序員也可以手動指定狀態碼?。通過Spring MVC的內置對象HttpServletResponse 提供的方法來進行設置?。

@RequestMapping("/m12")public String m12(HttpServletResponse response){response.setStatus(401);return "yes";}

狀態碼不影響頁面的展示
我們通過Proxyman來抓包發現狀態碼是401
這里是引用

??4.6 設置Header(了解)

Http響應報頭也會向客戶端傳遞一些附加信息,比如服務程序的名稱,請求的資源已移動到新地址等,如: Content-Type,Local等。這些信息通過@RequestMapping 注解的屬性來實現。

設置Content-Type?

 @RequestMapping(value = "/m13",produces = "application/json")public String m13(){return "{\"success\":true}";}

如果不設置produces , 方法返回結果為String時, Spring MVC默認返回類型, 是text/html.?

設置其他Header

設置其他Header的話, 需要使用Spring MVC的內置對象HttpServletResponse 提供的方法來進行設置?

@RequestMapping(value = "/m14")public String m14(HttpServletResponse response){response.setHeader("myHeader","hahaha");return "yes";}

void setHeader(String name, String value) 設置一個帶有給定的名稱和值的 header. 如果 name 已經存在, 則覆蓋舊的值.?

在這里插入圖片描述
通過Proxyman來查看我們設置的結果

📕5. 案例練習

??5.1 加法計算器

需求

輸入兩個整數, 點擊"點擊相加"按鈕, 顯示計算結果
?
定義接口

請求路徑 : calc/sum
請求方式 : GET/POST
接口描述 : 計算兩個整數相加

請求參數

參數名?類型?是否必須?備注?
num1?Integer?是?參與計算的第一個數?
num2?Integer?是?參與計算的第二個數?

響應數據

Content-Type : text/html
響應內容 : 計算機計算結果:

前端代碼

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>
<form action="calc/sum" method="post"><h1>計算器</h1>數字1:<input name="num1" type="text"><br>數字2:<input name="num2" type="text"><br><input type="submit" value=" 點擊相加 ">
</form>
</body></html>

后端代碼

package xulong.com;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/calc")
public class CalcController {@RequestMapping("/sum")public String add(Integer num1,Integer num2){if(num1==null||num2==null){return "輸入不合法";}return "計算機計算結果:"+(num1+num2);}
}
??5.2 用戶登錄

1.校驗接口
需求

用戶輸入賬號和密碼, 后端進行校驗密碼是否正確?

  1. 如果不正確, 前端進行用戶告知?
  2. 如果正確, 跳轉到首頁. 首頁顯示當前登錄用戶?
  3. 后續再訪問首頁, 可以獲取到登錄用戶信息?

定義接口

請求路徑 : /user/login
請求方式 : POST
接口描述 : 校驗賬號密碼是否正確

請求參數

參數名?類型?是否必須?備注?
userName?String是?校驗的賬號?
passwordString?是?校驗的密碼?

響應數據

Content-Type : text/html
響應內容 : true //賬號密碼驗證成功 false//賬號密碼驗證失敗

2.查詢接口

定義接口

請求路徑 : /user/getLoginUser
請求方式 : GET
接口描述 : 查詢當前登錄的用戶

響應數據

Content-Type : text/html
響應內容 : zhangsan

===================================================================================

后端代碼

package xulong.com.Login;import jakarta.servlet.http.HttpSession;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class LoginController {@RequestMapping("/login")public boolean login(String userName, String password, HttpSession session ){if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){return false;}if("zhangsan".equals(userName)&&"123456".equals(password)){session.setAttribute("username",userName);return true;}return false;}@RequestMapping("/getLoginUser")public String getLoginUser(HttpSession session){String username = (String)session.getAttribute("username");if(StringUtils.hasLength(username)) {return username;}return "";}}

前端代碼

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>登錄頁面</title>
</head><body><h1>用戶登錄</h1>用戶名:<input name="userName" type="text" id="userName"><br>密碼:<input name="password" type="password" id="password"><br><input type="button" value="登錄" onclick="login()"><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script><script>function login() {$.ajax({type: "post",url: "/user/login",data: {"userName": $("#userName").val(),"password": $("#password").val()},success: function (result) {if (result) {location.href = "/index.html"} else {alert("賬號或密碼有誤.");}}});}</script>
</body></html>
??5.3 留言板

需求

  1. 輸入留言信息, 點擊提交. 后端把數據存儲起來.
  2. 頁面展示輸入的表白墻的信息

接口定義

  1. 獲取全部留言
    請求:?GET /message/getList
    響應: JSON 格式?
    瀏覽器給服務器發送一個 GET /message/getList 這樣的請求, 就能返回當前一共有哪些留言 記錄. 結果以 json 的格式返回過來.
  1. 發表新留言
    請求: body 也為 JSON 格式.?
    響應: JSON 格式.?
    我們期望瀏覽器給服務器發送一個 POST /message/publish 這樣的請求, 就能把當前的留言提 交給服務器.?

前端代碼

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>留言板</title><style>.container {width: 350px;height: 300px;margin: 0 auto;/* border: 1px black solid; */text-align: center;}.grey {color: grey;}.container .row {width: 350px;height: 40px;display: flex;justify-content: space-between;align-items: center;}.container .row input {width: 260px;height: 30px;}#submit {width: 350px;height: 40px;background-color: orange;color: white;border: none;margin: 10px;border-radius: 5px;font-size: 20px;}</style>
</head><body><div class="container"><h1>留言板</h1><p class="grey">輸入后點擊提交, 會將信息顯示下方空白處</p><div class="row"><span>誰:</span> <input type="text" name="" id="from"></div><div class="row"><span>對誰:</span> <input type="text" name="" id="to"></div><div class="row"><span>說什么:</span> <input type="text" name="" id="say"></div><input type="button" value="提交" id="submit" onclick="submit()"><!-- <div>A 對 B 說: hello</div> --></div><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script><script>load();function load() {$.ajax({type: "get",url: "/message/getList",success: function (result) {for (var message of result) {var divE = "<div>" + message.from + "對" + message.to + "說:" +message.message + "</div>";$(".container").append(divE);}}});}function submit() {//1. 獲取留?的內容var from = $('#from').val();var to = $('#to').val();var say = $('#say').val();if (from == '' || to == '' || say == '') {return;}$.ajax({type: "post",url: "/message/publish",data: {from: from,to: to,message: say},success: function (result) {if (result) {//2. 構造節點var divE = "<div>" + from + "對" + to + "說:" + say + "</div>";//3. 把節點添加到??上$(".container").append(divE);//4. 清空輸?框的值$('#from').val("");$('#to').val("");$('#say').val("");} else {alert("發表留?失敗!");}}});}</script>
</body></html>

后端代碼

package xulong.com.Message;import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
import java.util.List;@RestController
@RequestMapping("/message")
public class MessageController {List<MessageInfo> list = new ArrayList<>();@RequestMapping("/getList")public List<MessageInfo> getList(){return list;}@RequestMapping("/publish")public boolean punish(@RequestBody MessageInfo messageInfos){if(StringUtils.hasLength(messageInfos.getFrom())&&StringUtils.hasLength(messageInfos.getTo())&&StringUtils.hasLength(messageInfos.getMessage())){list.add(messageInfos);return true;}return false;}
}

📕6. lombok介紹

Lombok是一個Java工具庫,通過添加注解的方式,簡化Java的開發.?

引入依賴

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>

使用

lombok通過一些注解的方式, 可以幫助我們消除一些冗長代碼, 使代碼看起來簡潔一些?
比如之前的Person對象 就可以改為?

@Data
public class Person {private int id;private String name;private String password;
}

@Data 注解會幫助我們自動一些方法, 包含getter/setter, equals, toString等

更多使用

如果覺得@Data比較粗暴(生成方法太多), lombok也提供了一些更精細粒度的注解??

注解?作用?
@Getter ?自動添加 getter 方法?
@Setter ?自動添加 setter 方法?
@ToString ?自動添加 toString 方法?
@EqualsAndHashCode ?自動添加 equals 和 hashCode 方法?
@NoArgsConstructor ?自動添加無參構造方法?
@AllArgsConstructor ?自動添加全屬性構造方法,順序按照屬性的定義順序?
@NonNull ?屬性不能為 null?
@RequiredArgsConstructor?自動添加必需屬性的構造方法,final + @NonNull 的屬性為 必需 ?

@Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @NoArgsConstructor ?

📕7. 應用分層

通過上面的練習,我們學習了Spring MVC簡單功能的開發,但是我們也發現了一些問題?,目前我們程序的代碼有點"雜亂",然而當前只是"一點點功能"的開發。如果我們把整個項目功能完成呢? 代碼會更加的"雜亂無章"(文件亂, 代碼內容亂)?。也基于此, 咱們接下來學習應用分層.?

為什么需要應用分層??

在最開始的時候,為了讓項目快速上線,我們通常是不考慮分層的。但是隨著業務越來越復雜,大量的代碼混在一起,會出現邏輯不清晰、各模塊相互依賴、代碼擴展性差、改動一處就牽一發而動全身等問題。所以學習對項目進行分層就是我們程序員的必修課了。

類似公司的組織架構
公司初創階段, 一個人身兼數職, 既做財務, 又做人事, 還有行政.?
隨著公司的逐漸壯大, 會把崗位進行細分, 劃分為財務部門, 人事部門, 行政部門等. 各個部門內部還會 再進行細分.?
項目開發也是類似, 最開始功能簡單時, 我們前后端放在一起開發, 隨著項目功能的復雜, 我們分為前 端和后端不同的團隊, 甚至更細粒度的團隊. 后端開發也會根據功能再進行細分. MVC就是其中的一種 拆分方式.?
但是隨著后端人員不再涉及前端, 后端開發又有了新的分層方式.?

??7.1 使用三層架構進行分層

之前介紹的 “MVC”,就是把整體的系統分成了 Model(模型),View(視圖)和Controller (控制器)三個層次,也就是將用戶視圖和業務處理隔離開,并且通過控制器連接起來,很好地實現了表現和邏輯的解耦,是一種標準的軟件分層架構。

在這里插入圖片描述

目前現在更主流的開發方式是 “前后端分離” 的方式,后端開發工程師不再需要關注前端的實現, 所以對 于Java后端開發者,又有了一種新的分層架構:把整體架構分為表現層、業務邏輯層和數據層。這種分層方式也稱之為"三層架構"。

  1. 表現層: 就是展示數據結果和接受用戶指令的,是最靠近用戶的一層。?
  2. 業務邏輯層:負責處理業務邏輯,里面有復雜業務的具體實現。
  3. 數據層:負責存儲和管理與應用程序相關的數據?

按照上面的層次劃分, Spring MVC 站在后端開發人員的角度上, 也進行了支持, 把上面的代碼劃分為三 個部分: ?
在這里插入圖片描述

在這里插入圖片描述

??7.2 應用分層的好處
  1. 降低層與層之間的依賴, 結構更加的明確, 利于各層邏輯的復用?
  2. 開發人員可以只關注整個結構中的其中某一層, 極大地降低了維護成本和維護時間?
  3. 可以很容易的用新的實現來替換原有層次的實現
  4. 有利于標準化

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/91874.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/91874.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/91874.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python-初學openCV——圖像預處理(五)——梯度處理、邊緣檢測、圖像輪廓

目錄 一、圖像梯度處理 1、垂直邊緣提取 2、Sobel算子 3、Laplacian算子 二、圖像邊緣檢測 1、高斯濾波 2、計算圖像的梯度、方向 3、非極大值抑制 4、雙閾值篩選 三、繪制圖像輪廓 1、概念 2、尋找輪廓 3、繪制輪廓 一、圖像梯度處理 還記得高數中的一階導數求極值…

【Redis】安裝Redis,通用命令,常用數據結構,單線程模型

目錄 一.在Ubuntu系統安裝Redis 二. redis客戶端介紹 三. 全局命令 3.1.GET和SET命令 3.2.KEYS&#xff08;生產環境禁止使用&#xff09; 3.3.EXISTS 3.4.DEL 3.5.EXPIRE 3.6.TTL 3.6.1.Redis的過期策略 3.6.2.基于優先級隊列/堆的實現去實現定時器 3.6.3.定時器&a…

ubuntu22.04系統實踐 linux基礎入門命令(三) 用戶管理命令

以下有免費的4090云主機提供ubuntu22.04系統的其他入門實踐操作 地址&#xff1a;星宇科技 | GPU服務器 高性能云主機 云服務器-登錄 相關兌換碼星宇社區---4090算力卡免費體驗、共享開發社區-CSDN博客 之所以推薦給大家使用&#xff0c;是因為上面的云主機目前是免費使用的…

DPDK中的TCP頭部處理

1. TCP頭部結構 TCP頭部通常為20字節&#xff08;不含可選字段&#xff09;&#xff0c;每個字段占據固定的字節位置。以下是TCP頭部的結構&#xff0c;按字節位置逐一說明&#xff1a;0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 …

開源在線客服系統Chatwoot配置文件

參考&#xff1a; https://developers.chatwoot.com/self-hosted/deployment/dockerhttps://developers.chatwoot.com/self-hosted/deployment/docker 1、.env 配置文件 # Learn about the various environment variables at # https://www.chatwoot.com/docs/self-hosted/co…

PHP進階語法詳解:命名空間、類型轉換與文件操作

掌握了PHP面向對象編程的基礎后&#xff0c;就可以深入學習命名空間、類型轉換、文檔注釋、序列化以及文件操作等重要概念。 1、命名空間&#xff08;Namespace&#xff09; 命名空間是PHP 5.3引入的重要特性&#xff0c;它解決了類名、函數名和常量名沖突的問題&#xff0c;使…

Webpack 搭建 Vue3 腳手架詳細步驟

創建一個新的 Vue 項目 1&#xff09;初始化項目目錄 新建一個文件夾&#xff0c;或者使用以下指令 mkdir webpack-vue_demo cd webpack-vue_demo2&#xff09;初始化 npm 項目 npm init -y3&#xff09;安裝 vue 和 webpack 相關依賴 npm install vue vue-loader vue-template…

【Git 誤操作恢復指南】

Git 誤操作恢復指南 適用場景&#xff1a;git reset --hard 誤操作后的緊急恢復 風險等級&#xff1a;&#x1f534; 高風險 - 可能導致代碼丟失 恢復成功率&#xff1a;95%&#xff08;CI/CD 環境下&#xff09; &#x1f6a8; 緊急情況概述 問題描述 在項目開發過程中&am…

Go語言 逃 逸 分 析

逃逸分析是什么 逃逸分析是編譯器用于決定變量分配到堆上還是棧上的一種行為。一個變量是在堆上分配&#xff0c;還是在棧上分配&#xff0c;是經過編譯器的逃逸分析之后得出的“結論”。Go 語言里編譯器的逃逸分析&#xff1a;它是編譯器執行靜態代碼分析后&#xff0c…

LeetCode算法日記 - Day 1: 移動零、復寫零

目錄 1. 移動零 1.1 思路解析 1.2 代碼實現 2. 復寫零 2.1 思路解析 2.2 代碼實現 1. 移動零 283. 移動零 - 力扣&#xff08;LeetCode&#xff09; 給定一個數組 nums&#xff0c;編寫一個函數將所有 0 移動到數組的末尾&#xff0c;同時保持非零元素的相對順序。 請…

Odoo:免費開源的醫療器械行業解決方案

開源智造Odoo專家團隊深知&#xff0c;作為醫療器械制造商&#xff0c;您的成功取決于制造卓越產品的能力。您必須遵循嚴密控制的流程&#xff0c;開發和制造出達到最嚴格質量標準的產品。“開源智造Odoo醫療器械行業解決方案”是為醫療器械制造商設計的全球企業資源規劃(ERP)軟…

Redis鍵值對中值的數據結構

前言 前面我們已經介紹了Redis的鍵值對存儲管理的底層數據結構。如果不清楚的同志可以看我前面的博客 Redis數據庫存儲鍵值對的底層原理-CSDN博客 下面,我們來看一下Redis鍵值對中值的數據結構有那些叭 Redis常見的5種數據類型 string …

MySQL自動化安裝工具-mysqldeploy

功能 可在linux系統上安裝 mysql5.5/5.6/5.7/8.0/8.4 版本的 MySQL&#xff0c;可以初始化多實例 MySQL。 碼云: https://gitee.com/hh688/mysqldeploy guithub: https://github.com/hhkens/mysqldeploy 限制 僅在 centos7 環境進行測試&#xff0c;后期可能支持更多系統。 此程…

簡要探討大型語言模型(LLMs)的發展歷史

關注大型語言模型(LLMs) 簡要探討語言模型的發展歷史 理解Transformer架構的基本元素和注意力機制 了解不同類型的微調方法 語言模型的大小之分 在語言模型領域,“小”和“大”是相對概念。幾年前還被視為“巨大”的模型,如今已被認為相當小。該領域發展迅猛,從參數規模為…

Java試題-選擇題(2)

Java試題-選擇題(2) 題目 下列語句創建對象的總個數是: String s=“a”+“b”+"c”+“d”+"e” A.4 B.2 C.3 D.1 關于下面的程序段的說法正確的是()? File file1=new File(“e:\xxx\yyy\zzz");file1.mkdir(); A.如目錄e:\xxx\yyy\不存在,程序會拋出FileN…

揭秘動態測試:軟件質量的實戰防線

動態測試概述&#xff08;擴展版&#xff09; 目錄 動態測試概述&#xff08;擴展版&#xff09; 一、動態測試的定義與重要性 ? 二、動態測試類型 &#x1f50d; &#xff08;一&#xff09;功能測試 &#x1f9e9; &#xff08;二&#xff09;非功能測試 &#x1f4ca…

機器學習①【機器學習的定義以及核心思想、數據集:機器學習的“燃料”(組成和獲取)】

文章目錄先言一、什么是機器學習1.機器學習的定義以及核心思想2.機器學習的四大類型2.1監督學習&#xff08;Supervised Learning&#xff09;2.2半監督學習&#xff08;Midsupervised Learning&#xff09;2.3無監督學習&#xff08;Unsupervised Learning&#xff09;2.4強化…

GaussDB 數據庫架構師(十二) 資源規劃

1 硬件和軟件要求 1&#xff09;硬件配置示例 硬件配置示例設備類型 設備型號 數量 備注 計算節點 CPU&#xff1a; 2*64 Cores&#xff0c;Kunpeng 920 內存&#xff1a;32*32GB 系統盤&#xff1a;2*960GB SATA SSD 數據盤&#xff1a;24*960GB SATA SSD RAID卡&#x…

Linux系統文件與目錄內容檢索(Day.2)

一、文件和目錄內容檢索處理命令1、uniq去重語法uniq [options] [input_file [output_file]]選項選項作用-c進行計數&#xff0c;并刪除文件中重復出現的行-d僅顯示連續的重復行-u僅顯示出現一次的行-i忽略大小寫案例1、刪除輸入文件中的重復行sort input.txt | uniq2、僅顯示重…

如何選擇一個容易被搜索引擎發現的域名?

在這個數字化時代&#xff0c;域名不僅是企業線上身份的標識&#xff0c;更是影響網站搜索曝光率的關鍵因素。一個精心挑選的域名能為品牌帶來更多自然流量&#xff0c;下面我們就來探討幾個實用技巧。一、簡潔易記是王道好域名首先要讓人過目不忘。想象一下&#xff0c;當用戶…