参考资料地址1:https://pan.baidu.com/s/13-a-PAQWokSLhLvNRqcPmA 提取码: 42mk
参考资料地址2:https://share.weiyun.com/aXaiIMC3 密码:q5aaj7
HarmonyOS应用分为两大类:安装的App和免安装原子化服务应用。
用户应用程序以App Pack形式发布,它包含一个或者多个HAP(Harmony Ability Package)以及描述每个HAP属性的pack.info组成。HAP是上文提到的Ability的部署包,鸿蒙的应用是围绕一个个Ability(能力/功能)组件展开的。一个HAP由代码、资源、第三方库及配置组件组成。
华为鸿蒙开发需要学习以下几种编程语言:
Java:鸿蒙系统支持使用Java语言进行应用程序开发。如果已经熟悉Java,那么可以直接使用Java进行鸿蒙应用程序的开发。
C/C++:鸿蒙系统也支持使用C/C++语言进行应用程序开发。使用C/C++语言可以更好地利用鸿蒙系统的底层特性,更好地发挥其性能和功能。
JS(JavaScript):鸿蒙系统还支持使用JavaScript语言进行应用程序开发。JavaScript是一种广泛使用的网络编程语言,适用于开发Web应用程序和构建用户界面。
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS基于TypeScript(简称TS)语言扩展而来,是TS的超集。
除了以上编程语言,还需要了解鸿蒙系统的开发特性、分布式能力、设备适配、调试和测试等方面的知识。同时,积极参与鸿蒙开发者社区,阅读官方文档、示例代码和教程,参加培训和研讨会,与其他开发者交流和分享经验也是非常有帮助的。
eTS是扩展的TS语言,而ArkTS同样是在TS语言基础上,配合ArkUI框架,扩展了声明式UI、状态管理等相应的能力,让开发者以更简洁、更自然的方式开发跨端应用。这样,我们也就清楚了华为eTS和ArKTS之间的区别关系,ArKTS就是eTS的升级版!
在配置文件中,添加JWT需要用到的密钥、过期时间和缓存过期时间。
package com.example.emos.wx.config.shiro;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@Component
@Scope("prototype")
public class OAuth2Filter extends AuthenticatingFilter {
@Autowired
private ThreadLocalToken threadLocalToken;
@Value("${emos.jwt.cache-expire}")
private int cacheExpire;
@Autowired
private JwtUtil jwtUtil;
@Autowired
private RedisTemplate redisTemplate;
/**
* 拦截请求之后,用于把令牌字符串封装成令牌对象
*/
@Override
protected AuthenticationToken createToken(ServletRequest request,
ServletResponse response) throws Exception {
//获取请求token
String token = getRequestToken((HttpServletRequest) request);
if (StringUtils.isBlank(token)) {
return null;
}
return new OAuth2Token(token);
}
/**
* 拦截请求,判断请求是否需要被Shiro处理
*/
@Override
protected boolean isAccessAllowed(ServletRequest request,
ServletResponse response, Object mappedValue) {
HttpServletRequest req = (HttpServletRequest) request;
// Ajax提交application/json数据的时候,会先发出Options请求
// 这里要放行Options请求,不需要Shiro处理
if (req.getMethod().equals(RequestMethod.OPTIONS.name())) {
return true;
}
// 除了Options请求之外,所有请求都要被Shiro处理
return false;
}
/**
* 该方法用于处理所有应该被Shiro处理的请求
*/
@Override
protected boolean onAccessDenied(ServletRequest request,
ServletResponse response) throws Exception {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
resp.setHeader("Content-Type", "text/html;charset=UTF-8");
//允许跨域请求
resp.setHeader("Access-Control-Allow-Credentials", "true");
resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
threadLocalToken.clear();
//获取请求token,如果token不存在,直接返回401
String token = getRequestToken((HttpServletRequest) request);
if (StringUtils.isBlank(token)) {
resp.setStatus(HttpStatus.SC_UNAUTHORIZED);
resp.getWriter().print("无效的令牌");
return false;
}
try {
jwtUtil.verifierToken(token); //检查令牌是否过期
} catch (TokenExpiredException e) {
//客户端令牌过期,查询Redis中是否存在令牌,如果存在令牌就重新生成一个令牌给客户端
if (redisTemplate.hasKey(token)) {
redisTemplate.delete(token);//删除令牌
int userId = jwtUtil.getUserId(token);
token = jwtUtil.createToken(userId); //生成新的令牌
//把新的令牌保存到Redis中
redisTemplate.opsForValue().set(token, userId + "", cacheExpire, TimeUnit.DAYS);
//把新令牌绑定到线程
threadLocalToken.setToken(token);
} else {
//如果Redis不存在令牌,让用户重新登录
resp.setStatus(HttpStatus.SC_UNAUTHORIZED);
resp.getWriter().print("令牌已经过期");
return false;
}
} catch (JWTDecodeException e) {
resp.setStatus(HttpStatus.SC_UNAUTHORIZED);
resp.getWriter().print("无效的令牌");
return false;
}
boolean bool = executeLogin(request, response);
return bool;
}
@Override
protected boolean onLoginFailure(AuthenticationToken token,
AuthenticationException e, ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
resp.setStatus(HttpStatus.SC_UNAUTHORIZED);
resp.setContentType("application/json;charset=utf-8");
resp.setHeader("Access-Control-Allow-Credentials", "true");
resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
try {
resp.getWriter().print(e.getMessage());
} catch (IOException exception) {
}
return false;
}
/**
* 获取请求头里面的token
*/
private String getRequestToken(HttpServletRequest httpRequest) {
//从header中获取token
String token = httpRequest.getHeader("token");
//如果header中不存在token,则从参数中获取token
if (StringUtils.isBlank(token)) {
token = httpRequest.getParameter("token");
}
return token;
}
@Override
public void doFilterInternal(ServletRequest request,
ServletResponse response, FilterChain chain) throws ServletException, IOException {
super.doFilterInternal(request, response, chain);
}
}
我们在写OAuth2Filter的时候,把更新后的令牌写到ThreadLocalToken里面的ThreadLocal。那么这个小节,我们要创建AOP切面类,拦截所有Web方法的返回值,在返回的R对象中添加更新后的令牌。
在com.example.emos.wx.aop中创建TokenAspect类。
package com.example.emos.wx.aop;
import com.example.emos.wx.common.util.R;
import com.example.emos.wx.config.shiro.ThreadLocalToken;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class TokenAspect {
@Autowired
private ThreadLocalToken threadLocalToken;
@Pointcut("execution(public * com.example.emos.wx.controller.*.*(..)))")
public void aspect() {
}
@Around("aspect()")
public Object around(ProceedingJoinPoint point) throws Throwable {
R r = (R) point.proceed(); //方法执行结果
String token = threadLocalToken.getToken();
//如果ThreadLocal中存在Token,说明是更新的Token
if (token != null) {
r.put("token", token); //往响应中放置Token
threadLocalToken.clear();
}
return r;
}
}
首先我们可以从微信APP上面获得用户临时授权字符串(Code),然后把这个字符串传递给后端Java系统,让Java系统拿着AppId、密钥和Code,提交给微信平台换取OpenId
String url = "https://api.weixin.qq.com/sns/jscode2session";
HashMap map = new HashMap();
map.put("appid", appId);
map.put("secret", appSecret);
map.put("js_code", code);
map.put("grant_type", "authorization_code");
String response = HttpUtil.post(url, map);
JSONObject json = JSONUtil.parseObj(response);
String openId = json.getStr("openid");
在UserServiceImpl.java中实现抽象方法
@Override
public Integer login(String code) {
String openId = getOpenId(code);
Integer id = userDao.searchIdByOpenId(openId);
if (id == null) {
throw new EmosException("帐户不存在");
}
//TODO 从消息队列中接收消息,转移到消息表
return id;
}
创建checkin.vue页面,然后编写页面内容
<camera device-position="front" flash="off" class="camera" @error="error" v-if="showCamera"></camera>
<image mode="widthFix" class="image" :src="photoPath" v-if="showImage"></image>
<view class="operate-container">
<button type="primary" class="btn" @tap="clickBtn" :disabled="!canCheckin">{{ btnText }}</button>
<button type="warn" class="btn" @tap="afresh" :disabled="!canCheckin">重拍</button>
</view>
<view class="notice-container">
<text class="notice">注意事项</text>
<text class="desc">拍照签到的时候,必须要拍摄自己的正面照片,侧面照片会导致无法识别。另外,拍照的时候不要戴墨镜或者帽子,避免影响拍照签到的准确度。</text>
</view>
编写checkin.less文件,声明CSS样式
@import url("../../style.less");
.camera,.image{
width: 100%;
height: 400px;
}
.operate-container{
display: flex;
justify-content: center;
margin-top: 50rpx;
.btn{
width: 40%;
margin: 0;
&:first-child{
margin-right: 30rpx;
}
}
}
.notice-container{
padding: 40rpx 60rpx;
.notice{
font-size: 40rpx;
color: @font-color;
font-weight: bold;
display: block;
margin-bottom: 15rpx;
}
.desc{
display: block;
font-size: 32rpx;
color: @desc-color;
line-height: 1.6;
}
}
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传