@Data // 自动生成getter和setter方法
@Builder // 自动生成Builder模式的方法
public class MongoResultSet<T> {
// 总数
Long total;
// 结果列表
List<T> result;
}
{
code:0,
msg:"success",
data:数据
}
封装一个类,例如:
@Data
public class Result implements Serializable {
private Integer code;
private String msg;
private Object data;
private Result(){}
public static Result success(Object data){
Result result = new Result();
result.setCode(ResultCode.SUCCESS.code());
result.setMsg(ResultCode.SUCCESS.msg());
result.setData(data);
return result;
}
public static Result failure(String message){
Result result = new Result();
result.setCode(ResultCode.FAILURE.code());
result.setMsg(message);
result.setData(null);
return result;
}
}
还会写一个枚举类作为code和msg
public enum ResultCode {
SUCCESS(0,"成功"),
FAILURE(-1,"失败");
private Integer code;
private String msg;
ResultCode(Integer code, String msg){
this.code = code;
this.msg = msg;
}
public Integer code(){
return this.code;
}
public String msg(){
return this.msg;
}
}
利用springboot的全局响应拦截
创建一个类,打上注解@ControllerAdvice,再实现ResponseBodyAdvice<Object>接口
必须在里面重写两个方法,一个boolean supports()方法,一个Object beforeBodyWrite()方法
beforeBodyWrite就可以重写响应结果,而supports方法返回的boolean值决定是否执行beforeBodyWrite方法
如果一味的将supports方法返回true,那么说明每一个响应都会返回统一的格式,但如果我有一个请求想返回一个文件流呢
基于以上想法,暂且想到的解决思路:
自定义一个注解,将注解打在请求的方法上,创建一个全局拦截器,拦截请求,如果请求的方法上发现有我们自定义的注解,那么我们在request请求域中添加一个属性(标识),然后再全局响应拦截中的supports()方法中,判断请求域中是否有之前添加的标识,如果有,则返回true,没有就返回false。返回true就表示执行beforeBodyWrite()方法,就可以重写响应结果
实战:
1、创建一个自定义注解:
@Target(ElementType.METHOD) // 该注解可以使用在方法上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResultApi {
}
2、创建一个拦截器
@Component
public class ResultInterceptor implements HandlerInterceptor {
// 标记
public static final String RESPONSE_RESULT = "response_flag";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if(handler instanceof HandlerMethod){
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取方法名
Method method = handlerMethod.getMethod();
// 如果方法被ResultApi注解修饰
if(method.isAnnotationPresent(ResultApi.class)){
request.setAttribute(RESPONSE_RESULT,method.getAnnotation(ResultApi.class));
}
}
return true;
}
}
3、使拦截器生效,并拦截所有路径
@Configuration
public class MyWebConfig implements WebMvcConfigurer {
/**
* 拦截全部
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new ResultInterceptor()).addPathPatterns("/**");
}
}
常用注解:
| 注解 | 作用 | 使用位置 |
|---|---|---|
| @Api | 表示对类的说明常用参数 | 类上面 |
| @ApiOperation | 说明方法的用途、作用 | 方法上面 |
| @ApiModel | 表示一个返回响应数据的信息 | 响应类 |
| @ApiModelProperty | 描述响应类的属性 | 属性 |
| @ApiIgnore | 忽略某个字段使之不显示在文档中 | 属性 |
1、前后端分离中,后端都会统一返回类似这样的结构
{
code:0,
msg:‘success’,
data:[ {id:1,name:'aa',age:18} ]
}
如果每次都自己去new,或者调用静态方法Result.success()。是不是太麻烦了,于是写了一个自定义注解,只要在方法上添加注解,即可自动返回上述结构
类似这样@ResultApi
@ResultApi
@ApiOperation("查询底部设置号码列表")
@PreAuthorize("hasAuthority('sys:foot:pageList')")
@PostMapping("/pageList")
public PageVo<SysPhone> pageList(@RequestBody SysPhone sysPhone){
return sysFootService.pageList(sysPhone);
}
oauth,单点登录 主攻java和前端了 python 视频服务,MinIO
微信扫码登录
安全框架SpringSecurity
中英文切换导入
logo图切换svg,保证不失真效果
使用mixin混入达到配置项fullpage的复用效果
微信扫码登录
1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;
3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
一共是两种方式,但两种方式的原理基本相同,第一种是在原来的网页打开一个新的标签页,标签页中涵盖微信提供的二维码。
第一种方式需要后端提供一个微信二维码的地址,返回给前端,前端调用window.open打开一个新的标签页
第二种是在自己的网页中内嵌微信提供的二维码。将使用微信提供的js库,自动获取微信的扫描二维码
将页面引入 res.wx.qq.com/connect/zh_… 这个js,由微信官方提供
在需要使用微信登录的地方实例以下JS对象:
var obj = new WxLogin({
self_redirect:true,
id:"login_container",
appid: "",
scope: "",
redirect_uri: "",
state: "",
style: "",
href: ""
});
// 举个例子
var obj = new WxLogin({
self_redirect:false,
id:"wxPng",
appid: "xx",
scope: "snsapi_login",
redirect_uri: encodeURIComponent("http://ip.cn"),
state: "",
style: "black",
href: "data:text/css;base64,LmltcG93ZXJCb3ggLnRpdGxlewogIGRpc3BsYXk6IG5vbmU7Cn0KCi5pbXBvd2VyQm94IC53YWl0aW5nIC5pbmZvIHsKICBkaXNwbGF5OiBub25lOwp9CgouaW1wb3dlckJveCAud2FpdGluZyAud3JwX2NvZGUgewogIG1hcmdpbjogMCBhdXRvOyAKICB3aWR0aDogMjAwcHg7CiAgYm9yZGVyOiBub25lOwp9CgouaW1wb3dlckJveCAud2FpdGluZyAucXJjb2RlIHsKICBib3JkZXI6IDA7CiAgd2lkdGg6IDEwMCU7Cn0="
});
参数 是否必须 说明
self_redirect 否 true:手机点击确认登录后可以在 iframe 内跳转到 redirect_uri,false:手机点击确认登录后可以在 top window 跳转到 redirect_uri。默认为 false。
id 是 第三方页面显示二维码的容器id
appid 是 应用唯一标识,在微信开放平台提交应用审核通过后获得
scope 是 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可 redirect_uri 是 重定向地址,需要进行UrlEncode
state 否 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
style 否 提供"black"、"white"可选,默认为黑色文字描述。详见文档底部FAQ
href 否 自定义样式链接,第三方可根据实际需求覆盖默认样式。
我们这里需要自定义css,可以使用href属性字段,将css发布到公网上,或者将css写好之后,进行base编码之后。直接赋值。例如:
// 自定义样式
.impowerBox .title {
display: none;
}
.impowerBox .status.status_browser {
display: none;
}
.impowerBox .qrcode {
border: none;
width: 200px;
height: 200px;
}
.impowerBox .status{
display: none
}
进行base64编码:
href必须使用 text/css模式,生成的base64添加到'data:text/css;base64,'后面就可以了
@Slf4j
@Component
public class InitDataSource {
@Autowired
private InitMapper initMapper;
@PostConstruct
public void init(){
log.info("初始化hikari连接池");
// 初始化hikari连接池
initMapper.Init();
}
}
在用户扫完码确认授权后,页面会跳转到你之前设置的回调地址,如果在本地开发的话 ,可以改host文件,将127.0.0.1指向bugtracker.itsource.cn地址
他会携带一个code和state参数,这个时候你在这个页面初始化时,检测地址url是否有code和state参数,如果有,那就往后台发送请求,后台会做两件事
1、通过code参数加上AppID和AppSecret等,通过API换取access_token;
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
返回结果:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
openid就是微信用户的唯一标识
通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
PV和UV
pv:pageViews,页面访问次数,同一个电脑访问次数可以叠加
uv:uniqueVisitor,独立访问客户,同一个电脑访问次数不算叠加
加群联系作者vx:xiaoda0423