目录
1.springboot整合Web
<!--springboot整合Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
1.1.2
//templates.list下
@Controller
public class index{
@RequestMapping("/index")
public String index() {
return "list/index";
}
}
2.springboot整合oss上传文件
<!-- 阿里云oss依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!-- 日期工具栏依赖 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
2.2.2前端设计上传
<form th:action="@{/fileupload}" method="post" enctype="multipart/form-data">
<table>
<tr>
<td><input type="file" name="file" multiple="multiple" /></td>
</tr>
<tr>
<td><input type="submit" value="提交"/></td>
</tr>
<hr>
</table>
</form>
2.2.3后端设计
@RequestMapping("fileupload")
public String upload(@Param("files") MultipartFile file){
//-----------------------上传阿里oss
String url = ossService.upload(file);
//-----------------------上传本地
String fileName = file.getOriginalFilename();//1.获取原文件名
System.out.println("fileName"+fileName);
int index = fileName.indexOf(".");
System.out.println("index"+index);
//2.获取后缀
String substring = fileName.substring(index, fileName.length());
System.out.println("substring"+substring);
//3. 获取新的文件名
SimpleDateFormat ymd = new SimpleDateFormat("yyyyMMdd");
String date = ymd .format(new Date());
String newFileName = date + UUID.randomUUID() + substring;
//4将要保存的全路径
File file1 = new File("D:/image/"+newFileName);
//.提交
//查看文件夹是否存在,不存在则创建
if(!file1.getParentFile().exists()) {
file1.getParentFile().mkdirs();
}
try {
//使用此方法保存必须要绝对路径且文件夹必须已存在,否则报错
file.transferTo(file1);
System.out.println("成功");
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
return "0";
}
@Service
public class OssServiceImpl implements OssService {
@Override
public String upload(MultipartFile file) {
String endPoint = ConstantPropertiesUtils.END_POINT;
String accessKeyId = ConstantPropertiesUtils.ACCESS_KEY_ID;
String accessKeySecret = ConstantPropertiesUtils.ACCESS_KEY_SECRET;
String bucketName = ConstantPropertiesUtils.BUCKET_NAME;
try {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
// 上传文件流。
InputStream inputStream = file.getInputStream();
//获取文件名称
String fileOriginalFilename = file.getOriginalFilename();
//使用uuid在文件名称里面添加唯一值
String uuid = UUID.randomUUID().toString().replace("-", "");
fileOriginalFilename = uuid + fileOriginalFilename;
String datePach = new DateTime().toString("yyyy/MM/dd");
fileOriginalFilename = datePach + "/" + fileOriginalFilename;
//调用oss进行上传
//第一个参数BucketName,第二个参数上传到oss文件的路径和名称,第三个文件输入流
ossClient.putObject(bucketName, fileOriginalFilename, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
String url = "http://" + bucketName + "." + endPoint + "/" + fileOriginalFilename;
return url;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package com.atguigu.oss.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//项目启动,spring接口,加载之后,执行接口的方法
@Component
public class ConstantPropertiesUtils implements InitializingBean {
//读取配置文件
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyid;
@Value("${aliyun.oss.file.keysecret}")
private String keysecret;
@Value("${aliyun.oss.file.bucketname}")
private String bucketname;
public static String END_POINT;
public static String ACCESS_KEY_ID;
public static String ACCESS_KEY_SECRET;
public static String BUCKET_NAME;
//定义公共的静态常量
@Override
public void afterPropertiesSet() throws Exception {
END_POINT = endpoint;
ACCESS_KEY_ID = keyid;
ACCESS_KEY_SECRET = keysecret;
BUCKET_NAME = bucketname;
}
}
application.properties文件
#阿里云oss
#yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
aliyun.oss.file.endpoint=oss-cn-beijing.aliyuncs.com
# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
aliyun.oss.file.keyid=LTAI5tG378r3
aliyun.oss.file.keysecret=uf0OWKm6WWcOq9NrzYC
aliyun.oss.file.bucketname=edu-yu10
3.spring整合视频点播
3.1整合
3.1.1 pom
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.3.3</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-vod</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-sdk-vod-upload</artifactId>
<version>1.4.14</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
3.1.2 application.properties
查看RAM 访问控制 (aliyun.com)获取用户的id和secret
aliyun.vod.file.keyid=LTAI5tBE2MLWLiiMRYny1c
aliyun.vod.file.keysecret=6msloN87DayD5rC8soeygWvGn
# 最大上传单个文件大小:默认1M
spring.servlet.multipart.max-file-size=1024MB
# 最大置总上传的数据大小 :默认10M
spring.servlet.multipart.max-request-size=1024MB
3.1.3 获取凭证
//根据视频id获得视频凭证 63e345254a33459d806b437d7fec4be3
@GetMapping("getPlayAuth/{id}")
public R getPlayAuth(@PathVariable String id) {
System.out.println("id"+id);
try {
//创建初始化对象
DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_SECRET);
System.out.println("client"+client);
//创建获取凭证的request和response对象
GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
System.out.println("request"+request);
//向request对象中设置视频id
request.setVideoId(id);
System.out.println("request"+request);
//调用方法获得凭证
GetVideoPlayAuthResponse response = client.getAcsResponse(request);
System.out.println("response"+response);
String playAuth = response.getPlayAuth();
System.out.println("playAuth"+playAuth);
return R.ok().data("playAuth", playAuth);
} catch (ClientException | com.aliyuncs.exceptions.ClientException e) {
e.printStackTrace();
throw new yuException(20001,"视频playAuth获取失败");
}
}
AliyunVodSDKUtils.java
public class AliyunVodSDKUtils {
public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
String regionId = "cn-shanghai"; // 点播服务接入区域 在视频管理可以看到
DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
return client;
}
}
ConstantVodUtils.java
@Component
public class ConstantVodUtils implements InitializingBean {
@Value("${aliyun.vod.file.keyid}")
private String keyid;
@Value("${aliyun.vod.file.keysecret}")
private String keysecret;
public static String ACCESS_KEY_SECRET;
public static String ACCESS_KEY_ID;
@Override
public void afterPropertiesSet() throws Exception {
ACCESS_KEY_ID = keyid;
ACCESS_KEY_SECRET = keysecret;
}
}
3.1.4 获取url
public static void getPlayUrl() throws ClientException {
//创建初始化对象
DefaultAcsClient client = AliyunVodSDKUtils.initVodClient("aliyun.vod.file.keyid", "aliyun.vod.file.keysecret");
//创建获取视频地址request和response
GetPlayInfoRequest request = new GetPlayInfoRequest();
GetPlayInfoResponse response = new GetPlayInfoResponse();
//向request对象里面设置视频id
request.setVideoId("9cc6a580681647029033baabed85dab0");
//调用初始化对象里面的方法,传递request,获取数据
response = client.getAcsResponse(request);
List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();
//播放地址
for (GetPlayInfoResponse.PlayInfo playInfo : playInfoList) {
System.out.println("PlayInfo.PlayURL =" + playInfo.getPlayURL() + "\n");
}
//Base信息
System.out.println("VideoBase.Title =" + response.getVideoBase().getTitle() + "\n");
}
3.2上传视频
@PostMapping("uploadAlyiVideo")
public R uploadAlyiVideo(MultipartFile file) {
System.out.println("VideoId");
String VideoId = vodService.uploadVIdeo(file);
System.out.println("VideoId"+VideoId);
return R.ok().data("VideoId", VideoId);
}
@Service
public class VodServiceImpl implements VodService {
@Override
public String uploadVIdeo(MultipartFile file) {
try {
//accessKeyId, accessKeySecret
//fileName:上传文件原始名称
// 01.03.09.mp4
String fileName = file.getOriginalFilename();
//title:上传之后显示名称
String title = fileName.substring(0, fileName.lastIndexOf("."));
//inputStream:上传文件输入流
InputStream inputStream = file.getInputStream();
UploadStreamRequest request = new UploadStreamRequest(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_SECRET, title, fileName, inputStream);
UploadVideoImpl uploader = new UploadVideoImpl();
UploadStreamResponse response = uploader.uploadStream(request);
String videoId = null;
if (response.isSuccess()) {
videoId = response.getVideoId();
} else { //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因
videoId = response.getVideoId();
}
return videoId;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public void removeVideo(String videoId) {
try {
//初始化对象
DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(
ConstantVodUtils.ACCESS_KEY_ID,
ConstantVodUtils.ACCESS_KEY_SECRET);
//创建删除视频的request对象
DeleteVideoRequest request = new DeleteVideoRequest();
//向request中设置videoId
request.setVideoIds(videoId);
//调用删除方法
DeleteVideoResponse response = client.getAcsResponse(request);
System.out.print("RequestId = " + response.getRequestId() + "\n");
} catch (ClientException e) {
throw new yuException(20001, "视频删除失败");
}
}
}
4.spring boot 整合登录jwt token
4.1 依赖pom
4.1.1导入依赖
<!-- JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
4.2 工具类
4.2.1JwtUtils .java
package com.yu.commonutils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
/**
* @author yu
* @since 2012/8/16
* 生成字符串,包含用户信息,
* jwt生成包含三部分:1头2.有效荷载3.签名哈希 防伪标志
*/
public class JwtUtils {
public static final long EXPIRE = 1000 * 60 * 60 * 24;//token过期时间
public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";//密钥
public static String getJwtToken(String id, String nickname){
String JwtToken = Jwts.builder()
//第一步分
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
//第二部分
.setSubject("yu-user")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
//第三部分 token主体
.claim("id", id)
.claim("nickname", nickname)
.signWith(SignatureAlgorithm.HS256, APP_SECRET)
.compact();
return JwtToken;
}
/**
* 判断token是否存在与有效
* @param jwtToken
* @return
*/
public static boolean checkToken(String jwtToken) {
if(StringUtils.isEmpty(jwtToken)) return false;
try {
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 判断token是否存在与有效
* @param request
* @return
*/
public static boolean checkToken(HttpServletRequest request) {
try {
String jwtToken = request.getHeader("token");
System.out.println("jwtToken"+jwtToken);
if(StringUtils.isEmpty(jwtToken)) return false;
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 根据token获取会员id
* @param request
* @return
*/
public static String getMemberIdByJwtToken(HttpServletRequest request) {
String jwtToken = request.getHeader("token");
if(StringUtils.isEmpty(jwtToken))
return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
Claims claims = claimsJws.getBody();
System.out.println("claims:"+claims);
return (String)claims.get("id");
}
}
4.2.2登录密码 只加密不揭密MD5.java
package com.yu.commonutils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public final class MD5 {
public static String encrypt(String strSrc) {
try {
char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
byte[] bytes = strSrc.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
bytes = md.digest();
System.out.println("bytes"+bytes);
int j = bytes.length;
System.out.println("j"+j);
char[] chars = new char[j * 2];
int k = 0;
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
System.out.println(" bytes[i]"+ bytes[i]);
//转化hexChars
chars[k++] = hexChars[b >>> 4 & 0xf];
chars[k++] = hexChars[b & 0xf];
}
return new String(chars);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("MD5加密出错!!+" + e);
}
}
public static void main(String[] args) {
System.out.println(MD5.encrypt("123456"));
}
}
4.2.3 登录获取token
package com.yu.educenter.controller;
import com.yu.commonutils.JwtUtils;
import com.yu.commonutils.R;
import com.yu.commonutils.user.UcenterMemberOrder;
import com.yu.educenter.entity.UcenterMember;
import com.yu.educenter.entity.vo.RegisterVo;
import com.yu.educenter.service.UcenterMemberService;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
/**
* <p>
* 会员表 前端控制器
* </p>
*
* @author atguigu
* @since 2020-08-11
*/
@RestController
@RequestMapping("/educenter/member")
@CrossOrigin
public class UcenterMemberController {
@Autowired
private UcenterMemberService ucenterMemberService;
//电话和密码登录 返回token
@PostMapping("login")
public R login(@RequestBody UcenterMember ucenterMember){
System.out.println("ucenterMember"+ucenterMember);
String token =ucenterMemberService.login(ucenterMember);
return R.ok().data("token",token);
}
}
package com.yu.educenter.service.impl;
import com.yu.commonutils.JwtUtils;
import com.yu.commonutils.MD5;
import com.yu.commonutils.exceptionhandler.GuliException;
import com.yu.educenter.entity.UcenterMember;
import com.yu.educenter.entity.vo.RegisterVo;
import com.yu.educenter.mapper.UcenterMemberMapper;
import com.yu.educenter.service.UcenterMemberService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* <p>
* 会员表 服务实现类
* </p>
*
* @author yu
* @since 2022-08-11
*/
@Service
public class UcenterMemberServiceImpl extends ServiceImpl<UcenterMemberMapper, UcenterMember> implements UcenterMemberService {
//用来验证,redis验证码是否匹配
@Autowired
private RedisTemplate<String,String> redisTemplate;
//登录的方法
@Override
public String login(UcenterMember ucenterMember) {
//手机号和密码做登录
//1、获取手机号和密码
String mobile = ucenterMember.getMobile();
String password = ucenterMember.getPassword();
//2、如过手机号和密码,直接返回登录失败
if (StringUtils.isEmpty(mobile)||StringUtils.isEmpty(password)){
throw new YuException(20001,"手机号和密码为空");
}
//判断手机号是否正确
QueryWrapper<UcenterMember> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("mobile",mobile);
UcenterMember mobileMember = baseMapper.selectOne(queryWrapper);
if (mobileMember == null){
throw new YuException(20001,"手机号不存在");
}
//判断密码是否相等
//数据库密码进行加密,不能直接对比
//MD5对密码进行加密,再与数据库进行比较
String password1 = mobileMember.getPassword();
if (!MD5.encrypt(password).equals(password1)){
throw new YuException(20001,"密码错误");
}
//判断用户是否被禁用
if(mobileMember.getIsDisabled()){
throw new YuException(20001,"用户被禁用登录失败");
}
//登录成功
//按照jwt生产token返回
String token = JwtUtils.getJwtToken(mobileMember.getId(), mobileMember.getNickname());
return token;
}
}
package com.yu.commonutils.exceptionhandler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 自定义异常类
*/
@Data
@AllArgsConstructor //有参数构造器
@NoArgsConstructor //生成无参数构造
public class YuException extends RuntimeException {
private Integer code;//状态码
private String msg;//输出消息
}
5.cookie和session和token
cookie原理
token原理
5.1session和cookie的区别
-
cookie数据存放在客户端的浏览器上,session数据 放在服务器上。
-
单个cookie保存的数据不能超过4K,浏览器都限制一个站点最多保存20个cookie。session没有这种限制。
-
cookie比session更不安全,别人可以分析存放在本地的cookie并进行cookie欺骗。(可考虑对cookie加密)
-
session会在一定时间内保存在服务器上。当访问增多时,会比较占用服务器的内容,考虑到减轻服务器负担,可以考虑使用cookie
-
session存放图片验证码session.setAttribute(CAPTCHA_KEY, verifyCode.toLowerCase());
cookie和token的区别
-
token存在哪儿都行,客户端可存放在localstorage或者cookie,而服务器端则会存放于数据库(服务器端的session是直接放在内存中的)
-
cookie 举例:门卫大爷看你的学生证,给你一个编号,以后进行任何操作,都出示编号后服务员去看查你是谁。
token 举例:直接给门卫大爷看自己学生证 -
对于token而言,服务器不需要去查看你是谁,是无状态的,而cookie则是相对有状态的。
-
token的可拓展性更强。
-
token可抵御csrf,因为cookie容易伪造,但是token是不容易伪造的。
5.2 后端接收保存
5.2.1 session和cookie
@RequestMapping("tes")
public String tes(HttpServletRequest req,HttpServletResponse response, HttpSession session) {
//1.cookie
Cookie cookie = new Cookie("mobile", "yu");
cookie.setMaxAge(Integer.MAX_VALUE);
//设置根目录
cookie.setPath("/");
//Cookie中 maxAge设置为负值 和0的区别
//如果设置为负值,则为浏览器进程Cookie(内存中保存),关闭浏览器就失效;
//如果设置为0,则立即删除该Cookie。
//设置Cookie的最大生命周期,否则浏览器关闭后Cookie即失效
//设置cookie过期值时间是7天,7*24*60*60单位是秒
Cookie cookie1 = new Cookie("mobile1", "10s");
cookie1.setMaxAge(10);
//将Cookie加到response中
response.addCookie(cookie);
response.addCookie(cookie1);
//2.session
//设置session,浏览器关闭后session即失效
session.setAttribute("mobile_session","yu1");
/* setMaxInactiveInterval(int i) i的单位是秒。
*如果设置的值为零或负数,则表示会话将永远不会超时。常用于设置当前会话时间。
* 不设置关闭浏览器 放弃值
*/
session.setMaxInactiveInterval(10);
final String id = session.getId();
System.out.println("sessionid:"+id);
return "file/index";
}
@RequestMapping("getse")
public String getse(HttpServletRequest req,HttpServletResponse response, HttpSession session) {
//获取session值 浏览器关了就没有了 在cookie中看不到
String sesionCode = (String) req.getSession().getAttribute("mobile_session");
log.info("sesionCode->{}",sesionCode);
final Object mobile = session.getAttribute("mobile_session");
log.info("mobile ->{}",mobile );
//获取Cookie值
Cookie[] cookie1 = req.getCookies();
for (int i = 0; i < cookie1.length; i++) {
Cookie cook = cookie1[i];
System.out.println("cook:"+cook);
System.out.println("cook.getName():"+cook.getName()); //K
System.out.println("cook:"+cook.getValue().toString());//V
if(cook.getName().equalsIgnoreCase("mobile")){ //获取键
System.out.println("mobile:"+cook.getValue().toString()); //获取值
}
}
return "file/index";
}
6.vue创建命令
vue create vue-vod 创建一个简单的vue项目
cd vue-vod
$ npm run serve