微信登录、商品浏览
HttpClient
介绍
- HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
- Maven坐标:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
- 核心API:HttpClient、HttpClients、CloseableHttpClient、HttpGet、HttpPost。
- 发送请求步骤:
- 创建HttpClient对象。
- 创建Http请求对象。
- 调用HttpClient的execute方法发送请求。
入门案例
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");
CloseableHttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity);
System.out.println(body);
response.close();
httpClient.close();
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");
JSONObject jsonObject = new JSONObject();
jsonObject.put("username","admin");
jsonObject.put("password", "123456");
StringEntity stringEntity = new StringEntity(jsonObject.toString());
stringEntity.setContentEncoding("utf-8");
stringEntity.setContentType("application/json");
httpPost.setEntity(stringEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity);
System.out.println(body);
response.close();
httpClient.close();
微信小程序开发
介绍
- 微信小程序是一种新的开放能力,可以在微信内被便捷地获取和传播,同时具有出色的使用体验。
- 官网:https://mp.weixin.qq.com/cgi-bin/wx?token=&lang=zh_CN
- 开放注册范围分为:个人(个人注册不能使用微信支付功能,也无法获取到用户的手机号)、企业、政府、媒体和其他组织。
- 开发支持:微信小程序提供了一系列工具帮助开发者快速接入并完成小程序开发:开发文档、开发者工具、设计指南和小程序体验DEMO。
- 接入流程:
- 注册:在微信公众平台注册小程序,完成注册后可以同步进行信息完善和开发。
- 小程序信息完善:填写小程序基本信息,包括名称、头像、介绍及服务范围等。
- 开发小程序:完成小程序开发者绑定、开发信息配置后,开发者可下载开发者工具、参考开发文档进行小程序的开发和调试。
- 提交审核和发布:完成小程序开发后,提交代码至微信团队审核,审核通过后即可发布(公测期间不能发布)。
准备工作
注册小程序
完善小程序信息
- 登录小程序后台:https://mp.weixin.qq.com/
- 完善小程序信息、小程序类目。
- 查看小程序的 AppID。
下载开发者工具
- 下载地址: https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html
- 扫描登录开发者工具。
- 创建小程序项目。
- 熟悉开发者工具布局。
- 设置不校验合法域名。
入门案例
- 操作步骤:
- 了解小程序目录结构。
- 编写小程序代码。
- 编译小程序。
了解小程序目录结构
- 小程序包含一个描述整体程序的 app 和多个描述各自页面的 page。
- 一个小程序主体部分由三个文件组成,必须放在项目的根目录,如下:
文件 |
必需 |
作用 |
app.js |
是 |
小程序逻辑 |
app.json |
是 |
小程序公共配置 |
app.wxss |
否 |
小程序公共样式表 |
文件类型 |
必需 |
作用 |
js |
是 |
页面逻辑 |
wxml |
是 |
页面结构 |
json |
否 |
页面配置 |
wxss |
否 |
页面样式表 |
编写小程序代码
<view class="container">
<view>{{msg}}</view>
<view>
<button type="default" bindtap="getUserInfo">获取用户信息</button>
<image style="width: 100px;height: 100px;" src="{{avatarUrl}}"></image>
{{nickName}}
</view>
<view>
<button type="primary" bindtap="wxlogin">微信登录</button>
授权码:{{code}}
</view>
<view>
<button type="warn" bindtap="sendRequest">发送请求</button>
响应结果:{{result}}
</view>
</view>
Page({
data:{
msg:'hello world',
avatarUrl:'',
nickName:'',
code:'',
result:''
},
getUserInfo:function(){
wx.getUserProfile({
desc: '获取用户信息',
success:(res) => {
console.log(res)
this.setData({
avatarUrl:res.userInfo.avatarUrl,
nickName:res.userInfo.nickName
})
}
})
},
wxlogin:function(){
wx.login({
success: (res) => {
console.log("授权码:"+res.code)
this.setData({
code:res.code
})
}
})
},
sendRequest:function(){
wx.request({
url: 'http://localhost:8080/user/shop/status',
method:'GET',
success:(res) => {
console.log("响应结果:" + res.data.data)
this.setData({
result:res.data.data
})
}
})
}
})
编译小程序
发布小程序
- 在微信开发者工具中点击上传。
- 在微信公众平台的版本管理中的开发版本中点击提交审核。
- 等待审核通过。
- 审核通过后,在审核版本中点击发布。
微信登录
导入小程序代码
微信登录流程
需求分析和设计
产品原型
业务规则
- 基于微信登录实现小程序的登录功能。
- 如果是新用户需要自动完成注册。
接口设计
数据库设计
字段名 |
数据类型 |
说明 |
备注 |
id |
bigint |
主键 |
自增 |
openid |
varchar(45) |
微信用户的唯一标识 |
|
name |
varchar(32) |
用户姓名 |
|
phone |
varchar(11) |
手机号 |
|
sex |
varchar(2) |
性别 |
|
id_number |
varchar(18) |
身份证号 |
|
avatar |
varchar(500) |
微信用户头像路径 |
|
create_time |
datetime |
注册时间 |
|
代码开发
配置微信登录所需配置项
sky:
wechat:
appid: appid
secret: appsecret
sky:
wechat:
appid: ${sky.wechat.appid}
secret: ${sky.wechat.secret}
配置为微信用户生成jwt令牌时使用的配置项
sky:
jwt:
user-secret-key: zgg1h
user-ttl: 7200000
user-token-name: authentication
DTO设计
@Data
public class UserLoginDTO implements Serializable {
private String code;
}
VO设计
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserLoginVO implements Serializable {
private Long id;
private String openid;
private String token;
}
根据接口定义创建UserController的login方法
@RestController
@RequestMapping("/user/user")
@Api(tags = "用户相关接口")
@Slf4j
public class UserController {
@PostMapping("/login")
@ApiOperation("微信登录")
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) {
return null;
}
}
完善UserController的login方法
@PostMapping("/login")
@ApiOperation("微信登录")
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) {
log.info("微信用户登录:{}", userLoginDTO.getCode());
UserLoginVO userLoginVO = userService.wxLogin(userLoginDTO);
return Result.success(userLoginVO);
}
创建UserService接口
public interface UserService {
UserLoginVO wxLogin(UserLoginDTO userLoginDTO);
}
创建UserServiceImpl实现类
@Service
@Slf4j
public class UserServiceImpl implements UserService {
@Override
public UserLoginVO wxLogin(UserLoginDTO userLoginDTO) {
return null;
}
}
在UserServiceImpl中创建私有方法getOpenid
@Autowired
private WeChatProperties weChatProperties;
public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
private String getOpenid(String code) {
Map<String, String> map = new HashMap<>();
map.put("appid", weChatProperties.getAppid());
map.put("secret", weChatProperties.getSecret());
map.put("js_code", code);
map.put("grant_type", "authorization_code");
String json = HttpClientUtil.doGet(WX_LOGIN, map);
JSONObject jsonObject = JSON.parseObject(json);
String openid = jsonObject.getString("openid");
return openid;
}
完善UserServiceImpl的wxLogin方法
@Autowired
private JwtProperties jwtProperties;
@Autowired
private UserMapper userMapper;
@Override
public UserLoginVO wxLogin(UserLoginDTO userLoginDTO) {
String openid = getOpenid(userLoginDTO.getCode());
if (openid == null) {
throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
}
User user = userMapper.getByOpenId(openid);
if (user == null) {
user = User.builder()
.openid(openid)
.createTime(LocalDateTime.now())
.build();
userMapper.insert(user);
}
Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.USER_ID, user.getId());
String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);
UserLoginVO userLoginVO = UserLoginVO.builder()
.id(user.getId())
.openid(user.getOpenid())
.token(token)
.build();
return userLoginVO;
}
创建UserMapper接口
@Mapper
public interface UserMapper {
@Select("select * from user where openid = #{openid}")
User getByOpenId(String openid);
void insert(User user);
}
创建UserMapper.xml映射文件
<?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="com.sky.mapper.UserMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into user (openid, name, phone, sex, id_number, avatar, create_time)
values (#{openid}, #{name}, #{phone}, #{sex}, #{idNumber}, #{avatar}, #{createTime})
</insert>
</mapper>
编写拦截器JwtTokenUserInterceptor,统一拦截用户端发送的请求并进行jwt校验
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
String token = request.getHeader(jwtProperties.getUserTokenName());
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
log.info("当前用户id:{}", userId);
BaseContext.setCurrentId(userId);
return true;
} catch (Exception ex) {
response.setStatus(401);
return false;
}
}
}
在WebMvcConfiguration配置类中注册拦截器
@Autowired
private JwtTokenUserInterceptor jwtTokenUserInterceptor;
protected void addInterceptors(InterceptorRegistry registry) {
log.info("开始注册自定义拦截器...");
registry.addInterceptor(jwtTokenAdminInterceptor)
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/employee/login");
registry.addInterceptor(jwtTokenUserInterceptor)
.addPathPatterns("/user/**")
.excludePathPatterns("/user/user/login")
.excludePathPatterns("/user/shop/status");
}
功能测试
- 可以通过接口文档进行测试,最后完成前后端联调测试即可。
导入商品浏览功能代码
需求分析和设计
产品原型
接口设计
代码导入
功能测试
- 可以通过接口文档进行测试,最后完成前后端联调测试即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了