add music pic query
This commit is contained in:
parent
9ac028a5f9
commit
7f4be753b2
@ -0,0 +1,18 @@
|
||||
package top.baogutang.music.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
|
||||
factory.setConnectTimeout(5000); // 连接超时
|
||||
factory.setReadTimeout(5000); // 读取超时
|
||||
return new RestTemplate(factory);
|
||||
}
|
||||
}
|
||||
@ -19,5 +19,7 @@ public class CacheKey {
|
||||
|
||||
public static final String KEY_USER_LEVEL_PREFIX = "baogutang-music:user:level:id:";
|
||||
|
||||
public static final String KEY_MUSIC_TAG_TOKEN_PREFIX = "baogutang-music:music-tag:token:";
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
package top.baogutang.music.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.baogutang.music.service.IMusicInfoService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @description:
|
||||
*
|
||||
* @author: N1KO
|
||||
* @date: 2025/01/23 : 14:45
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/music/info")
|
||||
public class MusicInfoController {
|
||||
|
||||
@Resource
|
||||
private IMusicInfoService musicInfoService;
|
||||
|
||||
@GetMapping("/cover")
|
||||
public void getMusicCover(@RequestParam(name = "title", required = false) String title,
|
||||
@RequestParam(name = "artist", required = true) String artist,
|
||||
@RequestParam(name = "album", required = false) String album,
|
||||
HttpServletResponse response) {
|
||||
musicInfoService.getCover(title, artist, album, response);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package top.baogutang.music.service;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @description:
|
||||
*
|
||||
* @author: N1KO
|
||||
* @date: 2025/01/23 : 14:53
|
||||
*/
|
||||
public interface IMusicInfoService {
|
||||
|
||||
void getCover(String title, String artist, String album, HttpServletResponse response);
|
||||
|
||||
}
|
||||
@ -21,4 +21,6 @@ public interface IMusicRecordService extends IService<MusicRecordEntity> {
|
||||
MusicRecordEntity queryByChannelAndPlatform(ChannelEnum channel, String platformId);
|
||||
|
||||
List<MusicRecordEntity> queryByPlatformIdList(List<String> platformIdList);
|
||||
|
||||
MusicRecordEntity queryByNameOrAlbumOrArtist(String title, String album, String artist);
|
||||
}
|
||||
|
||||
@ -0,0 +1,211 @@
|
||||
package top.baogutang.music.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import top.baogutang.music.dao.entity.MusicRecordEntity;
|
||||
import top.baogutang.music.exceptions.BusinessException;
|
||||
import top.baogutang.music.service.IMusicInfoService;
|
||||
import top.baogutang.music.service.IMusicRecordService;
|
||||
import top.baogutang.music.utils.CacheUtil;
|
||||
import top.baogutang.music.utils.OkHttpUtil;
|
||||
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static top.baogutang.music.constants.CacheKey.KEY_MUSIC_TAG_TOKEN_PREFIX;
|
||||
|
||||
/**
|
||||
*
|
||||
* @description:
|
||||
*
|
||||
* @author: N1KO
|
||||
* @date: 2025/01/23 : 14:53
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MusicInfoServiceImpl implements IMusicInfoService {
|
||||
|
||||
@Resource
|
||||
private IMusicRecordService musicRecordService;
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Resource(name = "commonExecutor")
|
||||
private Executor commonExecutor;
|
||||
|
||||
@Override
|
||||
public void getCover(String title, String artist, String album, HttpServletResponse response) {
|
||||
MusicRecordEntity musicRecord = musicRecordService.queryByNameOrAlbumOrArtist(title, album, artist);
|
||||
if (Objects.nonNull(musicRecord) && StringUtils.isNotBlank(musicRecord.getPic())) {
|
||||
this.downloadPicAndResponse(musicRecord.getPic(), response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取三方token
|
||||
String token = CacheUtil.cacheOrSupply(KEY_MUSIC_TAG_TOKEN_PREFIX,
|
||||
1L,
|
||||
TimeUnit.DAYS,
|
||||
redisTemplate,
|
||||
this::geneToken,
|
||||
new TypeReference<>() {
|
||||
});
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("authorization", "jwt " + token);
|
||||
headers.put("Content-Type", "application/json");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
if (StringUtils.isBlank(title)) {
|
||||
params.put("title", album);
|
||||
} else {
|
||||
params.put("title", title);
|
||||
}
|
||||
params.put("artist", artist);
|
||||
params.put("album", album);
|
||||
InfoRes<List<MusicInfoRes>> res = this.queryInfo(headers, params);
|
||||
if (Objects.isNull(res) || !Boolean.TRUE.equals(res.getResult()) || CollectionUtils.isEmpty(res.getData())) {
|
||||
log.error("<<<<<<<<<<query info error>>>>>>>>>>");
|
||||
return;
|
||||
}
|
||||
MusicInfoRes musicInfoRes = res.getData().get(0);
|
||||
|
||||
this.downloadPicAndResponse(musicInfoRes.getAlbumImg(), response);
|
||||
}
|
||||
|
||||
|
||||
private InfoRes<List<MusicInfoRes>> queryInfo(Map<String, String> headers, Map<String, Object> params) {
|
||||
InfoRes<List<MusicInfoRes>> res = null;
|
||||
try {
|
||||
params.put("resource", "qmusic");
|
||||
res = OkHttpUtil.post("http://114.96.87.132:8002/apimt/fetch_id3_by_title/", headers, params, new TypeReference<>() {
|
||||
});
|
||||
if (Objects.isNull(res) || !Boolean.TRUE.equals(res.getResult()) || CollectionUtils.isEmpty(res.getData())) {
|
||||
params.put("resource", "netease");
|
||||
res = OkHttpUtil.post("http://114.96.87.132:8002/apimt/fetch_id3_by_title/", headers, params, new TypeReference<>() {
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("query music info error:{}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private String geneToken() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("username", "admin");
|
||||
params.put("password", "admin");
|
||||
TokenRes tokenRes = null;
|
||||
try {
|
||||
tokenRes = OkHttpUtil.post("http://114.96.87.132:8002/apimt/token/", params, new TypeReference<>() {
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("<<<<<<<<<<获取token异常:{}>>>>>>>>>>", e.getMessage(), e);
|
||||
throw new BusinessException("获取token异常!");
|
||||
}
|
||||
if (Objects.nonNull(tokenRes) && Boolean.TRUE.equals(tokenRes.getResult())) {
|
||||
return tokenRes.getToken();
|
||||
}
|
||||
throw new BusinessException("获取token异常!");
|
||||
}
|
||||
|
||||
private void downloadPicAndResponse(String picUrl, HttpServletResponse response) {
|
||||
|
||||
// 获取响应实体
|
||||
ResponseEntity<org.springframework.core.io.Resource> responseEntity = restTemplate.exchange(
|
||||
picUrl,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
org.springframework.core.io.Resource.class
|
||||
);
|
||||
|
||||
// 设置Content-Type
|
||||
MediaType contentType = responseEntity.getHeaders().getContentType();
|
||||
if (contentType != null) {
|
||||
response.setContentType(contentType.toString());
|
||||
} else {
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
}
|
||||
|
||||
// 设置Content-Length(如果可用)
|
||||
List<String> contentLength = responseEntity.getHeaders().get(HttpHeaders.CONTENT_LENGTH);
|
||||
if (contentLength != null && !contentLength.isEmpty()) {
|
||||
response.setHeader(HttpHeaders.CONTENT_LENGTH, contentLength.get(0));
|
||||
}
|
||||
if (Objects.isNull(responseEntity.getBody())) {
|
||||
log.error("<<<<<<<<<<getCover error! url:{} response body is null>>>>>>>>>>", picUrl);
|
||||
return;
|
||||
}
|
||||
try (InputStream inputStream = responseEntity.getBody().getInputStream();
|
||||
OutputStream outputStream = response.getOutputStream()) {
|
||||
|
||||
// 数据传输
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
outputStream.flush();
|
||||
} catch (Exception e) {
|
||||
log.error("getCover error!picUrl:{},message:{}", picUrl, e.getMessage(), e);
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
static class TokenRes {
|
||||
private String token;
|
||||
private Boolean result;
|
||||
}
|
||||
|
||||
@Data
|
||||
static class InfoRes<T> {
|
||||
private Boolean result;
|
||||
private String code;
|
||||
private T data;
|
||||
}
|
||||
|
||||
@Data
|
||||
static class MusicInfoRes {
|
||||
|
||||
private String mid;
|
||||
|
||||
private String extra;
|
||||
|
||||
private String notice;
|
||||
|
||||
private String title;
|
||||
|
||||
private String singer;
|
||||
|
||||
private String album;
|
||||
|
||||
@JsonProperty("album_img")
|
||||
private String albumImg;
|
||||
|
||||
private String artist;
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package top.baogutang.music.service.impl;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.baogutang.music.dao.entity.MusicRecordEntity;
|
||||
import top.baogutang.music.dao.mapper.MusicRecordMapper;
|
||||
@ -76,4 +77,15 @@ public class MusicRecordServiceImpl extends ServiceImpl<MusicRecordMapper, Music
|
||||
.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MusicRecordEntity queryByNameOrAlbumOrArtist(String title, String album, String artist) {
|
||||
return new LambdaQueryChainWrapper<>(baseMapper)
|
||||
.like(StringUtils.isNotBlank(title), MusicRecordEntity::getName, title + "%")
|
||||
.like(StringUtils.isNotBlank(album), MusicRecordEntity::getAlbumName, album + "%")
|
||||
.like(StringUtils.isNotBlank(artist), MusicRecordEntity::getArtistName, artist + "%")
|
||||
.orderByDesc(MusicRecordEntity::getId)
|
||||
.last(" limit 1")
|
||||
.one();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user