学习笔记:基于SpringBoot的牛客网社区项目实现(五)之登陆模块
创始人
2025-06-01 03:52:08

一、发送邮件

发送邮件主要使用JavaMailSender类,使用send方法,send方法需要MimeMessage类型的参数。

void send(MimeMessage var1)

使用createMimeMessage()方法并用MimeMessage类型接收。再创建MimeMessageHelper()对象,添加一些数据。

MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);

最后发送邮件

mailSender.send(helper.getMimeMessage());

二、Cookie和Session的使用 

 Cookie

        因为是服务器发送给浏览器的,所以加上HttpServletResponse对象,给浏览器返回数据。创建cookie直接new Cookie对象就可以了,然后设置cookie的内容,生效范围,生存时间,最后通过response发送cookie。得到cookie直接使用注解@CookieValue,很方便。

//cookie示例@RequestMapping(path = "/cookie/set", method = RequestMethod.GET)@ResponseBodypublic String setCookie(HttpServletResponse response) {//创建cookieCookie cookie = new Cookie("code", CommunityUtil.generateUUID());//设置cookie生效的范围cookie.setPath("/community/alpha");//设置cookie生存时间cookie.setMaxAge(60 * 10);//10min//发送cookieresponse.addCookie(cookie);return "set cookie";}@RequestMapping(path = "/cookie/get", method = RequestMethod.GET)@ResponseBodypublic String getCookie(@CookieValue("code") String code) {System.out.println(code);return "get cookie";}

Session

 Session是存在服务端的,使用HttpSession对象创建,然后setAttribute信息。

//session示例@RequestMapping(path = "/session/set", method = RequestMethod.GET)@ResponseBodypublic String setSession(HttpSession session) {session.setAttribute("id", 1);session.setAttribute("name", "Test");return "set session";}@RequestMapping(path = "/session/get", method = RequestMethod.GET)@ResponseBodypublic String getSession(HttpSession session) {System.out.println(session.getAttribute("id"));System.out.println(session.getAttribute("name"));return "get session";}

三、生成验证码

package com.nowcoder.community.config;import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Properties;@Configuration
public class KaptchaConfig {@Beanpublic Producer kaptchaProducer() {Properties properties = new Properties();properties.setProperty("kaptcha.image.width", "100");properties.setProperty("kaptcha.image.height", "40");properties.setProperty("kaptcha.textproducer.font.size", "32");properties.setProperty("kaptcha.textproducer.font.color", "0,0,0");properties.setProperty("kaptcha.textproducer.char.string", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYAZ");properties.setProperty("kaptcha.textproducer.char.length", "4");properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");DefaultKaptcha kaptcha = new DefaultKaptcha();Config config = new Config(properties);kaptcha.setConfig(config);return kaptcha;}}

 生成文字的验证码放入session中,方便后续登录输入的验证码是否正确,最后生成图片验证码输出到浏览器中。

@RequestMapping(path = "/kaptcha", method = RequestMethod.GET)public void getKaptcha(HttpServletResponse response, HttpSession session) {// 生成验证码String text = kaptchaProducer.createText();BufferedImage image = kaptchaProducer.createImage(text);// 将验证码存入sessionsession.setAttribute("kaptcha", text);// 将图片输出给浏览器response.setContentType("image/png");try {OutputStream os = response.getOutputStream();ImageIO.write(image, "png", os);//image:图片对象,"bmg" :图片格式, filWriterOne 需要写入的地方} catch (IOException e) {logger.error("响应验证码失败:" + e.getMessage());}}

ServletOutputStream getOutputStream()

获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,再由Tomcat服务器将字节内容组成Http响应返回给浏览器。

response.getWriter().write("字符串"),这个方法只能写字符串。如果要写字节,比如,传个图片,怎么办呢?就要靠response.getOutputStream()

四、登录功能实现
 

 @RequestMapping(path = "/login", method = RequestMethod.POST)public String login(String username, String password, String code, boolean rememberme,Model model, HttpSession session, HttpServletResponse response) {// 检查验证码String kaptcha = (String) session.getAttribute("kaptcha");if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)) {model.addAttribute("codeMsg", "验证码不正确!");return "/site/login";}// 检查账号,密码int expiredSeconds = rememberme ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;Map map = userService.login(username, password, expiredSeconds);if (map.containsKey("ticket")) {Cookie cookie = new Cookie("ticket", map.get("ticket").toString());cookie.setPath(contextPath);cookie.setMaxAge(expiredSeconds);response.addCookie(cookie);return "redirect:/index";} else {model.addAttribute("usernameMsg", map.get("usernameMsg"));model.addAttribute("passwordMsg", map.get("passwordMsg"));return "/site/login";}}
@RequestMapping(path = "/logout", method = RequestMethod.GET)public String logout(@CookieValue("ticket") String ticket) {userService.logout(ticket);return "redirect:/login";}

五、拦截器的应用

        有许多请求同一个方法,统一对这些请求处理,比如访问账号设置一定要在用户登录的情况下才能访问,那么访问用户是否登录这个功能便可以使用拦截器进行实现。

package com.nowcoder.community.controller.interceptor;import com.nowcoder.community.annotation.LoginRequired;
import com.nowcoder.community.util.HostHolder;
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;
import java.lang.reflect.Method;@Component
public class LoginRequiredInterceptor implements HandlerInterceptor {@Autowiredprivate HostHolder hostHolder;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();LoginRequired loginRequired = method.getAnnotation(LoginRequired.class);if (loginRequired != null && hostHolder.getUser() == null) {response.sendRedirect(request.getContextPath() + "/login");return false;}}return true;}
}

 六、账号设置

@LoginRequired@RequestMapping(path = "/upload", method = RequestMethod.POST)public String uploadHeader(MultipartFile headerImage, Model model) {if (headerImage == null) {model.addAttribute("error", "您还没有选择图片!");return "/site/setting";}String fileName = headerImage.getOriginalFilename();String suffix = fileName.substring(fileName.lastIndexOf("."));if (StringUtils.isBlank(suffix)) {model.addAttribute("error", "文件的格式不正确!");return "/site/setting";}// 生成随机文件名fileName = CommunityUtil.generateUUID() + suffix;// 确定文件存放的路径File dest = new File(uploadPath + "/" + fileName);try {// 存储文件headerImage.transferTo(dest);} catch (IOException e) {logger.error("上传文件失败: " + e.getMessage());throw new RuntimeException("上传文件失败,服务器发生异常!", e);}// 更新当前用户的头像的路径(web访问路径)// http://localhost:8080/community/user/header/xxx.pngUser user = hostHolder.getUser();String headerUrl = domain + contextPath + "/user/header/" + fileName;userService.updateHeader(user.getId(), headerUrl);return "redirect:/index";}@RequestMapping(path = "/header/{fileName}", method = RequestMethod.GET)public void getHeader(@PathVariable("fileName") String fileName, HttpServletResponse response) {// 服务器存放路径fileName = uploadPath + "/" + fileName;// 文件后缀String suffix = fileName.substring(fileName.lastIndexOf("."));// 响应图片response.setContentType("image/" + suffix);try (FileInputStream fis = new FileInputStream(fileName);//需要自己关闭OutputStream os = response.getOutputStream();//SpringMVC会自动关闭) {byte[] buffer = new byte[1024];int b = 0;while ((b = fis.read(buffer)) != -1) {os.write(buffer, 0, b);}} catch (IOException e) {logger.error("读取头像失败: " + e.getMessage());}}

 

相关内容

热门资讯

今日起招股发售价9.75港元,... 6月2日,车来了母公司元光科技启动全球发售,发售价9.75港元,预计将在6月10日在港交所挂牌。元光...
港股午评:恒生指数跌2.20%... 新京报贝壳财经讯 6月2日,港股午间收盘,恒生指数跌2.20%,恒生科技指数跌2.43%。石药集团跌...
夏乐:美债压力与美元走弱 全球... 原创 财联社 蜂网专家2025年05月29日《首席说》是财联社倾力打造的一档高端直播联线栏目。面向泛...
罗志恒:财政政策不应受3%赤字... 罗志恒系粤开证券首席经济学家、中国首席经济学家论坛理事自2008年以来,本轮积极财政政策实行了长达1...
三大利空,突袭! 三大利空,突... 时局依然不稳!今天早上,全球市场全线杀跌。日经指数一度杀跌近1.5%,中国台湾股指大跌近1%,港股三...
美国客户“疯狂”催单 这家川企... 自硬公司的精密零件产品之一:随钻用核心零部件。韩吉尔摄 “5月中旬,美国休斯敦的客户发邮件,要求尽快...
这只港股,突然暴涨超60%!发... 6月2日,亚太股市开盘后持续走弱。不过,港股方面,加密货币数字概念股大涨,连连数字涨62.67%。港...
招商基金三首席同日上任!“去管... 当同行纷纷为投研人才做“去管理化”减法时,招商基金却反其道而行之,提拔朱红裕、王景两位基金经理。这究...
2025浙江国际电子商务博览会... 这个周末,端午的粽叶飘香和六一小朋友的欢笑声撞了个满怀~跨境电商圈也跟着热闹到飞起。 从节令美食到文...
头部餐饮,火拼儿童餐 头部餐饮... 总第4234期作者 |餐饮老板内参内参君儿童餐,卷入next level端午恰逢六一,双节叠加背景下...
舆论战升级!巨子生物深夜回应,... 2025.06.02本文字数:2490,阅读时长大约4分钟作者 |第一财经 刘晓颖重组胶原蛋白成分之...
财经时评|以创新厚度重塑汽车产... 作者 远山中国汽车工业协会与工业和信息化部近期针对行业“内卷式”竞争的联合发声,为持续蔓延的价格战按...
恒生指数午盘下跌2.20%,恒... 6月2日午盘,香港恒生指数下跌2.20%,报22778.45点;恒生科技指数下跌2.43%,报504...
“以旧换新”带货1万亿,中国何... “美国想让制造业回流成为中国的样子,一个踏实劳作的‘生产者社会’;而中国想努力扩大消费成为美国的样子...
恒指半日跌2.2% 恒指半日跌... 【恒指半日跌2.2%】截至午间收盘,香港恒生指数下跌2.20%,报22778.45点;恒生科技指数下...
“成分之争”舆论战升级,巨子生... 重组胶原蛋白成分之争的舆论战再度升级。美妆博主 "大嘴博士" (郝宇)近日连续发文质疑,巨子生物(0...
汇川技术新注册《InoCube... 证券之星消息,近日汇川技术(300124)新注册了《InoCube-InoData数据分析系统V1....
博将控股多家所投企业荣登202... 博将控股多家所投企业荣登2025杭州独角兽与准独角兽榜单 2025年4月24日,由民建浙江省委会、浙...
刚刚,A50直线跳水!亚太股市... 6月2日,亚太股市开盘后持续走弱。富时中国A50期货开盘跌0.6%,截至目前跌幅1.91%。 截至...
问界、智界、享界、尊界,202... 2025鸿蒙智行:四界表现鸿蒙智行作为国内造车新势力的主流品牌,一共规划了“五界”车型,包括:问界、...
花样年控股:重组支持协议的最后... 6月1日,花样年控股(01777.HK)公告称,公司2024年4月29日所订立的重组支持协议的最终截...
蜜雪集团股价创上市以来新高 蜜... 新京报贝壳财经讯 6月2日,港股蜜雪集团盘中涨超7%,股价刷新上市新高。
美单边关税让全球经济面临更大不... 美国征收关税的对象和标准可能随意变更,其关税政策具有不可预测性。无论是外国企业,还是美国本土企业,都...
桃李面包创始人向其两儿子转让3... 5月30日晚间,桃李面包(沪市代码:603866)公告称,公司控股股东及实际控制人吴志刚通过大宗交易...
前4月东莞重大项目完成投资42... 本期看点:前4月东莞重大项目完成投资429.09亿元;长联科技募投项目提升年产至2.77万吨;广东省...
恒生指数跌幅扩大至2%,医药、... 6月2日,恒生指数跌幅扩大至2%,医药、地产、能源板块跌幅居前,美中嘉和跌超14%,石四药集团跌近1...
港股、A50飘绿,亚太市场多数... 早间,亚太市场多数下跌。港股、A50集体下跌其中,恒生指数、恒生科技指数开盘跌幅扩大, 港股生物技术...
雷军看好的两兄弟,要IPO了 ... 2021年夏,小米产业园办公室内,雷军饶有兴致地打量眼前一对兄弟,“为什么张波是创始人,董事长却是张...
圣阳股份涨1.66%,成交额9... 5月30日,圣阳股份涨1.66%,成交额9.82亿元,换手率15.03%,总市值66.67亿元。 异...