0%

准备工作

配置域名
1
2
#community
community.path.domain=http://localhost:8080
封装生成随机字符串工具类(UUID),拼接随机字符串后MD5加密

注册整体逻辑

Service
  • 主要目标:接收Controller传递来的User对象,判断是否合法,合法则添加进User表,发送激活邮件。返回给Controller错误信息。
  • 不合法类型
    • 填写值为空
    • 账号已存在
    • 邮箱已注册
    • 密码格式不合法(还未实现)
  • 使用map记录不合法信息
  • 若合法则发送激活邮件
Controller
  • 主要目标:接受用户注册的POST请求,将User对象传递给Service。向用户显示注册成功与否的信息
  • 若无错误信息,跳转到operate-result界面,显示注册成功信息
  • 若有错误,返回register界面,渲染html界面,显示错误信息并保留用户上次填写的信息

激活邮件设置

  • 创建激活结果的工具接口
  • Service:接收激活url中的userId和激活码,到数据库中查询,返回激活工具接口中的结果
  • Controller:形参使用@PathVariable注解提取@RequestMapping中path的变量,判断激活结果,渲染html

  • 导入jar包

  • 邮箱参数配置

    1
    2
    3
    4
    5
    6
    7
    #Spring Boot Starter Mail
    spring.mail.host=smtp.qq.com
    spring.mail.port=465
    spring.mail.username=邮箱
    spring.mail.password=授权码
    spring.mail.protocol=smtps
    spring.mail.properties.mail.smtp.ssl.enable=true
  • 使用JavaMailSender发送邮件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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());
    }
    }

使用Thymeleaf发送HTML文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Autowired
private MailClient mailClient;

@Autowired
private TemplateEngine templateEngine;

@Test
public void testHtmlMail() {
Context context = new Context();
context.setVariable("username", "sunday");

String content = templateEngine.process("/mail/activation", context);
mailClient.sendMail("abc@qq.com", "测试邮件", content);
}

Cookie基本使用

  • Cookie:客户会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问

  • 发送Cookie

    • 创建Cookie对象,设置数据

      1
      Cookie cookie = new Cookie("key", "value");
    • 设置Cookie生效范围

      1
      cookie.setPath("路径");
    • 发送Cookie到客户端:使用response对象

      1
      response.addCookie(cookie);
  • 获取Cookie

    • 获取客户端携带的所有Cookie,使用request对象

      1
      Cookiep[] cookies = request.getCookies();
    • 使用Cookie对象方法获取数据

      1
      2
      cookie.getName();
      cookie.getValue();
    • 使用@CookieValue注解获取指定Cookie

      1
      2
      3
      public void getCookie(@CookieValue("code") String code) {
      System.out.println(code);
      }

Cookie原理

  • Cookie的实现基于HTTP协议
    • 响应头:set-cookie
    • 请求头:cookie

Cookie使用细节

  • Cookie存活时间
    • 存储在浏览器内存中默认当浏览器关闭,内存释放,Cookie被销毁
    • setMaxAge(int seconds):设置Cookie存活时间
      • 正数:将Cookie写入浏览器所在电脑硬盘,持久化存储,到时间自动删除
      • 负数:默认值
      • 零:删除对应Cookie
  • Cookie不能直接存储中文,需要转码:URL编码(String URLEncoder.encode(String, “utf-8”))

Cookie与Session的区别

  • 存储位置:Cookie是将数据存储在客户端,Session存储在服务器端
  • 安全性:Cookie不安全,Session安全
  • 数据大小:Cookie 3kb,Session无限制
  • 存储时间:Cookie可长期存储,Session默认30分钟
  • 服务器性能:Cookie不占用服务器资源,Session占用

  • 三层架构
    • 表现层,业务层,数据访问层
  • MVC
    • Model:模型层
    • View:视图层
    • Controller:控制层
  • 核心组件
    • 前端控制器:DispatcherServlet

接受HTTPget请求传参的两种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Controller
@RequestMapping("/alpha")
public class AlphaController{

//方式1
@RequestMapping(path = "/students", method = RequestMethod.GET)
@ResponseBody
public String getStudents(
@RequestParam(name="current", required = false, defaultValue = "1") int current,
@RequestParam(name="limit", required = false, defaultValue = "10") int limit){

System.out.println(current);
System.out.println(limit);
return "some students";
}

//方式2
@RequestMapping(path = "/student/{id}", method = RequestMethod.GET)
@ResponseBody
public String getStudent(@PathVariable("id") int id){
System.out.println(id);
return "a student";
}
}

接受HTTPpost请求提交数据

1
2
3
4
5
6
7
@RequestMapping(path = "/student", method = RequestMethod.POST)
@ResponseBody
public String saveStudent(String name, int age){
System.out.println(name);
System.out.println(age);
return "success";
}

利用thymeleaf向浏览器显示动态数据

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Teacher</title>
</head>
<body>
<p th:text="${name}"></p>
<p th:text="${age}"></p>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
方式1
@RequestMapping(path = "/teacher", method = RequestMethod.GET)
public ModelAndView getTeacher(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("name", "张三");
modelAndView.addObject("age", 30);
modelAndView.setViewName("/demo/view");
return modelAndView;
}

方式2
@RequestMapping(path = "/school", method = RequestMethod.GET)
public String getSchool(Model model){
model.addAttribute("name", "寄大学");
model.addAttribute("age", 7);
return "/demo/view";
}

向浏览器返回Json格式数据举例

1
2
3
4
5
6
7
8
9
@RequestMapping(path = "/emp", method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> getEmp(){
Map<String, Object> emp = new HashMap<>();
emp.put("name", "张三");
emp.put("age", 30);
emp.put("salary", 9000);
return emp;
}

Spring全家桶

  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Cloud Data Flow

Spring Framework

  • Spring Core
    • IOC, AOP
  • Spring Data Access
    • Transactions, Spring MyBatis
  • Web Servlet
    • Spring MVC
  • Integration
    • Emain, Scheduling, AMQP, Security

Spring IoC

  • Inversion of Control
    • 控制反转,是一种面向对象编程的设计思想
  • Dependency Injection
    • 依赖注入,是IoC思想的实现方式
  • IoC Container
    • IoC容器,是实现依赖注入的关键,本质上是一个工厂

四种类型注解

注解 说明
@Component 组件注解,通用注解,被该注解描述的类将被IoC容器管理并实例化
@Controller 语义注解,说明当前类是mvc应用中的控制器,用于接收用户的输入,调用Service的方法以及向客户端返回结果
@Service 语义注解,说明当前类是Service业务服务类,用于实现功能的最核心代码,通常这种类都是以xxxservice结尾
@Repository 语义注解,说明当前类用于业务持久层,通常描述对应的Dao类,负责与数据库实现增删改查的Dao类

Controller -> Service -> Dao

从Srping容器获取bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
class CommunityApplicationTests implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}

@Test
public void testApplicationContext(){
AlphaDao alphaDao = applicationContext.getBean("AlphaHibernate", AlphaDao.class);
System.out.println(alphaDao.select());
}
}

Bean注入

1
2
@Autowired
private AlphaDao alphaDao;

  • 核心作用
    • 起步依赖
    • 自动配置
    • 端点监控

使用spring initializer快速生成SringBoot项目

Hello,SpringBoot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.nowcoder.community.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/alpha")
public class AlphaController {

@RequestMapping("/hello")
@ResponseBody
public String sayHello() {
return "Hello, SpringBoot";
}
}

修改SpringBoot的Tomcat服务器端口

在application.properties中写入:server.port=[端口号]

修改项目访问路径(默认为空)

在application.properties中写入:server.servlet.context-path=[路径]

  • MVC是一种分层开发的模式,其中:
    • M:Model,业务模型,处理业务
    • V:View,视图,页面展示
    • C:Controller,控制器,处理请求,调用模型和视图
  • 三层架构
    • 表现层:接受请求,封装数据,调用业务逻辑层,响应数据(.web/controller),框架如SpringMVC
    • 业务逻辑层:对业务逻辑进行封装,组合数据访问层中基本功能,形成复杂逻辑功能(.service),框架如Spring
    • 数据访问层(持久层):对数据库进行CRUD操作(.dao/mapper),框架如MyBatis

JavaBean:业务逻辑层 + 数据访问层

HTTP是无状态的

  • 服务器无法判断这两次请求是否为同一个客户端发出
  • 通过会话跟踪技术解决无状态问题

输出sessionID
1
2
3
4
5
6
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get..");
HttpSession session = req.getSession(); //若参数为false,没有会返回null,不创建新的会话
System.out.println("sessionID:" + session.getId());
}
最大闲置时间

默认:1800秒

1
2
3
4
5
6
7
8
// 获取默认的最大闲置时间
int maxInactiveIntervalSecond = session.getMaxInactiveInterval(); //非激活间隔时长
System.out.println("maxInactiveIntervalSecond = " + maxInactiveIntervalSecond);

// 设置默认的最大闲置时间
session.setMaxInactiveInterval(15);

session.invalidate(); //强制失效

Session保存作用域

  • 是和具体的某一个session唯一对应的
  • 常用API
1
2
3
4
HttpSession session = req.getSession();
session.setAttribute("username", "Bob"); //向当前session保存作用域保存一个数据
session.getAttribute("username"); //从当前session保存作用域获取指定key对应的value
session.removeAttribute("username");

  • 查询一个实体类对象
  • 查询一个list集合
  • 查询单个数据
  • 查询一条数据为map的集合
1
2
3
4
5
6
7
@Test
public void testMybatis() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
Map<String, Object> result = parameterMapper. getUserByIdToMap(2);
System.out.println(result);
}
1
2
3
4
<!--Map<String, Object> getUserByIdToMap(@Param("id") int id)-->
<select id="getUserByIdToMap" resultType="java.util.Map">
select * from t_user where id = #{id}
</select>
  • 查询多条数据为map的集合
1
2
3
4
5
6
7
@Test
public void testMybatis() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
List<Map<String, Object>> result = parameterMapper. getUserByIdToMap();
result.forEach(mp -> System.out.println(mp));
}
1
2
3
4
<!--List<Map<String, Object>> getUserByIdToMap()-->
<select id="getUserByIdToMap" resultType="Map">
select * from t_user
</select>
使用@MapKey注解,定义唯一键,将每条数据转换的map集合作为值
1
2
3
4
5
6
7
@Test
public void testMybatis() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
Map<Integer, Object> result = parameterMapper. getUserByIdToMap();
result.forEach((id, obj) -> System.out.println(obj));
}
1
2
@MapKey("id")
Map<Integer, Object> getUserByIdToMap();
1
2
3
4
<!--Map<Integer, Object> getUserByIdToMap()-->
<select id="getUserByIdToMap" resultType="Map">
select * from t_user
</select>