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

提交评论