栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

课设搭建门户网站后端(springboot+redis)(发送邮箱(邮箱判断),文件上传(判断类型,是否重复,上传后访问不到)附源码)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

课设搭建门户网站后端(springboot+redis)(发送邮箱(邮箱判断),文件上传(判断类型,是否重复,上传后访问不到)附源码)

大三在学习了JavaWeb后,在学期末进行了课程设计(学习3个,其中第一个是JavaWeb,第二个基于springMVC,第3个springboot。并和舍友完成一个门户网站,负责后端编写)。在这个过程中学到了很多,限于本人水平,只用作记录和学习,如有不足,还请批评指出。

成果展示

问题总结与处理

1.登录注册时,希望注册时需要邮箱的验证码。
(1)生成验证码(这里截取了UUID的前六位,可自行调整)

import java.util.UUID;

public class CodeUtils {
    public static String getUUID() {
        String code= UUID.randomUUID().toString();
        code=code.substring(0,6);
        return code;
    }
}

(2)邮箱判断

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EmailJudge {

    public static boolean isMail(String email){
        String regEx1 = "^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$";
        Pattern p;
        Matcher m;
        p = Pattern.compile(regEx1);
        m = p.matcher(email);
        if(m.matches()){
            return true;
        }
        return false;
    }
}

(3)发送邮件(下有授权码获取方法)
这里新建一个线程完成邮箱发送操作,避免响应请求过慢。

    
    @GetMapping("/getEmail/{email}")
    public Result getEmail(@PathVariable String email) throws EmailException {
        if (EmailJudge.isMail(email)) {//判断邮件是否正确
            String code = CodeUtils.getUUID();//生成一个验证码
            new Thread(new Runnable(){
                @SneakyThrows
                @Override
                public void run() {
                    HtmlEmail email1 = new HtmlEmail();
                    email1.setHostName("smtp.qq.com");
                    email1.setCharset("utf-8");
                    email1.addTo(email);
                    email1.setFrom("【填写你的邮箱】", "【邮箱主题】");
                    email1.setAuthentication("【填写你的邮箱】", "【邮箱授权码】");
                    email1.setSubject("欢迎你注册本系统");//填写文案
                    email1.setMsg("您的验证码为: " + code);
                    email1.send();
                }
            }).start();
            return new Result(true, "验证码已发送!", code);
        } else {
            return new Result(false, "您输入的邮箱有误!", null);
        }
    }

上述发送邮件其实存在安全问题,即前端请求立即返回验证码,这样即使注册用户不看邮箱,依然可以获得验证码,可以在数据库储存邮箱验证码,这样更安全,也能控制索取验证码时间间隔
点击 授权码获得方法

2.文件上传
(1)文件上传(非空,验证,是否重复)
这里上传的是png或jpg类型的,这里的验证也是不安全的,只通过后缀判断文件类型,可以查阅更加安全的方法。通过md5加密实现判断文件是否重复,可以为文件的字节流生成一个32位的码,如果在数据库发现相同的码,那这个文件就已经上传过了

    @PostMapping("/add")
    public Result add(@RequestParam(required = false) MultipartFile picture)
                      throws IOException {
         if (!(picture ==null)) {
                String pictureName = picture.getOriginalFilename();//获取上传文件的名称
                int begin = pictureName.indexOf(".");
                int end = pictureName.length();
                String fileType = pictureName.substring(begin, end);//截取文件类型
                if (fileType.equals(".png") || fileType.equals(".jpg")) {
                    String md = DigestUtils.md5Hex(picture.getBytes());//生成md5码
                    Site site = this.siteMapper.fileJudge(md);//判断是否已上传
                    if (site == null) {//如果未上传
                        String local = "[文件名称]" + fileType;
                        picture.transferTo(new File("D:\work\shixun\stepTab\src\main\resources\static\" + local));//要存放的地址
                        return new Result(true,"添加成功",null);
                    } else {//文件已上传,获得数据库内的图片路径
                        pictureUrl = site.getPicture();
                        return new Result(true,"添加成功",null);
                    }
                } else {
                    return new Result(false, "文件类型错误,请上传PNG或者JPG格式文件!", null);
                }
            } else {
                return new Result(false, "文件不能为空!", null);
            }    
         }         

(2)上传后访问不到
在新上传后,路径下显示文件存在,但是通过服务器却访问不到,这时重启服务器发现又可以访问到,但是不能每次都重启,我们可以通过指定静态资源访问路径来解决这个问题,这样当服务器接收到要访问静态资源的请求就会到指定路径找到图片。

首先在yml指定访问静态资源的路由前缀

spring:
  mvc:
    static-path-pattern: /picture
@Configuration
public class ResourceConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/picture
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        // 使用JSON格式序列化对象,对缓存数据key和value进行转换
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
        // 解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
        // 设置RedisTemplate模板API的序列化方式为JSON
        template.setDefaultSerializer(jacksonSeial);
        return template;
    }

    
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换
        RedisSerializer strSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
        // 解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
        // 定制缓存数据序列化方式及时效
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(7))   // 设置缓存有效期为1天
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(strSerializer))
                .serializevaluesWith(RedisSerializationContext.SerializationPair.fromSerializer(jacksonSeial))
                .disableCachingNullValues();   // 对空数据不进行缓存
        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();
        return cacheManager;
    }
}

==实际应用:当用户访问网址推荐列表时,首先查看redis中是否存在,如果存在,直接返回,如果不存在,则从数据库获取并存放到redis中 ==

     
    @Override
    public List recommendList() {
        List sites=null;
        Object o=redisTemplate.opsForValue().get("recommendList");//查找
        if(o!=null){
            sites=(List) o;
        }else {
            sites=this.siteMapper.recommendList();
            if (!sites.isEmpty()) {
                redisTemplate.opsForValue().set("recommendList", sites);//存放
            }
        }
        return sites;
    }
结语

希望我们之后都能理解底层,共同进步。
后端源码:
链接:https://pan.baidu.com/s/1uc4b_8ZgYvJKp1M9Ed9WBA
提取码:3c4d

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/770350.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号