Java應用開發(中、高級)課件 項目2 服務接口應用開發與測試_第1頁
Java應用開發(中、高級)課件 項目2 服務接口應用開發與測試_第2頁
Java應用開發(中、高級)課件 項目2 服務接口應用開發與測試_第3頁
Java應用開發(中、高級)課件 項目2 服務接口應用開發與測試_第4頁
Java應用開發(中、高級)課件 項目2 服務接口應用開發與測試_第5頁
已閱讀5頁,還剩181頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

項目2

服務接口應用開發與測試

學習目標本項目主要學習使用JavaEE開源框架編寫API接口提供數據存儲、通訊、各類服務等功能。掌握使用SpringBoot框架構建后端項目,以及用項目管理工具Maven對Java項目進行構建、依賴管理。為保證API接口的授權訪問,掌握使用通過SpringSecurity框架和JWT完成接口的權限控制功能。同時通過標準軟件開發過程實踐,熟悉接口設計、編碼和測試標準流程以及編寫相關的文檔。

項目介紹將項目二的餐廳點餐系統使用服務接口的設計思路進行改造升級,為前后端分離架構開發提供后端服務支撐,使用主流的開發框架SpringBoot,結合常用的SpringMVC、Mybatis、SpringSecurity等技術框架實現登錄認證、用戶管理、菜品管理等接口功能。

知識結構

任務一

編寫接口設計文檔01

任務描述本任務主要是編寫項目的接口設計文檔,作為后續開發接口的標準。

知識準備1)接口設計文檔在項目開發中,采用前后端分離架構開發,就需要由前后端開發工程師共同定義接口,編寫接口文檔,之后開發人員需根據這個接口文檔進行開發,到項目結束前都要一直維護還項目文檔。2)接口文檔作用●約束:在前后端合作開發的項目中,可能會出現前后端開發人員對接口理解不一致的情況,在這個時候,接口設計文檔就起到了約束的作用?!褚幏叮涸陧椖恐型ǔ啥鄠€開發人員協同完成,如果沒有接口設計文檔,代碼的實現邏輯就可能差別很大,從而降低開發效率,增加維護成本。通過接口設計文檔,就可以規范項目中接口的實現思路,方便后期人員查看、維護。

任務實施步驟1:編寫接口文檔的項目介紹前言項目概述本系統是應用于餐廳的點餐系統,共實現了3種角色及其他功能,分別是餐廳服務員的點餐、提效結賬功能;后廚的配菜功能;管理員的結賬、用戶管理等功能。從而實現餐廳管理信息化的作用,同時也有效提升了點餐、配菜、結賬等工作的效率。用戶故事根據用戶故事識別系統必須處理的各種請求,識別出應用程序的核心系統操作,見用戶故事接口表3-1。t

任務實施步驟1:編寫接口文檔的項目介紹t表3-1用戶故事接口表

任務實施步驟1:編寫接口文檔的項目介紹t功能模塊根據用戶故事,將接口大致劃分為幾個模塊,詳情表3-2:表3-2功能模塊表

任務實施步驟2:編寫登錄模塊的接口設計t1)用戶登錄模塊接口描述

用戶登錄模塊接口描述見表3-3表3-3登錄功能接口表

任務實施步驟2:編寫登錄模塊的接口設計t2)用戶登錄接口設計(1)接口說明:請求方式為“POST”,請求地址為“/login”。(2)功能說明:用戶通過提交用戶名和密碼,獲取授權的token標志,并獲取用戶信息。(3)請求參數(輸入值)見表3-4。表3-4登錄接口參數表

任務實施步驟2:編寫登錄模塊的接口設計t(4)響應參數(輸出值)見表3-5。表3-5登錄接口響應表

任務實施步驟2:編寫登錄模塊的接口設計t(5)輸出值JSON格式示例

任務實施步驟3:編寫用戶管理模塊的接口設計t用戶管理用戶管理接口見表3-6

任務實施步驟3:編寫用戶管理模塊的接口設計t1)用戶列表接口設計(1)接口說明:請求方式為“GET”,請求地址為“/admin/user/getuserbypage”。(2)功能說明:通過分頁頁碼,查詢列表數據。(3)請求參數(輸入值)見表3-7。

任務實施步驟3:編寫用戶管理模塊的接口設計t(4)響應參數(輸出值)見表3-5。

任務實施步驟3:編寫用戶管理模塊的接口設計t(5)輸出值JSON格式示例

任務實施步驟3:編寫用戶管理模塊的接口設計t2)新增用戶接口設計(1)接口說明:請求方式為“POST”,請求地址為“/admin/user/adduser”。(2)功能說明:新增一條用戶記錄。(3)請求參數(輸入值):UserInfo見表3-9。

任務實施步驟3:編寫用戶管理模塊的接口設計t(4)響應參數(輸出值)見表3-10。

任務實施步驟3:編寫用戶管理模塊的接口設計t(5)輸出值JSON格式示例

任務實施步驟3:編寫用戶管理模塊的接口設計t3)刪除用戶接口設計(1)接口說明:請求方式為“POST”,請求地址為“/admin/user/deleteuser”。(2)功能說明:刪除一條用戶記錄。(3)請求參數(輸入值)見表3-11。

任務實施步驟3:編寫用戶管理模塊的接口設計t(4)響應參數(輸出值)見表3-12。

任務實施步驟3:編寫用戶管理模塊的接口設計t(5)輸出值JSON格式示例

任務實施步驟3:編寫用戶管理模塊的接口設計t4)更新用戶接口設計(1)接口說明:請求方式為“POST”,請求地“/admin/user/adminmodifyuser”。(2)功能說明:更新用戶記錄。(3)請求參數(輸入值)見表3-13。

任務實施步驟3:編寫用戶管理模塊的接口設計t(4)響應參數(輸出值)見表3-14。

任務實施步驟3:編寫用戶管理模塊的接口設計t(5)輸出值JSON格式示例

任務實施步驟3:編寫用戶管理模塊的接口設計t5)查詢用戶接口設計(1)接口說明:請求方式為“GET”,請求地址為“/admin/user/get”。(2)功能說明:通過用戶ID查詢數據。(3)請求參數(輸入值)見表3-15。

任務實施步驟3:編寫用戶管理模塊的接口設計t(4)響應參數(輸出值)見表3-16。

任務實施步驟3:編寫用戶管理模塊的接口設計t(5)輸出值JSON格式示例

任務實施步驟3:編寫用戶管理模塊的接口設計t6)驗證用戶名是否可用的接口設計(1)接口說明:請求方式為“POST”,請求地址為“/admin/user/checkuser”。(2)功能說明:檢查用戶名是否可用。(3)請求參數(輸入值)見表3-17

任務實施步驟3:編寫用戶管理模塊的接口設計t(4)響應參數(輸出值)見表3-18。

任務實施步驟3:編寫用戶管理模塊的接口設計t(5)輸出值JSON格式示例

拓展練習按照該任務的步驟2、3設計菜品管理、訂單流程的接口設計。

知識小結本任務主要是編寫項目的接口設計文檔,在編寫文檔過程中了解項目接口設計的基本內容,掌握接口文檔的基本結構和接口規范。編寫接口設計文檔包含下面核心內容:1.定義接口的請求方式和請求地址;2.描述接口功能邏輯;3.定義輸入值,請求參數;4.定義輸出值,響應參數;5.定義輸出值JSON格式。本任務知識技能點與等級證書對應關系見表3-19:

知識小結謝謝您的觀看!

任務二

搭建SpringBoot項目基礎02

任務描述本任務將通過STS搭建基本的SpringBoot項目,并通過配置Maven依賴,引入常用的項目基礎框架;另外,還會引入項目中需要用到的基礎工具類,通過以上的工作,搭建一個基本可用的SpringBoot項目。

知識準備1.SpringBoot框架SpringBoot是一個框架、一種全新的編程規范,簡化了Spring眾多框架中所需的大量且繁瑣的配置文件,讓文件配置變的相當簡單,讓應用部署變的簡單,可以快速開啟一個Web容器進行開發,所以SpringBoot是一個服務于框架的框架,服務范圍是簡化配置文件。

知識準備2.SpringBoot的核心功能010203可獨立運行的Spring項目:SpringBoot可以以jar包的形式獨立運行。內嵌的Servlet容器:SpringBoot可以選擇內嵌Tomcat、Jetty或者Undertow,無須以war包形式部署項目。簡化的Maven配置:Spring提供推薦的基礎POM文件來簡化Maven配置。

知識準備040506自動配置Spring:SpringBoot會根據項目依賴來自動配置Spring框架,極大地減少項目要使用的配置。提供生產就緒型功能:提供可以直接在生產環境中使用的功能,如性能指標、應用信息和應用健康檢查。無代碼生成和xml配置:SpringBoot不生成代碼。完全不需要任何xml配置即可實現Spring的所有配置

知識準備3Maven項目管理工具Maven是項目管理工具,主要有兩大作用:項目構建和依賴管理。項目構建就是項目編譯、測試、集成發布實現自動化,依賴管理是很方便的功能,只要把當前項目所依賴的構件(jar、war等)寫到pom配置文件中,就可以從倉庫中自動導入對應的構件及構件依賴的其他構件,不同的maven項目共享一個構件倉庫,項目引用倉庫中的構建,避免重復下載。

任務實施步驟1:創建項目t1在STS中單擊“File”菜單,選擇“New”->“SpringStarterProject”創建SpringBoot項目,如圖3-1所示:

任務實施步驟1:創建項目t2添加項目信息,填寫包名和唯一標志等項目信息,填寫完畢后點擊“Next”進入下一步,過程如圖3-2所示:

任務實施步驟1:創建項目t3“NewSpringStarterProjectDependencies”窗口,單擊選擇“Web->SpringWeb”,單擊“Finish”按鈕,過程如圖3-3所示:

任務實施步驟2:創建項目結構t1在項目目錄下,分別新建下列的包,把功能相關的類或接口組織在同一個包中,方便類的查找和使用。包名描述見表3-20。

任務實施步驟2:創建項目結構t2創建后結果如圖3-4所示

任務實施步驟3:編寫maven依賴文件t在pom.xml文件中,添加如下代碼引入commons-lang3包:

任務實施步驟4:引入工具類t1獲取教材提供的代碼包,解壓到本地目錄,如圖3-5所示

任務實施步驟4:引入工具類t2引入公共代碼,將代碼包中common的代碼,復制到項目目錄common包下,結果如圖3-6所示:

任務實施步驟4:引入工具類t3引入的common包下的公共類功能如下:“common.constant”包下的常量類見表3-21。

任務實施步驟4:引入工具類t

任務實施步驟4:引入工具類t

任務實施步驟4:引入工具類t4引入工具類,將代碼包中util的代碼,復制到項目目錄util包下,結果如圖3-7所示:

任務實施步驟4:引入工具類t5引入的util包下的工具類功能如下:“util”包下的工具類見表3-25。

任務實施步驟4:測試運行t4

在api包下新建TestController類,結果如圖3-8所示:

任務實施步驟4:測試運行t2在TestController中編寫下面的代碼用于驗證:@RestController@RequestMapping("/test")publicclassTestController{@GetMapping("first")publicStringtest(){return"Helloworld!";}@GetMapping("res")publicResultsresult(){returnResults.success("Helloworld!");}}

任務實施步驟4:測試運行t3在項目名處右鍵,單擊選擇“RunAs->SpringBootApp”運行項目,過程如圖3-9所示:

任務實施步驟4:測試運行t4驗證項目,訪問接口:8080/test/res,出現下面的返回數據,說明項目基礎創建成功,結果如圖3-10所示:

知識小結【對應證書技能】

SpringBoot框架用來簡化項目的初始搭建以及開發過程,該框架中有兩個非常重要的策略:開箱即用和約定優于配置。開箱即用,是指通過在MAVEN項目的pom文件中添加相關依賴包,使用注解來代替繁瑣的XML配置文件來管理對象的生命周期;約定優于配置,是由SpringBoot本身來配置目標結構,由開發者在結構中添加信息的軟件設計范式。這2個特點使得開發人員擺脫了復雜的配置工作以及依賴的管理工作,更加專注于業務邏輯,并且可以將代碼編譯、測試和打包等工作自動化。通過本任務需要理解SpringBoot是一些庫的集合,它能夠被任意項目的構建系統所使用,掌握使用SpringBoot框架搭建后端項目,掌握使用Maven工具管理項目的依賴版本。

知識小結本任務知識技能點與等級證書對應關系見表3-26:謝謝您的觀看!

任務三

實現API的Token認證03

任務描述本任務將通過SpringSecurity和JsonWebToken(JWT)完成接口的權限控制,即在未登錄前無法訪問受保護的接口,成功登錄獲取到token后,能夠通過token訪問受保護的接口。

知識準備1SpringSecurity框架SpringSecurity框架是一個功能強大且高度可定制的身份驗證和訪問控制框架。它是用于保護基于Spring的應用程序的實際標準。SpringSecurity致力于為Java應用程序提供身份驗證和授權。SpringBoot對于SpringSecurity提供了自動化配置方案,可以零配置使用SpringSecurity。

知識準備2數據庫連接池數據庫連接池負責分配、管理和釋放數據庫連接,它允許應用程序重復使用一個現有的數據庫連接,而不是再重新建立一個;在項目中,一般情況下訪問數據庫,會創建一個連接,用完后就關閉它,對于簡單的系統這樣不會帶來什么明顯的性能上的開銷。但是對于一個復雜的系統,頻繁的建立、關閉連接,會極大的減低系統的性能,因為對于數據庫連接的使用可能會成為系統性能的瓶頸。數據庫連接池負責分配、管理和釋放數據庫連接,它允許應用程序重復使用一個現有的數據庫連接,而不是再重新建立一個;釋放空閑時間超過最大空閑時間的數據庫連接來避免因為沒有釋放數據庫連接而引起的數據庫連接遺漏。

任務實施步驟1:引入認證工具類t1在pom.xml文件中,引入MySQL驅動包、Mybatis框架、SpringSecurity框架以及JWT包,添加下面的代碼:<!--mybatis--><dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version></dependency><!--數據庫驅動--><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> <version>8.0.15</version></dependency><!--springsecurity安全認證--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency><!--Token生成與解析--><dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version></dependency>

任務實施步驟1:引入認證工具類t2選中perties文件,右鍵單擊,依次選擇“Refactor->Rename”打開重命名窗口,將perties文件重命名為application.yml文件,結果如圖3-11所示:

任務實施步驟1:引入認證工具類t3)在application.yml文件中,添加下面的代碼server:port:8080#指定打印日志配置logging:level:#定義項目mapper包下的日志打印機別為debugcom.chinasofti.ordersys.mapper:DEBUGspring:profiles:active:dev#熱編譯devtools:restart:#需要實時更新的目錄additional-paths:resources/**,static/**,templates/**datasource:driver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://:3306/ordersys?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=UTCusername:rootpassword:rootplatform:mysql

任務實施步驟1:引入認證工具類t#連接池配置type:com.zaxxer.hikari.HikariDataSourcehikari:#連接池中允許的最小連接數。缺省值:10minimum-idle:10#連接池中允許的最大連接數。缺省值:10maximum-pool-size:100#自動提交auto-commit:true#一個連接idle狀態的最大時長(毫秒),超時則被釋放(retired),缺省:10分鐘idle-timeout:30000#連接池名字pool-name:HikariCP#一個連接的生命時長(毫秒),超時而且沒被使用則被釋放(retired),缺省:30分鐘,建議設置比數據庫超時時長少30秒max-lifetime:1800000#等待連接池分配連接的最大時長(毫秒),超過這個時長還沒可用的連接則發生SQLException,缺省:30秒connection-timeout:30000#數據庫連接測試語句connection-test-query:SELECT1mybatis:#指定實體類存放的包路徑type-aliases-package:com.chinasofti.ordersys.model#指定mapper.xml文件的位置為/mybatis-mappers/下的所有xml文件mapper-locations:classpath:/mybatis-mappers/*#轉換到駝峰命名configuration:mapUnderscoreToCamelCase:true#token配置token:#令牌自定義標識header:Authorization#令牌秘鑰#secret:abcdefghijklmnopqrstuvwxyzsecret:(OREDERSYS:)_$^11244^%$_(IS:)_@@++--(BAD:)_++++_.sds_(GUY:)#令牌有效期(默認30分鐘)expireTime:60

任務實施步驟1:引入認證工具類t4在common包下引入認證工具類,下載教材提供的代碼包并解壓到本地目錄,結果如圖3-12所示:

任務實施步驟1:引入認證工具類t5將代碼包中common文件夾下的代碼,復制到項目目錄common包下,結果如圖3-13所示:

任務實施步驟1:引入認證工具類t

任務實施步驟1:引入認證工具類t6在util包下引入認證工具類,將代碼包中util的代碼,復制到項目目錄util包下,結果如圖3-14所示::

任務實施步驟1:引入認證工具類t

任務實施步驟2:編寫權限認證配置類t1在項目目錄config包下,右鍵config包,依次選擇“New->Class”,創建SecuityConfig類文件,結果如圖3-15所示:

任務實施步驟2:編寫權限認證配置類t2SecurityConfig類需要繼承WebSecurityConfigurerAdapter抽象類,重寫configure(HttpSecurityhttp)方法,用來配置資源訪問權限和驗證用戶權限信息,在SecurityConfig.java文件中添加下面的代碼:/**springsecurity配置*/@EnableGlobalMethodSecurity(prePostEnabled=true,securedEnabled=true)publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{/**自定義用戶認證邏輯*/@AutowiredprivateUserDetailsServiceuserDetailsService;/**認證失敗處理類*/@AutowiredprivateAuthenticationEntryPointImplunauthorizedHandler;/**token認證過濾器*/@AutowiredprivateJwtAuthenticationTokenFilterauthenticationTokenFilter;/**解決

無法直接注入AuthenticationManager*@return*@throwsException*/@Bean@OverridepublicAuthenticationManagerauthenticationManagerBean()throwsException{returnsuper.authenticationManagerBean();}

任務實施步驟2:編寫權限認證配置類t/**強散列哈希加密實現*/@BeanpublicBCryptPasswordEncoderbCryptPasswordEncoder(){returnnewBCryptPasswordEncoder();}/**身份認證接口*/@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());}}

任務實施步驟2:編寫權限認證配置類t3編寫SecurityConfig類,根據接口服務的項目特點,我們需要在認證服務中解決下面的問題:①默認情況下,接口的權限控制②允許登錄接口,靜態資源的匿名訪問③JWT接入到Security框架為了解決上述的問題,下面重寫configure(HttpSecurityhttp)方法,我們在SecurityConfig.java文件中添加下面的代碼:

任務實施步驟2:編寫權限認證配置類t@Overrideprotectedvoidconfigure(HttpSecurityhttpSecurity)throwsException{httpSecurity.csrf().disable()//CRSF禁用,因為不使用session//認證失敗處理類.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()//基于token,所以不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//過濾請求//對于登錄login接口允許匿名訪問,.antMatchers("/login","/api","/t").anonymous()//除上面外的所有請求全部需要鑒權認證.anyRequest().authenticated().and().headers().frameOptions().disable();//添加JWTfilterhttpSecurity.addFilterBefore(authenticationTokenFilter,UsernamePasswordAuthenticationFilter.class);}

任務實施步驟2:編寫權限認證配置類t在上面的代碼中,重點關注幾個部分:

任務實施步驟2:編寫權限認證配置類t4編寫ConfigurerAdapter類,由于現代瀏覽器的請求策略,前后端服務使用的域名不一致的情況下,會導致接口訪問異常;在本項目中,通過后臺的跨域配置,解決此問題。在項目目錄config包下,右鍵config包,依次選擇“New”->“Class”,創建ConfigurerAdapter類文件,結果如圖3-16所示:

任務實施步驟2:編寫權限認證配置類t5在ConfigurerAdapter類文件中,編寫下面的代碼,啟用服務器的跨域配置。@Configuration@EnableWebMvcpublicclassConfigurerAdapterimplementsWebMvcConfigurer{//令牌自定義標識@Value("${token.header}")privateStringheader;@BeanpublicCorsFiltercorsFilter(){UrlBasedCorsConfigurationSourcesource=newUrlBasedCorsConfigurationSource();CorsConfigurationconfig=newCorsConfiguration();config.setAllowCredentials(true);config.addAllowedOrigin("*");config.addAllowedHeader("*");config.addAllowedMethod("*");config.setExposedHeaders(Arrays.asList(header));source.registerCorsConfiguration("/**",config);returnnewCorsFilter(source);}}

任務實施步驟2:編寫權限認證配置類t6編寫GlobalExceptionHandler類用于全局錯誤處理,在項目目錄config包下,右鍵config包,依次選擇“New”->“Class”,創建GlobalExceptionHandler類文件,結果如圖3-17所示:

任務實施步驟2:編寫權限認證配置類t7GlobalExceptionHandler中編寫下面的代碼,通過下面的配置,將應用運行時異常全部攔截,并統一進行處理,返回自定義的業務返回碼。@RestControllerAdvicepublicclassGlobalExceptionHandler{/***攔截所有運行時的全局異常

*/@ExceptionHandler(RuntimeException.class)@ResponseBodypublicResultsruntimeException(RuntimeExceptione){returnResults.failure(ResponseCode.FAIL.getCode(),e.getMessage());}}

任務實施步驟3:新建用戶登錄接口t1.新建用戶實體類(1)在model包下,右鍵model包,依次選擇“New->Class”,新建UserInfo類,結果如圖3-18所示:

任務實施步驟3:新建用戶登錄接口t(2)在UserInfo類中添加下面的代碼publicclassUserInfo{ privateintuserId;//用戶ID privateStringuserAccount;//用戶賬戶 privateStringuserPass;//用戶密碼 privateintroleId;//用戶角色ID privateStringroleName;//用戶角色名 privateintlocked;//用戶是否被鎖定的標識 privateStringfaceimg="default.jpg";//用戶頭像路徑 publicStringgetFaceimg(){ returnfaceimg; } publicvoidsetFaceimg(Stringfaceimg){ this.faceimg=faceimg; } publicintgetLocked(){ returnlocked; } publicvoidsetLocked(intlocked){ this.locked=locked; } publicintgetUserId(){ returnuserId; } publicvoidsetUserId(intuserId){ this.userId=userId; }

任務實施步驟3:新建用戶登錄接口t publicStringgetUserAccount(){ returnuserAccount; } publicvoidsetUserAccount(StringuserAccount){ this.userAccount=userAccount; } publicStringgetUserPass(){ returnuserPass; } publicvoidsetUserPass(StringuserPass){ this.userPass=userPass; } publicintgetRoleId(){ returnroleId; } publicvoidsetRoleId(introleId){ this.roleId=roleId; } publicStringgetRoleName(){ returnroleName; } publicvoidsetRoleName(StringroleName){ this.roleName=roleName; }}

任務實施步驟3:新建用戶登錄接口t2.新建登錄Mapper接口(1)在mapper包下新建LoginMapper類,結果如圖3-19所示:

任務實施步驟3:新建用戶登錄接口t(2)在LoginMapper類中添加下面的代碼。@MapperpublicinterfaceLoginMapper{ @Select("selectuserId,userAccount,userPass,locked,roleId,roleName,faceimgfromuserinfo,roleinfowhereuserinfo.role=roleinfo.roleIdanduserinfo.userAccount=#{userAccount}") publicList<UserInfo>findUsersByName(@Param("userAccount")StringuserAccount);}

任務實施步驟3:新建用戶登錄接口t3.新建登錄Service類(1)在service包下,右鍵service包,依次選擇“New”->“Package”,新建login包結果如圖3-20所示:

任務實施步驟3:新建用戶登錄接口t(2)在service.login包下新建LoginService類,結果如圖3-21所示::

任務實施步驟3:新建用戶登錄接口t(3)在LoginService類中添加下面的代碼@ServicepublicclassLoginService{ @AutowiredLoginMappermapper; publicLoginMappergetMapper(){ returnmapper; } publicvoidsetMapper(LoginMappermapper){ this.mapper=mapper; } /**

*根據用戶名查詢用戶數據 *@paramuserAccount *@return */ publicUserInfofindUserByName(StringuserAccount){ List<UserInfo>list=mapper.findUsersByName(userAccount); UserInfouserInfo=null; if(null!=list&&list.size()==1){ userInfo=list.get(0); } returnuserInfo; }}

任務實施步驟3:新建用戶登錄接口t4.新建登錄Api接口(1)在api包下新建login包,結果如圖3-22所示:

任務實施步驟3:新建用戶登錄接口t

(2)在api.login包下新建LoginController類,結果如圖3-23所示

任務實施步驟3:新建用戶登錄接口t

(3)在LoginController類中,新增登錄邏輯,添加下面的代碼:@RestControllerpublicclassLoginController{ @AutowiredLoginServiceloginService; @AutowiredSysLoginServicesysLoginService; /**

*登錄方法

*@paramusername用戶名

*@parampassword密碼

*@return結果 */ @PostMapping("/login") publicResultslogin(Stringusername,Stringpassword){ System.out.println("/login:username["+username+"]"+"password:["+password+"]");

//生成令牌 Stringtoken=sysLoginService.login(username,password); LoginUseruser=UserHandleUtils.getUser(token); UserInfouserInfo=user.getUser(); userInfo.setUserPass(""); Map<String,Object>res=newHashMap<>(3); res.put("token",token); res.put("user",userInfo); returnResults.success(res); }}

任務實施步驟3:新建用戶登錄接口t5.添加兩個用于測試登陸結果的接口,添加下面的代碼:@GetMapping({"/auth"}) publicResultsauth(Stringusername){ System.out.println("/auth:username["+username+"]"); //生成令牌 Map<String,Object>res=newHashMap<>(); res.put("api","auth"); res.put("username",username); res.put("msg","登錄后可見"); returnResults.success(res); }

@PreAuthorize("hasRole('3')") @GetMapping({"/waiter"}) publicResultstestRoleWaiter(Stringusername){ System.out.println("/test:username["+username+"]"); //生成令牌 Map<String,Object>res=newHashMap<>(); res.put("api","testRoleWaiter"); res.put("username",username); res.put("msg","服務員角色可見");_x0005__x0005_ returnResults.success(res); }

任務實施步驟3:新建用戶登錄接口t6.運行測試(1)運行項目,結果如圖3-24所示:

任務實施步驟3:新建用戶登錄接口t(2)打開PostMan,新建一個測試tab,分別填寫請求鏈接,然后添加兩個請求參數,分別是“username”,值為“aa”;“password”,值為“1”,結果如圖3-25所示:

任務實施步驟3:新建用戶登錄接口t(3)填寫完畢點擊“send”按鈕發送請求,看到返回的用戶信息,說明登錄成功。結果如圖3-26所示:

任務實施步驟3:新建用戶登錄接口t(4)測試登錄限制接口“/auth”點擊“+”號新建請求tab,并按照下面的圖設置請求參數;點擊“Send”按鈕發送請求。會看到返回401認證失敗的信息;說明當前接口是被攔截的,結果如圖3-27所示:

任務實施步驟3:新建用戶登錄接口t(5)設置Httpheaders

1)首先切換到剛才登錄接口的測試頁面,復制數據中的token內容,結果如圖3-28所示:

任務實施步驟3:新建用戶登錄接口t

2)回到登錄限制接口“/auth”的測試界面,打開PostMan請求地址欄下方的“Headers”欄,在Key欄下面添加“Authorization”一項,并在對應的Value位置,填入剛才復制的token字符串。點擊“Send”按鈕,發現請求返回值內容變成了200請求成功,說明token認證功能實現完畢,結果如圖3-29所示::

知識小結【對應證書技能】

SpringSecurity致力于為Java應用程序提供身份驗證和授權,在本任務中,通過SpringSecurity實現接口的權限配置,實現自定義的登錄邏輯控制。與之前的WEB項目不同的是,在本項目中使用的是基于JWT的認證方式,基于Spring的過濾器,還有JWT框架,將認證信息保存在token中,在請求時通過過濾器將token轉換成對應的認證信息。通過本任務的學習,理解SpringSecurity加上JWT實現API的token認證思路;掌握使用過濾器處理請求;掌握在SpringBoot項目中配置數據庫連接池。本任務知識技能點與等級證書對應關系見表3-29:

知識小結謝謝您的觀看!

任務四

實現用戶管理模塊HTTPAPI04

任務描述本任務將完成用戶管理模塊,包含用戶的添加、刪除、修改、查詢功能;管理員通過賬號密碼生成具有管理員權限的token后,能夠根據用戶信息中的用戶ID對用戶信息進行新增、刪除和修改,并通過接口分頁獲取用戶信息。在本任務中,將學習如何設計API接口。

知識準備1.MyBatis框架:見項目22.Mybatis常用注解(1)@Mapper注解添加了@Mapper注解之后,這個接口在編譯時會生成相應的實現類。需要注意的是:這個接口中不可以定義同名的方法,因為會生成相同的id;也就是說這個接口是不支持重載的。(2)@Insert注解插入sql,和xml<insert>sql語法完全一樣。每個注解分別代表將會被執行的SQL語句。它們用字符串數組(或單個字符串)作為參數。如果傳遞的是字符串數組,字符串數組會被連接成單個完整的字符串,每個字符串之間加入一個空格。這有效地避免了用Java代碼構建SQL語句時產生的“丟失空格”問題。當然,你也可以提前手動連接好字符串。屬性:value,指定用來組成單個SQL語句的字符串數組。

知識準備(3)@Delete注解刪除sql,和xml<delete>sql語法完全一樣(4)@Update注解更新sql,和xml<update>sql語法完全一樣(5)@Select注解查詢sql,和xml<select>sql語法完全一樣

知識準備(6)@Param注解如果你的映射器的方法需要多個參數,這個注解可以被應用于映射器的方法參數來給每個參數一個名字。否則,多參數將會以它們的順序位置來被命名(不包括任何RowBounds參數)比如。#{param1},#{param2}等,這是默認的。使用@Param(“person”),參數應該被命名為#{person}。(7)@Options注解這個注解提供訪問交換和配置選項的寬廣范圍,它們通常在映射語句上作為屬性出現。而不是將每條語句注解變復雜,Options注解提供連貫清晰的方式來訪問它們。

知識準備

任務實施步驟1:新建用戶Mapper接口t在項目目錄mapper包下,新建UserInfoMapper類,結果如圖3-30所示:

任務實施步驟1:新建用戶Mapper接口t1.在UserInfoMapper類中添加下面的代碼:@MapperpublicinterfaceUserInfoMapper{

@Select("selectuserId,userAccount,userPass,locked,roleId,roleName,faceimgfromuserinfo,roleinfowhereuserinfo.role=roleinfo.roleIdorderbyuserId") publicList<UserInfo>getAllUser();

@Insert("insertintouserinfo(userAccount,userPass,role,faceImg)values(#{info.userAccount},#{info.userPass},#{info.roleId},#{info.faceimg})") @Options(useGeneratedKeys=true,keyProperty="info.userId") publicIntegeraddUser(@Param("info")UserInfouser);

@Select("selectuserId,userAccount,userPass,locked,roleId,roleName,faceimgfromuserinfo,roleinfowhereuserinfo.role=roleinfo.roleIdorderbyuserIdlimit#{first},#{max}") publicList<UserInfo>getUserByPage(@Param("first")intfirst,@Param("max")intmax); @Select("selectcount(*)fromuserinfo") publicLonggetMaxPage();

@Delete("deletefromuserinfowhereuserId=#{userId}") publicvoiddeleteUser(@Param("userId")IntegeruserId);

任務實施步驟1:新建用戶Mapper接口t@Update("updateuserinfosetuserPass=#{info.userPass},faceimg=#{info.faceimg}whereuserId=#{info.userId}") publicvoidmodify(@Param("info")UserInfoinfo); @Update("updateuserinfosetuserPass=#{info.userPass},faceimg=#{info.faceimg},role=#{info.roleId}whereuserId=#{info.userId}") publicvoidadminModify(@Param("info")UserInfoinfo); @Select("selectuserId,userAccount,userPass,locked,roleId,roleName,faceimgfromuserinfo,roleinfowhereuserinfo.role=roleinfo.roleIdanduserId=#{userId}") publicUserInfogetUserById(@Param("userId")IntegeruserId); @Select("selectuserId,userAccount,userPass,locked,roleId,roleNamefromuserinfo,roleinfowhereuserinfo.role=roleinfo.roleIdanduserinfo.userId=#{info.userId}") publicList<UserInfo>checkPass(@Param("info")UserInfoinfo);

@Select("selectuserId,userAccount,userPass,locked,roleId,roleName,faceimgfromuserinfo,roleinfowhereuserinfo.role=roleinfo.roleIdanduserinfo.userAccount=#{userAccount}") publicList<UserInfo>findUsersByName(@Param("userAccount")StringuserAccount);}

任務實施步驟2:新建用戶Service類t1.在項目目錄service包下,新建admin包,結果如圖3-31所示:

任務實施步驟2:新建用戶Service類t2.在項目目錄service.admin包下,新建UserService類,結果如圖3-32所示:

任務實施步驟2:新建用戶Service類t3.在UserService類中添加下面的代碼@ServicepublicclassUserService{ @AutowiredUserInfoMappermapper; publicUserInfoMappergetMapper(){ returnmapper; } publicvoidsetMapper(UserInfoMappermapper){ this.mapper=mapper; }

}

任務實施步驟2:新建用戶Service類t4.在UserService類中添加用于增刪改的方法(1)添加用戶的方法/** *添加用戶的方法 *@paraminfo需要添加的用戶信息 **/ publicvoidaddUser(UserInfoinfo){ //創建加密工具 info.setUserPass(newBCryptPasswordEncoder().encode(info.getUserPass())); //執行用戶信息插入操作 mapper.addUser(info); }

任務實施步驟2:新建用戶Service類t(2)刪除用戶的方法 /** *刪除用戶的方法 *@paramuserId待刪除用戶的Id **/ publicvoiddeleteUser(IntegeruserId){ //獲取帶有連接池的數據庫模版操作工具對象 mapper.deleteUser(userId); }

任務實施步驟2:新建用戶Service類t(3)修改用戶的方法 /** *修改用戶自身信息的方法 *@paraminfo需要修改的用戶信息,其中userId屬性指明需要修改的用戶ID,其他信息為目標值,本人修改信息只能修改密碼和頭像 **/ publicvoidmodify(UserInfoinfo){ //獲取帶有連接池的數據庫模版操作工具對象 info.setUserPass(newBCryptPasswordEncoder().encode(info.getUserPass())); //修改本人信息 mapper.modify(info); } /** *管理員修改用戶信息的方法 *@paraminfo需要修改的用戶信息,其中userId屬性指明需要修改的用戶ID,其他信息為目標值 **/ publicvoidadminModify(UserInfoinfo){ info.setUserPass(newBCryptPasswordEncoder().encode(info.getUserPass())); //修改本人信息 mapper.adminModify(info); }

任務實施步驟2:新建用戶Service類t5.在UserService類中添加用于查詢的方法(1)分頁獲取用戶數據的方法/** *分頁獲取用戶數據的方法 *@parampage要獲取數據的頁號 *@parampageSize每頁顯示的條目數 *@return當前頁的用戶數據列表 **/ publicList<UserInfo>getByPage(intpage,intpageSize){ //獲取帶有連接池的數據庫模版操作工具對象 intfirst=(1)*pageSize; //返回結果 returnmapper.getUserByPage(first,pageSize); } /** *獲取用戶信息的最大頁數 *@parampageSize每頁顯示的條目數 *@return當前數據庫中數據的最大頁數 **/ publicintgetMaxPage(intpageSize){ //獲取最大頁數信息 Longrows=mapper.getMaxPage(); //返回最大頁數 return(int)((rows.longValue()-1)/pageSize+1); }

任務實施步驟2:新建用戶Service類t(2)根據ID獲取用戶詳細信息的方法 /** *根據ID獲取用戶詳細信息的方法 *@paramuserId需要獲取詳細信息的用戶ID *@return返回查詢到的用戶詳細信息 **/ publicUserInfogetUserById(IntegeruserId){ returnmapper.getUserById(userId); } publicList<UserInfo>findUserByName(StringuserAccount){ returnmapper.findUsersByName(userAccount); }

任務實施步驟2:新建用戶Service類t6.在UserService類中添加用于檢查用戶名是否可用的方法/**

*驗證用戶用戶名密碼是否正確的方法 *@paraminfo用于判定用戶名、密碼的用戶對象

*@return用戶名、密碼是否驗證通過,true表示用戶名密碼正確、false表示用戶名或密碼錯誤 **/ publicbooleancheckPass(UserInfoinfo){

//根據給定的用戶名查詢用戶信息 List<UserInfo>userList=mapper.checkPass(info);

//判定查詢結果集合 switch(userList.size()){

//如果沒有查詢到任何數據 case0:

//返回驗證失敗 returnfalse;

//如果查詢到一條記錄則判定密碼是否一致 case1:

//構建加密對象 BCryptPasswordEncoderencoder=newBCryptPasswordEncoder();

//判定用戶給定的密碼和數據庫中的密碼是否一致 if(encoder.matches(info.getUserPass(),userList.get(0).getUserPass())){

//如果一致,則返回true returntrue;

//如果不一致 }else{

//返回用戶名、密碼不匹配 returnfalse; } }

//其他情況下返回驗證失敗 returnfalse; }

任務實施步驟3:新建用戶Controller類t1.在項目目錄api包下,新建admin包,結果如圖3-33所示

任務實施步驟3:新建用戶Controller類t2.在項目目錄api.admin包下,新建AdminUserController類,結果如圖3-34所示:

任務實施步驟3:新建用戶Controller類t3.在AdminUserController類中添加下面的代碼@PreAuthorize("hasRole('1')")@RestController@RequestMapping("/admin/user")publicclassAdminUserController{ @AutowiredUserServiceservice; publicUserServicegetService(){ returnservice; } publicvoidsetService(UserServiceservice){ this.service=service; } @RequestMapping("/adminmodifyuser") publicResultsadminModify(UserInfoinfo){if(info.getUserPass().isEmpty()){ info.setUserPass("1"); }

//執行修改操作 service.adminModify(info); returnResults.success(info); }

任務實施步驟3:新建用戶Controller類t@RequestMapping("/deleteuser") publicResultsdeleteUser(IntegeruserId){ service.deleteUser(userId); returnResults.ok(); } @GetMapping("/get") publicResults<UserInfo>getUser(IntegeruserId){ UserInfouser=service.getUserById(userId); user.setUserPass(""); returnResults.success(user); } @RequestMapping("/getuserbypage") publicPageResultsgetUserByPage(intpage){

//獲取最大頁碼數 intmaxPage=service.getMaxPage(10);

//對當前的頁碼數進行糾錯,如果小于1,則直接顯示第一頁的內容 page=page<1?1:page;

//對當前的頁碼數進行糾錯,如果大于最大頁碼,則直接顯示最后一頁的內容 page=page>maxPage?maxPage:page;

//進行分頁數據查詢 List<UserInfo>list=service.getByPage(page,10);

//過濾掉密碼信息 list=list.stream().map(item->{item.setUserPass("");returnitem;}).collect(Collectors.toList());

//嘗試將結果結構化 returnPageResults.success(list,page,maxPage); }

任務實施步驟3:新建用戶Controller類t@RequestMapping("/modifyuser") publicResultsmodifyMyInfo(UserInfoinfo){ service.modify(info); //修改信息后需要自動注銷 returnResults.success(info); } @RequestMapping("/adduser") publicResultsaddUser(UserInfoinfo){ //添加用戶 service.addUser(info); //跳轉到用戶管理界面 returnResults.success(info); } @RequestMapping("/checkuser") //獲取請求參數中的用戶名信息 publicResultscheckAddUser(@RequestParam("name")StringuserAccount){ //查詢對應用戶名的用戶信息 List<UserInfo>list=service.findUserByName(userAccount); //如果數據庫中無數據 if(list.size()==0){ //輸出可以添加標識 returnResults.ok(); //如果數據庫中有數據 }else{ //輸出不能添加標識 returnResults.failure(); } }}

拓展練習按照該任務完成菜品管理、訂單流程的接口功能

知識小結

MyBatis是優秀的優秀的持久層框架,它允許開發人員通過XML文件配置SQL語句的動態拼接,實現復雜的查詢功能。而在一些業務邏輯相對直接的查詢中,可以直接通過注解實現查詢功能,從而減少維護XML文件的工作。MyBatis提供了@Insert、@Delete、@Update、@Select等常用的注解,分別對應了增刪改查功能。本任務通過實現用戶管理接口,了解RestfulAPI接口的作用和規范,掌握RestfulAPI接口實現的能力。核心功能包括:用戶新增、用戶刪除、用戶更

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論