首页 > 其他分享 >使用经典技术的音乐网站

使用经典技术的音乐网站

时间:2024-02-07 19:11:44浏览次数:27  
标签:音乐网站 return String 经典 技术 springframework org import public

项目地址

技术栈

后端
SpringBoot + MyBatis + Redis

前端
Vue3.0 + TypeScript + Vue-Router + Vuex + Axios + ElementPlus + Echarts

简介

是一个经典简单的音乐网站。后端基本也就是在CRUD,redis是当缓存用的,数据库用的是mysql.

XML自定义(附加)mybatis-plus的mapper配置

mapper接口正常定义

package com.example.yin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.yin.model.domain.Admin;
import org.springframework.stereotype.Repository;
@Repository
public interface AdminMapper extends BaseMapper<Admin> {

}

在资源路径下定义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.example.yin.mapper.AdminMapper">
  <resultMap id="BaseResultMap" type="com.example.yin.model.domain.Admin">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="password" jdbcType="VARCHAR" property="password" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name, password
  </sql>

</mapper>

Base_Column_Lis是sql语句块,用于减少重复代码,可以在别的地方用id包含进去,这里拿来覆盖mybatis-plus的默认设置。
resultMap的id必须是这样才能覆盖默认设置。

分环境的SpringBoot配置文件

示意图
通过默认(主)配置文件的最后一行:
spring.profiles.active=dev 启用application-dev.properties。
就是说两个环境之间可以有一些公共操作的。

log4j配置文件

log4j.properties跟application.properties同级目录。

# LOG4J
log4j.rootCategory=INFO, stdout,file

# print to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

# print to file
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.DatePattern='-'yyyy-MM-dd'.log'
log4j.appender.file.File=./logs/musicWebsite
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p [%c]: %m%n

mybatis-plus的MetaObjectHandler

看着是在访问实体对象之前或者之后做一些操作,有点像拦截器。

package com.example.yin.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {

        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}

代码习惯

对控制器的每个请求,都定义一个专门的model类来接受信息
控制器


@RestController
public class AdminController {
    @Autowired
    private AdminService adminService;

    // 判断是否登录成功
    @PostMapping("/admin/login/status")
    public R loginStatus(@RequestBody AdminRequest adminRequest, HttpSession session) {
        return adminService.verityPasswd(adminRequest, session);
    }
}

AdminRequest的结构

package com.example.yin.model.request;

import lombok.Data;

/**
 * @Author 祝英台炸油条
 * @Time : 2022/6/6 18:44
 **/
@Data
public class AdminRequest {
    private Integer id;

    private String username;

    private String password;
}

并且定义一个服务调用结果类,作为服务调用的返回对象,也作为控制器的返回对象。
这里是R类



@Data
public class R {

    private int code;

    private String message;

    private String type;

    private Boolean success;

    private Object data;

    public static R success(String message) {
        R r = new R();
        r.setCode(200);
        r.setMessage(message);
        r.setSuccess(true);
        r.setType("success");
        r.setData(null);
        return r;
    }

    public static R success(String message, Object data) {
        R r = success(message);
        r.setData(data);
        return r;
    }

    public static R warning(String message) {
        R r = error(message);
        r.setType("warning");
        return r;
    }

    public static R error(String message) {
        R r = success(message);
        r.setSuccess(false);
        r.setType("error");
        return r;
    }

    public static R fatal(String message) {
        R r = error(message);
        r.setCode(500);
        return r;
    }
}

这个类作为前后端交流的消息结构。
Service类无论如何也要分成接口和impl实现部分。这为微服务部署提供便利。

package com.example.yin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.yin.common.R;
import com.example.yin.mapper.AdminMapper;
import com.example.yin.model.domain.Admin;
import com.example.yin.model.request.AdminRequest;
import com.example.yin.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;

@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Override
    public R verityPasswd(AdminRequest adminRequest, HttpSession session) {
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name",adminRequest.getUsername());
        queryWrapper.eq("password",adminRequest.getPassword());
        if (adminMapper.selectCount(queryWrapper) > 0) {
            session.setAttribute("name", adminRequest.getUsername());
            return R.success("登录成功");
        } else {
            return R.error("用户名或密码错误");
        }
    }
}

服务类的实现类需要继承mybatis-plus提供的ServiceImpl类,同时实现服务接口。
这个ServiceImpl类看原码发现会要一个基本mapper,但是为了使用扩展后的mapper我们定义了一个新的,而且这个类提供了不少常用的方法,可以研究一下。

工具代码

复杂表单提交,包含文件和参数的表单。用户home目录和文件系统分隔符的获取,
表单文件的保存。

 public R addSong(SongRequest addSongRequest, MultipartFile mpfile) {
        Song song = new Song();
        BeanUtils.copyProperties(addSongRequest, song);
        String pic = "/img/songPic/tubiao.jpg";
        String fileName = mpfile.getOriginalFilename();
        String filePath = System.getProperty("user.dir") + System.getProperty("file.separator") + "song";
        File file1 = new File(filePath);
        if (!file1.exists()) {
            if (!file1.mkdir()) {
                return R.fatal("创建文件失败");
            }
        }
        File dest = new File(filePath + System.getProperty("file.separator") + fileName);
        String storeUrlPath = "/song/" + fileName;
        try {
            mpfile.transferTo(dest);
        } catch (IOException e) {
            return R.fatal("上传失败" + e.getMessage());
        }
        song.setCreateTime(new Date());
        song.setUpdateTime(new Date());
        song.setPic(pic);
        song.setUrl(storeUrlPath);
        if (songMapper.insert(song) > 0) {
            return R.success("上传成功", storeUrlPath);
        } else {
            return R.error("上传失败");
        }
    }

BeanUtils类的使用
这里拿来拷贝对象的属性,可以理解为复制对象。

    public R updateSongMsg(SongRequest updateSongRequest) {
        Song song = new Song();
        BeanUtils.copyProperties(updateSongRequest, song);
        if (songMapper.updateById(song) > 0) {
            return R.success("修改成功");
        } else {
            return R.error("修改失败");
        }
    }

md5加密,StringUtils类的使用,字符串工具类

 public R addUser(ConsumerRequest registryRequest) {
        if (this.existUser(registryRequest.getUsername())) {
            return R.warning("用户名已注册");
        }
        Consumer consumer = new Consumer();
        BeanUtils.copyProperties(registryRequest, consumer);
        //MD5加密
        String password = DigestUtils.md5DigestAsHex((SALT + registryRequest.getPassword()).getBytes(StandardCharsets.UTF_8));
        consumer.setPassword(password);
        //都用用
        if (StringUtils.isBlank(consumer.getPhoneNum())) {
            consumer.setPhoneNum(null);
        }
        if ("".equals(consumer.getEmail())) {
            consumer.setEmail(null);
        }
        consumer.setAvator("img/avatorImages/user.jpg");
        try {
            if (consumerMapper.insert(consumer) > 0) {
                return R.success("注册成功");
            } else {
                return R.error("注册失败");
            }
        } catch (DuplicateKeyException e) {
            return R.fatal(e.getMessage());
        }
    }

SALT是一个常量字符串,叫盐值。

package com.example.yin.constant;

public class Constants {
    /* 歌曲图片,歌手图片,歌曲文件,歌单图片等文件的存放路径 */
    public static String ASSETS_PATH = System.getProperty("user.dir");
    
    public static String AVATOR_IMAGES_PATH = "file:" + ASSETS_PATH + "/img/avatorImages/";
    public static String SONGLIST_PIC_PATH = "file:" + ASSETS_PATH + "/img/songListPic/";
    public static String SONG_PIC_PATH = "file:" + ASSETS_PATH + "/img/songPic/";
    public static String SONG_PATH = "file:" + ASSETS_PATH + "/song/";
    public static String SINGER_PIC_PATH = "file:" + ASSETS_PATH + "/img/singerPic/";
    public static String BANNER_PIC_PATH = "file:" + ASSETS_PATH + "/img/swiper/";

    /* 盐值加密 */
    public static String SALT = "zyt";
}

redis配置类
`` java
package com.example.yin.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@EnableCaching //开启缓存注解
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
RedisSerializer redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setConnectionFactory(factory);
//key序列化方式
template.setKeySerializer(redisSerializer);
//value序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
//value hashmap序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}

@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
    RedisSerializer<String> redisSerializer = new StringRedisSerializer();
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    //解决查询缓存转换异常的问题
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    // 配置序列化(解决乱码的问题),过期时间600秒
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofSeconds(600))
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
            .disableCachingNullValues();
    return RedisCacheManager.builder(factory)
            .cacheDefaults(config)
            .build();
}

}

# 拦截器的定义
先实现HandlerInterceptor接口,再去实现WebMvcConfigurer接口的@Configuration覆盖  public void addInterceptors(InterceptorRegistry registry)把实现的拦截器注册进去。
定义拦截器
``` java


package com.example.yin.config;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class CorsInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x_requested_with,x-requested-with,Authorization,Content-Type,token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        return true;
    }
}

注册拦截器

package com.example.yin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Author 祝英台炸油条
 * @Time : 2022/6/7 17:08
 **/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Bean
    public CorsInterceptor corsInterceptor() {
        return new CorsInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(corsInterceptor())
                .addPathPatterns("/**");
    }

}

标签:音乐网站,return,String,经典,技术,springframework,org,import,public
From: https://www.cnblogs.com/panzewen/p/18011205

相关文章

  • 面试经典 150 题 (十四)
    就用除法classSolution{publicint[]productExceptSelf(int[]nums){int[]answer=newint[nums.length];intsum=1;intzeroNum=0;for(inti=0;i<nums.length;i++){if(nums[i]==0)zeroNum++;......
  • 面试经典 150 题 (十三)
    先来个大的classRandomizedSet{privateHashSet<Integer>hashSet;publicRandomizedSet(){hashSet=newHashSet<Integer>();}publicbooleaninsert(intval){if(hashSet.contains(val)){returnfa......
  • 从零开始的直播带货商城APP开发教学:技术架构设计
    在当今数字化时代,直播带货已成为电商行业的一股强劲力量,为商家和消费者提供了全新的购物体验。为了满足这一需求,开发一个功能强大的直播带货商城APP至关重要。本文将从零开始,深入探讨直播带货商城APP的技术架构设计。 一、项目概述直播带货商城APP旨在为用户提供便捷的购物体验,同......
  • 【论文笔记】用于遥感图像语义分割的几何边界引导特征融合与空间-语义上下文聚合技术
    作者:YupeiWang发表年代:2023使用的方法:边界指导、上下文聚合来源:IEEETIP方向:语义分割期刊层次:CCFA;计算机科学1区;IF13.3文献链接:https://doi.org/10.1109/TIP.2023.3326400WangY,ZhangH,HuY,etal.Geometricboundaryguidedfeaturefusionandspa......
  • 面试经典 150 题 (十二)
    排序,i代表至少发表的论文数量时间复杂度:O(nlogn)空间复杂度:O(logn)classSolution{publicinthIndex(int[]citations){//01356intlength=citations.length;Arrays.sort(citations);inth=0;for(inti=1......
  • 经典Prompt欣赏 - Video Script Generator 视频脚本生成器
    体验可以通过https://chat.openai.com/g/g-rxlwmrnqa-video-script-generator地址体验,它将按照你的主题要求,创建TikTok视频脚本。PromptYouareanexpertinthefieldoftopic,whowantstocreateengagingandinformativecontentforTikTok.Youraudienceconsi......
  • 经典Prompt欣赏 - Video Script Generator 视频脚本生成器
    体验可以通过https://chat.openai.com/g/g-rxlwmrnqa-video-script-generator地址体验,它将按照你的主题要求,创建TikTok视频脚本。PromptYouareanexpertinthefieldoftopic,whowantstocreateengagingandinformativecontentforTikTok.Youraudienceconsi......
  • 春节经典诗词祝福语快记到手机便签里
    随着春节的临近,我们纷纷为如何表达对亲朋好友的美好祝愿而烦恼。在这个时刻,古诗词中蕴含着丰富而高级的祝福语文案,成为我们发祝福语或春节文案的灵感源泉。关于春节的经典诗词有很多,这其中蕴含的祝福语文案也颇具深意。为了便捷地找到这些珍贵的春节诗句,我们可以利用网络搜索“春......
  • 技术人员核心能力 -- 向上管理能力
    工作了很多年后才真正明白一些道理-在为谁工作?为谁效力?谁在买我们的劳动、时间、技术、能力?有些时候一直学习技术为主、有些时候就忙于一些手上的工作内容、如何让领导满意、如何得到领导认可、需要干哪些事情?平时关键精力应该要放在哪里?如何拿到产出?如何量化汇报?如何......
  • http会话技术
    http中cookie、session、token是啥子?http是无状态的,每个请求间相互独立也就是说我用第一个数据包进行登录,第二个数据包去请求服务器时,服务器无法确认我们是否已经登录。这时就需要一些新的技术来解决这个问题。下面就以登录为例子来讲这个问题cookie+session方案既然我们需要......