首页 > 其他分享 >牛客网

牛客网

时间:2023-08-20 13:46:11浏览次数:28  
标签:map return String 牛客 session user public

牛客网项目

发送邮件

邮箱设置

启用客户端SMTP服务

Spring Email

导入jar包

邮箱参数配置

使用javaMailSender 发送邮件

模板引擎

使用Thymeleaf发送HTML邮件

1.新建MailClient类

@Component
public class MailClient {

   private static final Logger logger = LoggerFactory.getLogger(MailClient.class);

   @Autowired
   private JavaMailSender mailSender;

   @Value("${spring.mail.username}")
   private String from;

   public void sendMail(String to, String subject, String content) {
       try {
           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());
      } catch (MessagingException e) {
           logger.error("发送邮件失败:" + e.getMessage());
      }
  }

}

2.更改配置

#发送邮件
#MialProperties
spring.mail.host=smtp.sina.com
spring.mail.port=465
[email protected]
spring.mail.password=357ab4337a0ade10
spring.mail.protocol=smtps
spring.mail.properties.mail.smpt.ssl.enable=true

3.新建templates邮件模板

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="UTF-8">
   <title>邮件示例</title>
</head>
<body>
<p>欢迎你,<span style="color: red;" th:text="${username}"></span>!</p>
</body>
</html>

4.新建测试类Mail Tests

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class MailTests {

   @Autowired
   private MailClient mailClient;

   //   模板引擎
   @Autowired
   private TemplateEngine templateEngine;

   @Test
   public void testTextMail() {
       // 把邮箱密码改为授权码后,错误解决
       mailClient.sendMail("[email protected]", "TEST", "Welcome.");
  }

    //尝试发送html邮件
   @Test
   public void testHtmlMail() {
       Context context = new Context();
       context.setVariable("username", "sunday");

       String content = templateEngine.process("/mail/demo", context);
       System.out.println(content);

       mailClient.sendMail("[email protected]", "HTML", content);
  }

}

测试结果

 

 

开发注册功能

三层架构:数据访问层 业务层 视图层

访问注册页面

点击顶部区域内链接,打开注册页面

User Service

@Service
public class UserService implements CommunityConstant {

   @Autowired
   private UserMapper userMapper;

   @Autowired
   private MailClient mailClient;

   @Autowired
   private TemplateEngine templateEngine;

   @Value("${community.path.domain}")
   private String domain;

   @Value("${server.servlet.context-path}")
   private String contextPath;

   public User findUserById(int id) {
       return userMapper.selectById(id);
  }

Login Controller

@Controller
public class LoginController implements CommunityConstant {

   @Autowired
   private UserService userService;
    //引入路径 注册
   @RequestMapping(path = "/register", method = RequestMethod.GET)
   public String getRegisterPage() {
       return "/site/register";
  }
   //登录
   @RequestMapping(path = "/login", method = RequestMethod.GET)
   public String getLoginPage() {
       return "/site/login";
  }

提交注册数据

-通过表单提交数据。

-服务端验证账号是否已存在,邮箱是否已注册。

-服务端发送激活邮件。

User Service

public Map<String, Object> register(User user) {
   Map<String, Object> map = new HashMap<>();

   // 空值处理
   if (user == null) {
       throw new IllegalArgumentException("参数不能为空!");
  }
   if (StringUtils.isBlank(user.getUsername())) {
       map.put("usernameMsg", "账号不能为空!");
       return map;
  }
   if (StringUtils.isBlank(user.getPassword())) {
       map.put("passwordMsg", "密码不能为空!");
       return map;
  }
   if (StringUtils.isBlank(user.getEmail())) {
       map.put("emailMsg", "邮箱不能为空!");
       return map;
  }

   // 验证账号
   User u = userMapper.selectByName(user.getUsername());
   if (u != null) {
       map.put("usernameMsg", "该账号已存在!");
       return map;
  }

   // 验证邮箱
   u = userMapper.selectByEmail(user.getEmail());
   if (u != null) {
       map.put("emailMsg", "该邮箱已被注册!");
       return map;
  }

   // 注册用户
   user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
   user.setPassword(CommunityUtil.md5(user.getPassword() + user.getSalt()));
   user.setType(0);
   user.setStatus(0);
   user.setActivationCode(CommunityUtil.generateUUID());
   user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000)));
   user.setCreateTime(new Date());
   userMapper.insertUser(user);

Login Controller

@RequestMapping(path = "/register", method = RequestMethod.POST)
public String register(Model model, User user) {
   Map<String, Object> map = userService.register(user);
   if (map == null || map.isEmpty()) {
       model.addAttribute("msg", "注册成功,我们已经向您的邮箱发送了一封激活邮件,请尽快激活!");
       model.addAttribute("target", "/index");
       return "/site/operate-result";
  } else {
       model.addAttribute("usernameMsg", map.get("usernameMsg"));
       model.addAttribute("passwordMsg", map.get("passwordMsg"));
       model.addAttribute("emailMsg", map.get("emailMsg"));
       return "/site/register";
  }
}

激活注册账号

点击邮件中的链接,访问服务端的激活服务。

User Service

 // 激活邮件
Context context = new Context();
context.setVariable("email", user.getEmail());
// http://localhost:8080/community/activation/101/code
String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode();
context.setVariable("url", url);
String content = templateEngine.process("/mail/activation", context);
mailClient.sendMail(user.getEmail(), "激活账号", content);

return map;
}
//激活账号
public int activation(int userId, String code) {
User user = userMapper.selectById(userId);
if (user.getStatus() == 1) {
return ACTIVATION_REPEAT;
} else if (user.getActivationCode().equals(code)) {
userMapper.updateStatus(userId, 1);
return ACTIVATION_SUCCESS;
} else {
return ACTIVATION_FAILURE;
}
}

Login Controller

// http://localhost:8080/community/activation/101/code
@RequestMapping(path = "/activation/{userId}/{code}", method = RequestMethod.GET)
public String activation(Model model, @PathVariable("userId") int userId, @PathVariable("code") String code) {
int result = userService.activation(userId, code);
if (result == ACTIVATION_SUCCESS) {
model.addAttribute("msg", "激活成功,您的账号已经可以正常使用了!");
model.addAttribute("target", "/login");
} else if (result == ACTIVATION_REPEAT) {
model.addAttribute("msg", "无效操作,该账号已经激活过了!");
model.addAttribute("target", "/index");
} else {
model.addAttribute("msg", "激活失败,您提供的激活码不正确!");
model.addAttribute("target", "/index");
}
return "/site/operate-result";
}

新建CommunityConstant接口

public interface CommunityConstant {
// 激活成功
int ACTIVATION_SUCCESS= 0;

//重复激活
int ACTIVATION_REPEAT =1;
//激活失败
int ACTIVATION_FAILURE = 2;
}

测试结果

 

 

 

 

会话管理

Http的基本性质

Http是简单的

Http是可扩展的

Http是无状态的,有会话的

Cookie

是服务器发送到浏览器,并保存在浏览器的一小块数据。

浏览器下次访问该服务器时,会自动携带酷块该数据,将其发送给服务器。

Cookie可以创建有状态的会话。

Session

是JavaEE的标准,用于在服务端记录客户信息。

数据存放在服务器端更安全,但是也会增加服务端的内存压力。

//cookie示例
@RequestMapping(path = "/cookie/set",method = RequestMethod.GET)
@ResponseBody
public String setCookie(HttpServletResponse response){
//创建cookie
Cookie cookie = new Cookie("code", CommunityUtil.generateUUID());//随机生成字符串
//设置cookie生效范围
cookie.setPath("/community/alpha");
//设置cookie存储时间
response.addCookie(cookie);
return "set cookie";
}
@RequestMapping(path = "/cookie/set",method = RequestMethod.GET)
@ResponseBody
public String getCookie(@CookieValue("code") String code){
System.out.println(code);
return "get cookie";
}

cookie不安全性高

访问服务器增加数据量,对流量性能产生影响

Session依赖cookie

// session示例

@RequestMapping(path = "/session/set", method = RequestMethod.GET)
@ResponseBody
public String setSession(HttpSession session) {
//可以存取大量数据
session.setAttribute("id", 1);
session.setAttribute("name", "Test");
return "set session";
}

@RequestMapping(path = "/session/get", method = RequestMethod.GET)
@ResponseBody
public String getSession(HttpSession session) {
System.out.println(session.getAttribute("id"));
System.out.println(session.getAttribute("name"));
return "get session";
}

 

同步session

共享session

 

生成验证码

Kaptcha

导入jar包

<dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>

编写Kaptcha 配置类

生成随机字符,生成图片

官方路径: (FQ)

@Configuration
public class KaptchaConfig {

@Bean
public 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;
}

LoginController

//声明日志
private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

@Autowired
private UserService userService;

//声明验证码
@Autowired
private Producer kaptchaProducer;
 //验证码
@RequestMapping(path = "/kaptcha", method = RequestMethod.GET)
public void getKaptcha(HttpServletResponse response, HttpSession session) {
// 生成验证码
String text = kaptchaProducer.createText();
BufferedImage image = kaptchaProducer.createImage(text);

// 将验证码存入session
session.setAttribute("kaptcha", text);

// 将突图片输出给浏览器
response.setContentType("image/png");
try {
OutputStream os = response.getOutputStream();
ImageIO.write(image, "png", os);
} catch (IOException e) {
//日志
logger.error("响应验证码失败:" + e.getMessage());
}
}

https://releases.jquery.com/

标签:map,return,String,牛客,session,user,public
From: https://www.cnblogs.com/tong11/p/17643908.html

相关文章

  • 一道牛客题相关的思考
    牛客多校202310H:\(F_0(x)=x\)\(F_k(x)=(x^2-1)F'_{k-1}(x)\)给定\(x_0\),求\(F_n(x_0)\)。场上我的做法:设\(f_{i,j}\)为\(F_i\)求\(j\)次导后,\(x_0\)的点值。那可以导出递推式:\(f_{i,j}=f_{i-1,j-1}\timesj(j-1)+f_{i,j}\timesj\times2x_0+f_{i-1......
  • 暑假牛客多校第九场 2023-8-15(D、I)
    未补完D.Non-Puzzle:ErrorPermutation算法:差分做法:   考虑题目的数据,我们的做法可以先枚举出不合法的区间数,然后由区间总数减去不合法区间数。我们首先确定一个数,令这个数就是包含这个数的一段区间的不和法值,即这个数是第\(i\)小的数。一开始我们使这段区间大小......
  • 牛客多校赛第9场G Game
    黑板上有一些数字,Alice和Bob轮流操作,每次操作可以选择黑板上的两个数(两个数可以相同),然后在黑板上写下这两个数的异或。谁先写出k谁赢。首先重复的数字是没有用的,进而可以推出除整局游戏的第一步之外,都可以选择保持当前的局面不变.比如如果一个玩家面对的是一个必输的局面,他就......
  • 牛客多校赛第9场D Error Permutaition
    给定一个长度为n的排列,计算满足条件的子区间的个数。对于子区间\([l,r]\)要求任意区间第k小,不在区间的第k个位置上。\(n<=5000\)从每个值入手,设这个值为先,寻找对于x来讲是不合法的区间,也就是x在这个区间中是第k小,并且在区间的第k个位置上。1.如果固定区间左端点l,那么右端......
  • 2023牛客暑期多校训练营8
    A.AliveFossils纯模拟没啥好说的map<string,int>mp;voidsolve(){intn;cin>>n;for(inti=1;i<=n;i++){intt;cin>>t;while(t--){strings;cin>>s;mp[s]++;}}......
  • 2023牛客暑期多校训练营7
    C.BeautifulSequence题意:有长为\(n\)的数组\(a\),通过操作\(a_i\oplusa_{i+1}\)得到\(b_i\),现在给出数组\(b\),求出字典序第\(k\)小的数组\(a\)Solution不难发现,如果确定了\(a_1\)的某一二进制位上的数,就可以确定整个数组\(a\)的这一位上的数,我们首先把所有的二进制位数都变......
  • 2023牛客暑期多校训练营9--I Non-Puzzle: Segment Pair
    思路:直接枚举区间左端点,用一个cnt数组表示当前端点l,r或者L,R存在1个还是2个或者0个。用一个sum变量记录有多少段区间覆盖了该端点,如果sum==n那么这个端点就有了贡献。更详细的看代码注释。#include<bits/stdc++.h>usingnamespacestd;#defineIOSios::sync_with_stdio(fa......
  • 2023牛客多校(9)
    D首先考虑枚举一个左端点然后我们就会发现,对于一个位置来说,会影响它的只有前缀和后缀比它小的数于是让每个数字不合法的都是一个区间可以预处理$[L,i]$这个范围内有几个比它小的数,设为$x$然后就能知道第一个让它不合法的位置($i-L-x$)个比它小的数的位置而让它重新合法......
  • 2023牛客多校第九场 D Non-Puzzle: Error Permutation
    题意给定一个长度为n的序列,计算有多少个子区间满足子区间第K小的数不在子区间第K位。 找出所有不满足条件的区间。枚举所有的ai和左端点al,找出满足ai是区间[l,r]中第r-l+1小的右端点r,则右端点r一定是一段区间。例如   342165         l i ......
  • 23牛客多校9 I Non-Puzzle: Segment Pair
    也许更好的阅读体验\(\mathcal{Description}\)给\(n\)对区间,要求每对区间恰好选一个使得选出来的\(n\)个区间有交集,问有多少方案数\(1\len,l_i,r_i\le5×10^5\)\(\mathcal{Solution}\)注意到区间的值域也是\(5×10^5\),考虑从值域入手,也就是枚举每个点看有多少种方案使最后......