前言

最近在使用uniapp开发安卓应用,我本人并没有这方面的经验,在第一次前台发送请求获取后台存在session里的数据居然为null,而我用apifox调用的时候是正常,经高人指点才知道h5里请求是自动传递cookie信息而安卓是不传递的。

解决思路

使用jwt将生成的token和结果一起返回给前端,前端拿到后缓存到本地,后面每次请求都在header里传递这个token。

开发环境

jdk8,maven3.3.9,solon1.10.7,uniapp

代码示例

后台

public ApiResult login(Users users) {
        if (StrUtil.isEmpty(users.getUsername()) || StrUtil.isEmpty(users.getPassword())) {
            return ApiResult.error("请填写用户名或密码");
        }
        QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", users.getUsername());
        Users user1 = usersDao.selectOne(queryWrapper);
        if (user1 == null) return ApiResult.error("不存在此用户");
        boolean checkFlag = BCrypt.checkpw(users.getPassword(), user1.getPassword());
        if (!checkFlag) {
            return ApiResult.error("用户名密码不正确");
        }

        try {
            //session缓存当前用户信息
            Context ctx = Context.current();
            ctx.sessionSet("loginUserId", user1.getId());

            Map<String, Object> data = new LinkedHashMap<>();
            data.put("TOKEN", ctx.sessionState().sessionToken());
            data.put("users", user1);
            return ApiResult.success(data);
        } catch (Exception e) {
            log.error("【登陆】接口出错: {}", e.getMessage());
            throw new ApiException("登陆异常");
        }
    }

前端处理:

  1. 通过请求获取到token
			formSubmit(e) {
				let data = {
					username: e.detail.value.username,
					password: e.detail.value.password
				}
				let opts = {
					url: 'users/login',
					method: 'post',
					data: data
				}
				request.httpRequest(opts).then(res => {

					if (res) {
						uni.setStorage({
							key: 'userInfo',
							data: res.users
						});
						uni.setStorage({
							key: 'TOKEN',
							data: res.TOKEN
						});

						uni.switchTab({
							url: '/pages/chatGroup/index'
						});
					} else {
						console.log('数据请求错误~');
					}
				});
			}

2.每次请求都在头里携带token

let baseUrl;

// 不带token请求
const httpRequest = (opts, data) => {
	if (opts.type == 2) {
		baseUrl = '';
	} else {
		baseUrl = 'http://localhost:8080/api/';
	}
	uni.onNetworkStatusChange(function(res) {
		if (!res.isConnected) {
			uni.showToast({
				title: '网络连接不可用!',
				icon: 'none'
			});
		}
		return false
	});

	let httpDefaultOpts = {
		url: baseUrl + opts.url,
		data: opts.data,
		method: opts.method,
		header: opts.method == 'get' ? {
			'X-Requested-With': 'XMLHttpRequest',
			"Accept": "application/json",
			"Access-Control-Allow-Headers": 'TOKEN',
			"TOKEN": uni.getStorageSync('TOKEN'),// 获取token
			"Content-Type": "application/json; charset=UTF-8"
		} : {
			'X-Requested-With': 'XMLHttpRequest',
			"Access-Control-Allow-Headers": 'TOKEN',
			'Content-Type': 'application/json; charset=UTF-8'
		},
		dataType: 'json',
	}
	let promise = new Promise(function(resolve, reject) {
		uni.request(httpDefaultOpts).then(
			(res) => interceptorsRes(res, resolve, reject)
		).catch(
			(response) => {
				reject(response)
			}
		)
	})
	return promise
};

这个问题困扰了我很久,说实话uniapp官方群真的没人解答问题,反倒是solon的作者在群里热心的帮助我解决问题。

一个更现代感的应用开发框架:更快、更小、更自由。
启动快 5 ~ 10 倍;qps 高 2~ 3 倍;运行时内存节省 1/3 ~ 1/2;打包可以缩到 1/2 ~ 1/10;同时支持 jdk8, jdk11, jdk17, jdk19
开发形式与springboot高度相似,可以最小代价转换~

@Controller
public class App {
    public static void main(String[] args) {
        Solon.start(App.class, args, app -> {
            //手写模式
            app.get("/hello1", ctx -> ctx.output("Hello world!"));
        });
    }

    //注解模式
    @Get
    @Socket
    @Mapping("/hello2")
    public String hello2(@Param(defaultValue = "world") String name) {
        return String.format("Hello %s!", name);
    }
}

solon
gitee地址:https://gitee.com/noear/solon

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐