一、VUE框架qs框架
formdata数据格式转换
npm i qs -S
添加(main.js)
import qs from 'qs';
Vue.prototype.qs=qs;
使用:let formData= this.qs.stringify(this.ruleForm);;主要功能代替JSON对象转换为fromdata数据往后台传输,后台不用添加@RequestBody
二、jackson框架
主要用于序列化和反序列化(SpringMVC自动加载)
使用:#jackson:JSON中有null值时不显示空值
jackson: default-property-inclusion: non_null
三、在线文档 Knife4j
Knife4j是一款基于Swagger 2的在线API文档框架。当前建议使用的Knife4j版本,只适用于Spring Boot 2.6以下版本,不含Spring Boot 2.6, 在主配置文件(application.yml)中开启Knife4j的增强模式, 添加Knife4j的配置类,进行必要的配置, 必须指定控制器的包。
添加依赖
<!-- Knife4j Spring Boot:在线API -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>
主配置文件
在`application.yml`中添加配置:
```yaml
knife4j:
enable: true
添加配置类config
package cn.tedu.csmall.passport.config;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
/**
* Knife4j配置类
*
* @author java@tedu.cn
* @version 0.0.1
*/
@Slf4j
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfiguration {
/**
* 【重要】指定Controller包路径
*/
private String basePackage = "cn.tedu.csmall.passport.controller";
/**
* 分组名称
*/
private String groupName = "passport";
/**
* 主机名
*/
private String host = "http://xxxxx.cn";
/**
* 标题
*/
private String title = "酷鲨商城在线API文档--管理员管理";
/**
* 简介
*/
private String description = "酷鲨商城在线API文档--管理员管理";
/**
* 服务条款URL
*/
private String termsOfServiceUrl = "http://www.apache.org/licenses/LICENSE-2.0";
/**
* 联系人
*/
private String contactName = "wk";
/**
* 联系网址
*/
private String contactUrl = "http://xxxxx.cn";
/**
* 联系邮箱
*/
private String contactEmail = "java@xxxx.cn";
/**
* 版本号
*/
private String version = "1.0.0";
@Autowired
private OpenApiExtensionResolver openApiExtensionResolver;
public Knife4jConfiguration() {
log.debug("加载配置类:Knife4jConfiguration");
}
@Bean
public Docket docket() {
String groupName = "1.0.0";
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.host(host)
.apiInfo(apiInfo())
.groupName(groupName)
.select()
.apis(RequestHandlerSelectors.basePackage(basePackage))
.paths(PathSelectors.any())
.build()
.extensions(openApiExtensionResolver.buildExtensions(groupName));
return docket;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(title)
.description(description)
.termsOfServiceUrl(termsOfServiceUrl)
.contact(new Contact(contactName, contactUrl, contactEmail))
.version(version)
.build();
}
}
在Controller层中的应用 :
@Api(tags = "1管理员管理模块") :配置模块的名称
@ApiOperation("添加管理员"):配置业务的名称
@ApiOperationSupport(order = 100):给业务添加编号
@Api(tags = "1管理员管理模块")
@RestController
@RequestMapping("/admins")
public class AdminController {
@Autowired
IAdminService iAdminService;
@ApiOperation("添加管理员")
@ApiOperationSupport(order = 100)
@PostMapping("/add-new")
public JSONResult addNew(AdminAddNewDTO adminAddNewDTO) {
iAdminService.addNew(adminAddNewDTO);
return JSONResult.ok();
}
}
完成后,启动项目,通过 http://localhost:9081/doc.html 即可访问在线API文档!
四、spring-validation框架(检查封装在pojo中的对象)
<!--检查格式-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
public class AlbumAddNewDTO {
@NotNull(message = "添加失败,数据不能为空")
private String name;
private String description;
private Integer sort;
}
在请求前添加@Valid注解,用于判断字符是否符合规范
@ApiOperation("添加相册")
@ApiOperationSupport(order = 400)
//在类上添加ResquestMaping 会将路径拼接起来全名("/albim/add-new")
@PostMapping(value = "/add-new")
public JSONResult addNew(@Valid AlbumAddNewDTO albumAddNewDTO) {
albumService.addNew(albumAddNewDTO);
log.trace(albumAddNewDTO.toString());
return JSONResult.ok();
}
**配置快速失败,遇到一个不符合规范的立马停止检查
@Configuration
@Slf4j
public class ValidationConfiguration {
public ValidationConfiguration() {
System.out.println("ValidationConfiguration配置类开始启动");
}
//快速失败,遇到错误立马输出并停止不载向后检查
@Bean
public javax.validation.Validator validator() {
return Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true)
.buildValidatorFactory()
.getValidator();
}
}
五、安全框架Spring-Security
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency
添加配置类
@Slf4j
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean //https://gitee.com/chengheng2022/jsd2206-csmall-passport-teacher.git
public PasswordEncoder passwordEncoder() {
log.debug("创建@Bean方法定义的对象:PasswordEncoder");
// return new BCryptPasswordEncoder();
return NoOpPasswordEncoder.getInstance(); // 无操作的密码编码器,即:不会执行加密处理
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 【配置白名单】
// 在配置路径时,星号是通配符
// 1个星号只能匹配任何文件夹或文件的名称,但不能跨多个层级
// 例如:/*/test.js,可以匹配到 /a/test.js 和 /b/test.js,但不可以匹配到 /a/b/test.js
// 2个连续的星号可以匹配若干个文件夹的层级
// 例如:/**/test.js,可以匹配 /a/test.js 和 /b/test.js 和 /a/b/test.js
String[] urls = {
"/doc.html",
"/**/*.js",
"/**/*.css",
"/swagger-resources",
"/v2/api-docs"
};
http.csrf().disable(); // 禁用CSRF(防止伪造的跨域攻击)
http.authorizeRequests() // 对请求执行认证与授权
.antMatchers(urls) // 匹配某些请求路径
.permitAll() // (对此前匹配的请求路径)不需要通过认证即允许访问
.anyRequest() // 除以上配置过的请求路径以外的所有请求路径
.authenticated(); // 要求是已经通过认证的
http.formLogin(); // 开启表单验证,即视为未通过认证时,将重定向到登录表单,如果无此配置,则直接响应403
}
}
通过Security框架对明文加密
// TODO 从Admin对象获取密码,加密,并将密文封装回Admin中
String rowPassword = a.getPassword();
String encode = new BCryptPasswordEncoder().encode(rowPassword);
//passwordEncoder.encode(rowPassword);
a.setPassword(encode);
log.trace("原文:" + rowPassword, "密文:" + encode);
六、JWT认证
<!-- JWT生成解析 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
生成令牌
Map<String, Object> claims = new HashMap<>();
claims.put("id", 9527);
claims.put("username", "liucangsong");
claims.put("email", "liucangsong@163.com");
Date date = new Date(System.currentTimeMillis() + 10 * 60 * 1000);
System.out.println("过期时间" + date);
String secretKey = "kns439a}fdLK34jsmfd{MF5-8DJSsLKhJNFDSjn";
String jwt = Jwts.builder()
//header 加密方式和类型
.setHeaderParam("alg", "HS256")
.setHeaderParam("typ", "JWT")
//payload 携带参数和过期时间
.setClaims(claims)
.setExpiration(date)
//Signature 加密方式和盐值
.signWith(SignatureAlgorithm.HS256, secretKey)
//整合
.compact();
System.out.println(jwt);
解析令牌
String jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6OTUyNywiZXhwIjoxNjY1NTc4ODc1LCJlbWFpbCI6ImxpdWNhbmdzb25nQDE2My5jb20iLCJ1c2VybmFtZSI6ImxpdWNhbmdzb25nIn0.FrFo3EXmg9bzCmh6YhlBFAGkOUOS8plv5K7PmncW7FU";
String secretKey = "kns439a}fdLK34jsmfd{MF5-8DJSsLKhJNFDSjn";
Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();
Long id = claims.get("id",Long.class);
String username = claims.get("username", String.class);
String email = claims.get("email", String.class);
System.out.println("id: " + id + "," + username + "," + email);
七、fastjson转换对象为Json 数据
<!-- fastjson:实现对象与JSON的相互转换 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
String jsonResultString = JSON.toJSONString(jsonResult);
toJSONString(需要被转换的内容)
八、Aop面向切面
实现获取任务运行时间
导入依赖
<!--Spring - AOP引入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
在类上添加@Aspect
@Slf4j
@Component
@Aspect
public class TinerAspect {
public TinerAspect() {
log.trace("Aop切面类开始执行");
}
// 关于ProceedingJoinPoint
// 必须调用proceed()方法,表示执行表达式匹配到的方法
// 调用proceed()方法必须获取返回值,且作为当前方法的返回值,表示返回表达式匹配的方法的返回值
// 调用proceed()方法时的异常必须抛出,不可以使用try...catch进行捕获并处理
// ---------------------------------------------------
// 关于execution表达式:用于匹配在何时执行AOP相关代码
// 表达式中的星号:匹配任意内容,只能匹配1次
// 表达式中的2个连续的小数点:匹配任意内容,可以匹配0~n次,只能用于包名和参数列表部分
// 表达式中的包是根包,会自动包含其子孙包中的匹配项
@Around("execution(* cn.tude.csmall.product.service.*.*(..))")
// ↑ 无论方法的返回值类型是什么
// ↑ 无论是哪个类
// ↑ 无论是哪个方法
// ↑ 2个小数点表示任何参数列表
public Object xx(ProceedingJoinPoint pjp) throws Throwable {
log.trace("执行TimerAspe类中的方法");
long start = System.currentTimeMillis();
Object proceed = pjp.proceed();//执行连接点方法
long end = System.currentTimeMillis();
log.debug("【{}】类型的对象调用了【{}】方法,方法的参数值为【{}】",
pjp.getTarget().getClass().getName(),
pjp.getSignature().getName(),
pjp.getArgs());
log.trace("执行耗时:{} 毫秒", (end - start));
return proceed;//执行返回请求结果,没有的话请求只有传没有取
}
}
九、Dubbo框架
该框架将方法接口的调用范围从Spring容器提升到全分布服务器
<!-- Dubbo 在SpringCloud中使用的依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
配置文件
dubbo:
protocol:
# port设置为-1 表示当前dubbo框架使用的端口自动寻找
# 使用端口的规则是从20880开始寻找可用端口,如果当前端口号占用,就继续加1来使用,直到找到可用的为止
port: -1
# 设置连接的名称,一般固定为dubbo即可
name: dubbo
registry:
# 指定当前Dubbo服务注册中心的类型和位置
address: nacos://localhost:8848
启动类的配置,生产者需要添加@EnableDubbo注解
//此服务为生产者,添加了此注解才能被注册到Nacos中
@EnableDubbo
@SpringBootApplication
public class CsmallStockWebapiApplication {
public static void main(String[] args) {
SpringApplication.run(CsmallStockWebapiApplication.class, args);
}
}
微服务方法的调用,@DubboService注解会将此类下的方法注册到Nacos中共享到全部服务器
//以类为单位共享给Nacos,其他服务可以调用这个类下的方法
@DubboService
@Service
@Slf4j
public class StockServiceImpl implements IStockService {
调用注册过的方法
@DubboReference
private IStockService iStockService;
Mybatis框架
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
server.port=9082
spring.datasource.url=jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
#mybatis
mybatis.mapper-locations=mapper/*.xml
@Configuration
@MapperScan("cn.tedu.csmall.passport.mapper")
public class MybatisConfiguration {
public MybatisConfiguration() {
System.out.println("配置类启动成功");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.csmall.passport.mapper.RoleMapper">
<!-- List<RoleListItemVO> list(); -->
<select id="list" resultMap="ListResultMap">
SELECT
<include refid="ListQueryFields"/>
FROM
ams_role
ORDER BY
sort DESC, id
</select>
<sql id="ListQueryFields">
<if test="true">
id, name, description, sort
</if>
</sql>
<resultMap id="ListResultMap" type="cn.tedu.csmall.passport.pojo.vo.RoleListItemVO">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="description" property="description"/>
<result column="sort" property="sort"/>
</resultMap>
</mapper>