【Spring Boot】分層開發 Web 應用程序(含實例)

分層開發 Web 應用程序

  • 1.應用程序分層開發模式:MVC
    • 1.1 了解 MVC 模式
    • 1.2 MVC 和三層架構的關系
  • 2.視圖技術 Thymeleaf
  • 3.使用控制器
    • 3.1 常用注解
      • 3.1.1 @Controller
      • 3.1.2 @RestController
      • 3.1.3 @RequestMapping
      • 3.1.4 @PathVariable
    • 3.2 將 URL 映射到方法
    • 3.3 在方法中使用參數
      • 3.3.1 獲取路徑中的值
      • 3.3.2 獲取路徑中的參數
      • 3.3.3 通過 Bean 接收 HTTP 提交的對象
      • 3.3.4 用注解 @ModelAttribute 獲取參數
      • 3.3.5 通過 HttpServletRequest 接收參數
      • 3.3.6 用 @RequestParam 綁定入參
      • 3.3.7 用 @RequestBody 接收 JSON 數據
      • 3.3.8 上傳文件 MultipartFile
      • 3.3.9 上傳圖片
  • 4.理解模型
  • 5.實現 MVC 模式的 Web 應用程序(實戰)
    • 5.1 添加依賴
    • 5.2 創建實體模型
    • 5.3 創建控制器
    • 5.4 創建用于展示的視圖

1.應用程序分層開發模式:MVC

1.1 了解 MVC 模式

Spring Boot 開發 Web 應用程序主要使用 MVC 模式。MVC 是 Model(模型)、View(視圖)、Controller(控制器)的簡寫。

  • Model:是 Java 的實體 Bean,代表存取數據的對象或 POJO(Plain Ordinary JavaObiects,簡單的 Java 對象),也可以帶有邏輯。其作用是在內存中暫時存儲數據,并在數據變化時更新控制器(如果要持久化,則需要把它寫入數據庫或者磁盤文件中)。
  • View:主要用來解析、處理、顯示內容,并進行模板的渲染。
  • Controller:主要用來處理視圖中的響應。它決定如何調用 Model(模型)的實體 Bean、如何調用業務層的數據增加、刪除、修改和查詢等業務操作,以及如何將結果返給視圖進行渲染。建議在控制器中盡量不放業務邏輯代碼。

這樣分層的好處是:將應用程序的用戶界面和業務邏輯分離,使得代碼具備良好的可擴展性可復用性、可維護性和靈活性。

如果不想使用 MVC 開發模式也是可以的,MVC 只是一個非常合理的規范。MVC 的關系如下圖所示。

在這里插入圖片描述
如果讀者對 MVC 開發模式理解得不深入,那么往往會以為用戶通過瀏覽器訪問 MVC 模型的頁面就是訪問視圖(View)。實際上,它并不是直接訪問視圖,而是訪問 DispatcherServlet 處理映射和調用視圖渲染,然后返回給用戶的數據。

在整個 Spring MVC 框架中,DispatcherServlet 處于核心位置,繼承自 HttpServlet。它負責協調和組織不同組件,以完成請求處理并返回響應工作。

整個工程流程如下:

  • 客戶端(用戶)發出的請求由 Tomcat(服務器)接收,然后 Tomcat 將請求轉交給 DispatcherServlet 處理。
  • DispatcherServlet 匹配控制器中配置的映射路徑,進行下一步處理。
  • ViewResolver 將 ModelAndView 或 Exception 解析成 View。然后 View 會調用 render() 方法,并根據 ModelAndView 中的數據渲染出頁面。

在 MVC 開發模式中,容易混淆的還有 Model,它往往會被認為是業務邏輯層或 DAO 層。這種理解并不能說是錯誤的,但并不是嚴格意義上的 MVC 模式。

1.2 MVC 和三層架構的關系

🚀 可參考博主寫的一篇博文《MVC框架和經典三層結構》

三層架構,就是將整個應用程序劃分為 表現層(UI)、業務邏輯層(Service)、數據訪問層(DAO / Repository)。

  • 表現層:用于展示界面。主要對用戶的請求進行接收,以及進行數據的返回。它為客戶端(用戶)提供應用程序的訪問接口(界面)。
  • 業務邏輯層:是三層架構的服務層,負責業務邏輯處理,主要是調用 DAO 層對數據進行增加、刪除、修改和查詢等操作。
  • 數據訪問層:與數據庫進行交互的持久層,被 Service 調用。在 Spring Data JPA 中由 Hibernate 來實現。
  • Repository 和 DAO 層一樣,都可以進行數據的增加、刪除、修改和查詢。它們相當于倉庫管理員,執行進 / 出貨操作。
  • DAO 層的工作是 存取對象。Repository 層的工作是 存取和管理對象
  • 簡單理解就是:Repository = 管理對象(對象緩存和在 Repository 的狀態)+ DAO。

嚴格地說,MVC 是三層架構中的 UI 層。通過 MVC 把三層架構中的 UI 層又進行了分層。

由此可見,三層架構是基于業務邏輯或功能來劃分的,而 MVC 是基于頁面或功能來劃分的。

2.視圖技術 Thymeleaf

Spring Boot 主要支持 Thymeleaf、Freemarker、Mustache、Groovy Templates 等模板引擎。

Thymeleaf 可以輕易地與 Spring MVC 等 Web 框架進行集成。

Thymeleaf 語法并不會破壞文檔的結構,所以 Thymeleaf 模板依然是有效的 HTML 文檔。模板還可以被用作工作原型,Thymeleaf 會在運行期內替換掉靜態值。它的模板文件能直接在瀏覽器中打開并正確顯示頁面,而不需要啟動整個 Web 應用程序。

現代軟件開發基本遵循前后端分離模式,會有專門的前端框架,如 Vue、React 等,本文對于 Thymeleaf 不再展開,有興趣可以自行了解。

Thymeleaf 解決了前端開發人員要和后端開發人員配置一樣環境的尷尬和低效。它通過屬性進行模板渲染,不需要引入不能被瀏覽器識別的新的標簽。頁面直接作為 HTML 文件,用瀏覽器打開頁面即可看到最終的效果,可以降低前后端人員的溝通成本。

要使用 Thymeleaf,首先需要引入依賴。直接在 pom.xml 文件中加入以下依賴即可。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

3.使用控制器

在 Spring MVC 中,控制器(Controller)負責處理由 DispatcherServlet 接收并分發過來的請求。它把用戶請求的數據通過業務處理層封裝成一個 Model,然后再把該 Model 返回給對應的 View 進行展示。

Controller 無須繼承特定的類或實現特定的接口。只需使用 @Controller(@RestController)來標記一個控制器,然后用注解 @RequestMapping 定義 URL 請求和 Controller 方法之間的映射,這樣 Controller 就能被外界訪問到。它可以包含多個請求處理方法。

3.1 常用注解

Spring MVC 控制器中常使用的注解有如下幾種。

3.1.1 @Controller

@Controller 標記在類上。使用 @Controller 標記的類表示是 Spring MVC 的 Controller 對象。分發處理器將會掃描使用了該注解的類,并檢測其中的方法是否使用了注解 @RequestMapping。注解 @Controler 只是定義了一個控制器類,使用了注解 @RequestMapping 的方法才是真正處理請求的處理器,完成映射關系。

3.1.2 @RestController

@RestController 是 Spring 4.0 之后才有的注解。它等價于原來的注解 @Controller 加上注解 @ResponseBody 的功能,直接返回字符串。用它來標注 Rest 風格的控制器類。

3.1.3 @RequestMapping

它用來處理請求地址映射的注解,可用在類或方法上。如果用在類上,則表示類中的所有響應請求的方法都以該地址作為父路徑。

RequestMapping 注解有 6 個屬性。

  • value:指定請求的地址。
  • method:指定請求的 method 類型,例如 GETHEADPOSTPUTPATCHDELETEOPTIONSTRACE
  • consumes:消費消息,指定處理請求的提交內容類型(Content-Type),例如 application/jsontext/html
  • produces:生產消息,指定返回的內容類型。僅當 request 請求頭中的 Accept 類。含該指定類型時才返回。
  • params:指定 request 中必須包含某些參數值才讓該方法處理請求。
  • headers:指定 request 中必須包含某些指定的 header 值才能讓該方法處理請求。

3.1.4 @PathVariable

將請求 URL 中的模板變量映射到功能處理方法的參數上,即獲取 URI 中的變量作為參數。以下代碼先通過獲取路徑中的 id 值,再根據獲取的 id 值來獲取數據庫中產品的對象。

@RequestMapping(value="/product/{id}",method = RequestMethod.GET)
public String getProduct(@PathVariable("id") String id){Product product = productRepository.findById(id);System.out.println("產品 id :" + product.getId());System.out.println("產品名稱 :" + product.getTitle());return "product/show"
}

3.2 將 URL 映射到方法

將 URL(統一資源定位符)映射到方法,是通過注解 @RequestMapping 來處理的。URL 映射其實就是用控制器定義訪問的 URL 路徑。用戶通過輸入路徑來訪問某個方法。
在這里插入圖片描述
注解 @RequestMapping 可以在類和方法上使用。如在類上使用,則可以窄化映射。如以下代碼:

@RestController
@RequestMapping("news")
Public class NewsController {// GET方式@RequestMapping(value = "/", method = RequestMethod.GET)public void add(){}// POST方式@RequestMapping(value = "/", method = RequestMethod.POST)public void save(){}
}

訪問 addsave 方法都需要加上 news 級目錄,如下所示。

  • GET 方式訪問 add 方法的路徑:http://localhost:8080/news/
  • POST 方式訪問 save 方法的路徑:http://localhost:8080/news/

這里的路徑是一樣的,但并不錯誤,因為資源路徑一樣,只是 HTTP 方法不一樣。

Spring Boot 還提供了更簡潔的編寫 URL 映射的方法,如 @GetMapping("/"),它等價于 @RequestMapping(value="", method = RequestMethod.GET)。除此之外還有下面的寫法。

  • @GetMapping:處理 GET 請求。
  • @PostMapping:處理 POST請求
  • @DeleteMapping:處理刪除請求。
  • @PutMapping:處理修改請求。

3.3 在方法中使用參數

對于程序開發的初學者來說,比較困難的可能并不是理論,而是程序的具體實現。比如,如何把最簡單的程序運行起來,如何實現參數的接收和發送等。本節講解的就是如何在控制器的方法中使用參數。

3.3.1 獲取路徑中的值

/**
*Description:根據id 獲取文章對象
*/
@GetMapping("article/{id}")
public ModelAndView getArticle(@PathVariable("id") Integer id) {Article articles = articleRepository.findById(id);ModelAndView mav = new ModelAndView("article/show");mav.addObject("article", articles);return mav;
}

在訪問 http://localhostarticle/123 時,程序會自動將 URL 中的模板變量 {id} 綁定到通過 @PathVariable 注解的同名參數上,即 “程序獲取路徑中 123 的值”。

3.3.2 獲取路徑中的參數

對于路徑中的參數獲取,可以寫入方法的形參中。下面代碼是獲取參數 username 的值。

@RequestMapping("/addUser")
public String addUser(String username) {
}

這里的參數和上面所講的獲取路徑值是不一樣的,比如 http://localhostuser/?username=longzhiran,它是由 = 隔開的。

3.3.3 通過 Bean 接收 HTTP 提交的對象

可以通過 Bean 獲取 HTTP 提交的對象,如以下代碼:

public String addUser(UserModel user)

3.3.4 用注解 @ModelAttribute 獲取參數

用于從 Model、Form 或 URL 請求參數中獲取屬性值,如以下代碼:

@RequestMapping(value="addUser",method=RequestMethod.POST)
public String addUser(@ModelAttribute("user") UserModel user)

3.3.5 通過 HttpServletRequest 接收參數

可以通過 HttpServletRequest 接收參數,如以下代碼:

@RequestMapping("/addUser")
public String addUser(HttpServletRequest request) {System.out.println("name:" + request.GETParameter("username"));return "/index";
}

3.3.6 用 @RequestParam 綁定入參

用法如以下代碼:

@RequestParam(value="username",required=false)

當請求參數不存在時會有異常發生,可以通過設置屬性 required=false 來解決。

3.3.7 用 @RequestBody 接收 JSON 數據

可以通過 @RequestBody 注解來接收 JSON 數據,如以下代碼:

@RequestMapping(value = "adduser", method = {RequestMethod.POST})
@ResponseBody
public void saveUser(@RequestBody List<User> users) {userService.Save(users);
}

3.3.8 上傳文件 MultipartFile

通過 @RequestParam 獲取文件,如以下代碼:

public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {if (file.isEmpty()) {redirectAttributes.addFlashAttribute("message", "請選擇文件");return "redirect:uploadStatus";}try {byte[] bytes = file.getBytes();Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());Files.write(path, bytes);redirectAttributes.addFlashAttribute("message", "成功上傳 " + file.getOriginalFilename() + "");} catch (IOException e) {e.printStackTrace();}return "redirect:/uploadStatus";
}

出于安全考慮,在生產環境中需要判斷文件的類型,一般不允許上傳 .exe 等格式的可執行文件。

3.3.9 上傳圖片

很多人在整合富文本編輯器時不容易成功,特別是在不同版本要求返回的數據類型不一樣時,而網絡上的資料很多是不帶版本號或是過時的。

CKEditor 4.10.1 之后的版本只有返回的是 JSON 格式的數據才能成功,如 [{"uploaded":1, "fileName":"fileName", "url"="", "message":"上傳成功"}]

4.理解模型

模型(Model)在 MVC 模式中是實體 Bean,代表一個存取數據的對象或 POJO(Plain OrdinaryJava Object)。它可以帶有邏輯,其作用是暫時存儲數據(存在內存中),以便進行持久化(存入數據庫或寫入文件),以及在數據變化時更新控制器。簡單地理解是:Model 是數據庫表對應的實體

以下代碼定義了一個用戶實體 Bean(Model)。

@Getter
@Setter
public class User {//定義idprivate long id;//定義用戶名private String name;//定義用戶年齡private int age;
}

可以通過常用的 GetterSetter 封裝來對實體 Bean 進行賦值、獲值操作,并在其中添加邏輯代碼。

5.實現 MVC 模式的 Web 應用程序(實戰)

在這里插入圖片描述

5.1 添加依賴

MVC 模式的 Web 應用程序需要依賴 Spring Boot 的 spring-boot-starter-web(Starter)還需要添加模板的依賴。具體依賴如以下代碼:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

5.2 創建實體模型

創建實體 Bean,用于和 Controller 進行數據交互。

package com.example.demo.model;
import lombok.Data;@Data
public class User {//定義idprivate long id;//定義用戶名private String name;//定義用戶年齡private int age;
}

5.3 創建控制器

控制器層用來實例化實體 Bean(Model),并傳值給視圖模版。

package com.example.demo.controller;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;@Controller
public class MVCDemoController {//映射URL地址@GetMapping("/mvcdemo")public ModelAndView hello() {//實例化對象User user = new User();user.setName("pipi");user.setAge(26);//定義mvc中的視圖模板ModelAndView modelAndView = new ModelAndView("mvcdemo");//傳遞user實體對象給視圖modelAndView.addObject("user",user);return modelAndView;}
}

5.4 創建用于展示的視圖

以下代碼用于獲取控制器中傳遞的實體 Bean,并進行渲染。

<!DOCTYPE html>
<!--thymeleaf模板支持-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body><div><!-- 顯示由控制器傳遞過來的實體user的值--><div th:text="${user.name}"></div><div th:text="${user.age}"></div></div>
</body>
</html>

啟動項目,然后訪問 http://localhost:8080/mvcdemo

在這里插入圖片描述

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

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

相關文章

用戶數據報協議UDP實現可靠傳輸的思路

一、UDP協議的特點 按照報文來分割發送。不需要建立連接和維護連接。不需要接收確認。速度較快。不確保接收的順序和發送順序一樣。 二、用UDP實現可靠通信的思路 (一)接收時發送一個確認報文 實現接收確認的機制。 (二)每個報文騰出空間放置序號 發送時設置序號&#xff0c…

如何安裝虛擬機Wmware,并且在虛擬機中使用centos系統

1. 前言 大家好&#xff0c;我是jiaoxingk 本篇文章主要講解如何安裝虛擬機&#xff0c;并且在虛擬機中安裝centos系統&#xff0c;讓windows電腦也能夠使用Linux系統 2. 虛擬機的介紹 在安裝Vmware之前&#xff0c;我們先做虛擬機的介紹 虛擬機&#xff1a;通過軟件虛擬出來的…

Docker拉取鏡像報錯:x509: certificate has expired or is not yet v..

太久沒有使用docker進行鏡像拉取&#xff0c;今天使用docker-compose拉取mongo發現報錯&#xff08;如下圖&#xff09;&#xff1a; 報錯信息翻譯&#xff1a;證書已過期或尚未有效。 解決辦法&#xff1a; 1.一般都是證書問題或者系統時間問題導致&#xff0c;可以先執行 da…

用HAL庫改寫江科大的stm32入門例子-6-2 定時器外部時鐘

實驗目的&#xff1a; 熟悉外部時鐘的應用。 實驗步驟&#xff1a; 創建項目參照前面的文章&#xff0c;集成oled(沒有oled,用uart串口傳遞也可以)選擇外部時鐘源時鐘源參數設置編寫代碼&#xff1a; 5.1聲明全局變量&#xff0c;如果發生定時器中斷的時候&#xff0c;在回調…

SW 零件插入零件的重合配合

重合配合有時候會失效,可以先用距離配合代替,之后修改距離盡量接近

AI網絡爬蟲-自動獲取百度實時熱搜榜

工作任務和目標&#xff1a;自動獲取百度實時熱搜榜的標題和熱搜指數 標題&#xff1a;<div class"c-single-text-ellipsis"> 東部戰區臺島戰巡演練模擬動畫 <!--48--></div> <div class"hot-index_1Bl1a"> 4946724 </div> …

【bash】統計服務器信息腳本

起因 寫一個bash腳本統計服務器的機器名、內網IP、CPU使用率、內存使用率、List{GPU使用率、顯存} 腳本 #!/bin/bash# 主機名 hostname$(hostname) # 內網ip ip$(ip addr | grep inet | grep -v 127.0.0.1 | awk {print $2} | cut -d/ -f1) ip$(echo "$ip"|tr \n…

Excel表格在線解密:輕松解密密碼,快速恢復數據

忘記了excel表格密碼&#xff1f;教你簡單兩步走&#xff1a;具體步驟如下。首先&#xff0c;在百度搜索中鍵入“密碼帝官網”。其次&#xff0c;點擊“立即開始”&#xff0c;在用戶中心上傳表格文件即可找回密碼。這種方法不用下載軟件&#xff0c;操作簡單易行&#xff0c;適…

【DZ模板】價值288克米設計APP手機版DZ模板 數據本地化+完美使用

模版介紹 【DZ模板】價值288克米設計APP手機版DZ模板 數據本地化完美使用 騰訊官方出品discuz論壇DIY的后臺設置&#xff0c;功能齊全&#xff0c;論壇功能不亞于葫蘆俠&#xff0c;自定義馬甲&#xff0c;自定義認證&#xff0c;自定義廣告&#xff0c;完全可以打造出自己想…

元本學堂是什么?杜旭東疑似再翻車!

杜旭東&#xff0c;1956年1月7日出生于中國北京市&#xff0c;畢業于解放軍藝術學院&#xff0c;中國內地男演員、國家一級演員&#xff01; 2023年11月17日晚&#xff0c;杜旭東在其個人社交媒體上發布視頻&#xff0c;就其以前給緬北電詐集團的白家成員錄制慶生視頻一事道歉…

C++11std::bind的簡單使用

std::bind用來將可調用對象與其參數一起進行綁定&#xff0c;綁定后的結果可以用std::function&#xff08;可調用對象包裝器&#xff09;進行保存&#xff0c;并延遲調用到任何我們需要的時候。 通俗來講&#xff0c;它主要有兩大作用&#xff1a; &#xff08;1&#xff09…

每日一題Cat, Fox and the Lonely Array

文章目錄 題名&#xff1a;題意&#xff1a;題解&#xff1a;代碼&#xff1a; 題名&#xff1a; Cat, Fox and the Lonely Array 題意&#xff1a; 給定一個數組a&#xff0c;求出最小的k&#xff0c;滿足數組每個長度為k的連續子數組元素按位或答案都相等。 題解&#xf…

【AI新時代】擁抱未來,用AI無人直播替代真人直播,解放勞動力,控制成本!

在科技日新月異的新時代&#xff0c;人工智能&#xff08;AI&#xff09;的 keJ0277 浪潮正在席卷各行各業&#xff0c;為傳統的工作模式帶來了前所未有的變革。其中&#xff0c;AI無人直播的興起&#xff0c;無疑是這場科技革命中的一股強勁力量。它以其獨特的優勢&#xff0…

【Linux設備驅動】1.字符設備驅動程序框架及相關結構體

目錄 程序總體框架模塊加載函數模塊卸載函數具體操作函數 相關結構體cdev結構體file_oparations結構體 設備號分配設備號注銷設備號創建設備文件 程序總體框架 /* 包含相關頭文件 */ #include <linux/module.h> #include <linux/fs.h> #include <linux/init.h&…

C# System.Span<T>、ref struct

1. Span<T>的特性 system.span<T>在.net core 2.0版本引入它適用于對連續內存的操作&#xff0c;而不產生新的內存分配&#xff0c;比如數組、字符串、堆外內存類型為ref struct&#xff0c;不能作為參數傳遞&#xff0c;不能被裝箱(不能作為類的字段)&#xff0c…

信號處理技術:現代通信技術的基石

隨著信息技術的飛速發展&#xff0c;通信技術的每一次革新都極大地改變了人們的生活方式。而在這背后&#xff0c;信號處理技術作為通信技術的核心&#xff0c;通過深入分析信號特性、提取有用信息、轉換信號形式等一系列手段&#xff0c;為現代通信技術的發展提供了強有力的支…

機器學習7大方面,30個硬核數據集。純干貨分享

在剛剛開始學習算法的時候&#xff0c;大家有沒有過這種感覺&#xff0c;最最重要的那必須是算法本身&#xff01; 其實在一定程度上忽略了數據的重要性。 而事實上一定是&#xff0c;質量高的數據集可能是最重要的&#xff01; 數據集在機器學習算法項目中具有非常關鍵的重…

Python讀寫文件

最近得以空閑&#xff0c;然后繼續學習py。 學習一下py中最頻繁用到的文件讀寫的方法。 在py中&#xff0c;操作是通過文件對象【File obj】實現的&#xff0c;通過文件對象可以讀寫文本文件和一些二進制文件。 1.打開文件 使用Python中的open函數。有8個參數&#xff0c;但…

2024.5.25.python.exercise

# # 導入數據處理的包 # # from pyecharts.charts import Line # # from pyecharts.options import TitleOpts, LegendOpts, ToolboxOpts, VisualMapOpts, LabelOpts # # import json # # # # # 打開文件 # # file_us open("美國.txt", "r", encoding&quo…

C++ Primer Plus第十八章復習題

1、使用用大括號括起的初始化列表語法重寫下述代碼。重寫后的代碼不應使用數組ar。 class z200 { private:int j;char ch;double z; public:Z200(int jv,char chv&#xff0c;zv) : j(jv), ch (chv), z(zv){} };double x 8.8; std::string s "what a bracing effect ! …