课外开发苍穹外卖苍穹外卖学习笔记(六)
Jie一. HttpClient
介绍
HttpClient是Apache Jakarta Common下的子项目,可以用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。
1 2 3 4 5
| <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency>
|
该项目导入了阿里的sdk,传递依赖
核心API:
- HttpClient
- HttpClients
- CloseableHttpClient
- HttpGet
- HttpPost
发生请求步骤:
- 创建HttpClient对象
- 创建Http请求对象
- 调用HttpClient的execute方法发送请求
入门案例
HttpClientTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| package com.sky.test;
import com.alibaba.fastjson.JSONObject; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest public class HttpClientTest {
@Test public void testGet() { CloseableHttpClient aDefault = HttpClients.createDefault(); HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status"); try { CloseableHttpResponse execute = aDefault.execute(httpGet); int statusCode = execute.getStatusLine().getStatusCode(); System.out.println("状态码:" + statusCode); HttpEntity entity = execute.getEntity(); String string = EntityUtils.toString(entity); System.out.println("响应数据:" + string);
execute.close(); aDefault.close(); } catch (Exception e) { e.printStackTrace(); } }
@Test public void testPost() throws Exception { CloseableHttpClient aDefault = 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 entity = new StringEntity(jsonObject.toString()); entity.setContentEncoding("UTF-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); CloseableHttpResponse execute = aDefault.execute(httpPost); int statusCode = execute.getStatusLine().getStatusCode(); System.out.println("状态码:" + statusCode); HttpEntity entity1 = execute.getEntity(); String string = EntityUtils.toString(entity1); System.out.println("响应数据:" + string);
execute.close(); aDefault.close(); } }
|
二. 微信登录
applivation.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| sky: jwt: admin-secret-key: itcast admin-ttl: 720000000 admin-token-name: token user-secret-key: itheima user-ttl: 720000000 user-token-name: authentication alioss: endpoint: ${sky.alioss.endpoint} access-key-id: ${sky.alioss.access-key-id} access-key-secret: ${sky.alioss.access-key-secret} bucket-name: ${sky.alioss.bucket-name} wechat: appid: ${sky.wechat.appid} secret: ${sky.wechat.secret}
|
UserController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| package com.sky.controller.user;
import com.sky.constant.JwtClaimsConstant; import com.sky.dto.UserLoginDTO; import com.sky.entity.User; import com.sky.properties.JwtProperties; import com.sky.result.Result; import com.sky.service.UserService; import com.sky.utils.JwtUtil; import com.sky.vo.UserLoginVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap; import java.util.Map;
@RestController @RequestMapping("/user/user") @Api(tags = "用户管理") @Slf4j public class UserController {
@Autowired private UserService userService;
@Autowired private JwtProperties jwtProperties;
@PostMapping("/login") @ApiOperation(value = "用户登录") public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) { log.info("用户登录:{}", userLoginDTO.getCode()); User user = userService.wxLogin(userLoginDTO); 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 Result.success(userLoginVO); } }
|
UserMapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.sky.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.sky.entity.User; import org.apache.ibatis.annotations.Mapper;
@Mapper public interface UserMapper extends BaseMapper<User> { }
|
UserService.java
1 2 3 4 5 6 7 8 9
| public interface UserService {
User wxLogin(UserLoginDTO userLoginDTO); }
|
UserServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| package com.sky.service.impl;
import com.alibaba.fastjson.JSONObject; import com.sky.constant.MessageConstant; import com.sky.dto.UserLoginDTO; import com.sky.entity.User; import com.sky.exception.LoginFailedException; import com.sky.mapper.UserMapper; import com.sky.properties.WeChatProperties; import com.sky.service.UserService; import com.sky.utils.HttpClientUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map;
@Service @Slf4j public class UserServiceImpl implements UserService {
public static final String WX_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
@Autowired private WeChatProperties weChatProperties;
@Autowired private UserMapper userMapper;
@Override public User wxLogin(UserLoginDTO userLoginDTO) { String openid = getOpenid(userLoginDTO.getCode()); if (openid == null) { log.error("登录失败,openid为空"); throw new LoginFailedException(MessageConstant.LOGIN_FAILED); } User user = userMapper.selectById(openid); if (user == null) { user = User.builder() .openid(openid) .createTime(LocalDateTime.now()) .build(); userMapper.insert(user); } return user; }
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_URL, map); JSONObject jsonObject = JSONObject.parseObject(json); String openid = jsonObject.getString("openid"); return openid; } }
|
JwtTokenUserInterceptor.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| package com.sky.interceptor;
import com.sky.constant.JwtClaimsConstant; import com.sky.context.BaseContext; import com.sky.properties.JwtProperties; import com.sky.utils.JwtUtil; import io.jsonwebtoken.Claims; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@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.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| package com.sky.config;
import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import com.sky.interceptor.JwtTokenAdminInterceptor; import com.sky.interceptor.JwtTokenUserInterceptor; import com.sky.json.JacksonObjectMapper; 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 org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket;
import java.util.List;
@Configuration @Slf4j public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Autowired private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
@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"); }
@Bean public Docket docket1() { ApiInfo apiInfo = new ApiInfoBuilder() .title("苍穹外卖项目接口文档") .version("2.0") .description("苍穹外卖项目接口文档") .build(); Docket docket = new Docket(DocumentationType.SWAGGER_2) .groupName("admin") .apiInfo(apiInfo) .select() .apis(RequestHandlerSelectors.basePackage("com.sky.controller.admin")) .paths(PathSelectors.any()) .build(); return docket; }
@Bean public Docket docket2() { ApiInfo apiInfo = new ApiInfoBuilder() .title("苍穹外卖项目接口文档") .version("2.0") .description("苍穹外卖项目接口文档") .build(); Docket docket = new Docket(DocumentationType.SWAGGER_2) .groupName("user") .apiInfo(apiInfo) .select() .apis(RequestHandlerSelectors.basePackage("com.sky.controller.user")) .paths(PathSelectors.any()) .build(); return docket; }
protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); }
@Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { log.info("配置消息转换器..."); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(new JacksonObjectMapper()); converters.add(0, converter); }
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { log.info("配置 MyBatis-Plus 的全局设置..."); MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor; } }
|
三. 导入商品浏览功能代码
由于user的Controller与admin的相同,记得修改RestController注释
1. 查询分类
CategoryController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.sky.controller.user;
import com.sky.entity.Category; import com.sky.result.Result; import com.sky.service.CategoryService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController("userCategoryController") @RequestMapping("/user/category") @Api(tags = "分类管理") @Slf4j public class CategoryController {
@Autowired private CategoryService categoryService;
@GetMapping("/list") @ApiOperation("条件查询") public Result<List<Category>> listCategory(Integer type) { log.info("条件查询:type={}", type); List<Category> list = categoryService.listCategory(type); return Result.success(list); }
}
|
业务层方法与admin的相同,使用同一个
2. 根据分类ID查询菜品
Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package com.sky.controller.user;
import com.sky.constant.StatusConstant; import com.sky.entity.Dish; import com.sky.result.Result; import com.sky.service.DishService; import com.sky.vo.DishVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController("userDishController") @RequestMapping("/user/dish") @Api(tags = "菜品管理") @Slf4j public class DishController {
@Autowired private DishService dishService;
@GetMapping("/list") @ApiOperation("根据分类id查询菜品") public Result<List<DishVO>> list(Long categoryId) { Dish dish = new Dish(); dish.setCategoryId(categoryId); dish.setStatus(StatusConstant.ENABLE); List<DishVO> list = dishService.listWithFlavor(dish); return Result.success(list); } }
|
Service
1 2 3 4
|
List<DishVO> listWithFlavor(Dish dish);
|
Impl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
@Override public List<DishVO> listWithFlavor(Dish dish) { LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Dish::getCategoryId, dish.getCategoryId()); queryWrapper.eq(Dish::getStatus, StatusConstant.ENABLE); List<Dish> dishes = dishMapper.selectList(queryWrapper); List<DishVO> dishVOList = new ArrayList<>(); for (Dish d : dishes) { DishVO dishVO = new DishVO(); BeanUtils.copyProperties(d, dishVO); LambdaQueryWrapper<DishFlavor> flavorQueryWrapper = new LambdaQueryWrapper<>(); flavorQueryWrapper.eq(DishFlavor::getDishId, d.getId()); List<DishFlavor> flavors = dishFlavorMapper.selectList(flavorQueryWrapper); dishVO.setFlavors(flavors); dishVOList.add(dishVO); } return dishVOList; }
|
3. 根据分类ID查询套餐
SetmealController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package com.sky.controller.user;
import com.sky.constant.StatusConstant; import com.sky.entity.Setmeal; import com.sky.result.Result; import com.sky.service.SetmealService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController("userSetmealController") @RequestMapping("/user/setmeal") @Api(tags = "套餐管理") @Slf4j public class SetmealController {
@Autowired private SetmealService setmealService;
@GetMapping("/list") @ApiOperation("套餐列表") public Result<List<Setmeal>> list(Long categoryId) { Setmeal setmeal = new Setmeal(); setmeal.setCategoryId(categoryId); setmeal.setStatus(StatusConstant.ENABLE);
List<Setmeal> list = setmealService.list(setmeal); return Result.success(list); } }
|
Service
1 2 3 4
|
List<Setmeal> list(Setmeal setmeal);
|
Impl
1 2 3 4 5 6 7 8 9 10
|
@Override public List<Setmeal> list(Setmeal setmeal) { LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId()); lambdaQueryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus()); return setmealMapper.selectList(lambdaQueryWrapper); }
|
4. 根据套餐ID查询菜品
controller
1 2 3 4 5 6 7 8 9
|
@GetMapping("/dish/{id}") @ApiOperation("根据套餐id查询包含的菜品") public Result<List<DishItemVO>> dishList(@PathVariable Long id) { List<DishItemVO> list = setmealService.getDishItemById(id); return Result.success(list); }
|
service
1 2 3 4 5
|
List<DishItemVO> getDishItemById(Long id);
|
impl
1 2 3 4 5 6 7
|
@Override public List<DishItemVO> getDishItemById(Long id) { return setmealMapper.getDishItemBySetmealId(id); }
|
mapper
1 2 3 4 5 6 7
|
@Select("select sd.name, sd.copies, d.image, d.description " + "from setmeal_dish sd left join dish d on sd.dish_id = d.id " + "where sd.setmeal_id = #{setmealId}") List<DishItemVO> getDishItemBySetmealId(Long id);
|