仿论坛项目--初识Spring Boot

1. 技术准备

技术架构

• Spring Boot
• Spring、Spring MVC、MyBatis
• Redis、Kafka、Elasticsearch
• Spring Security、Spring Actuator

开发环境

• 构建工具:Apache Maven
• 集成开发工具:IntelliJ IDEA
• 数据库:MySQL、Redis
• 应用服务器:Apache Tomcat
• 版本控制工具:Git
在这里插入图片描述

2. 搭建开发环境

Apache Maven
• 可以帮助我们构建项目、管理项目中的jar包
• Maven仓库:存放构件的位置

  • 本地仓库:默认是 ~/.m2/repository
  • 远程仓库:中央仓库、镜像仓库、私服仓库
    • 示例:安装、配置、常用命令
    http://maven.apache.org
    安装配置版本:apache-maven-3.6.1-bin.zip

改成阿里云的镜像仓库
在conf文件夹下修改settings.html

<mirror>
  <id>alimaven</id>
  <mirrorOf>central</mirrorOf>
  <name>aliyun maven</name>
  <url>https://maven.aliyun.com/repository/central</url>
</mirror>

配置好后在系统环境变量path上新建一条
E:\work\apache-maven-3.6.1-bin\apache-maven-3.6.1\bin

输入命令行:mvn -version 出现以下信息就是安装成功了。(首先要配置好JDK)
在这里插入图片描述

IntelliJ IDEA
• 目前最流行的Java集成开发工具
• 示例:安装、配置、创建项目
http://www.jetbrains.com/idea

Spring Initializr
• 创建 Spring Boot 项目的引导工具
• 示例:创建“论坛社区”项目
https://start.spring.io

Spring Boot 入门示例
• Spring Boot 核心作用

  • 起步依赖、自动配置、端点监控
    • 示例
  • 一个简单的处理客户端请求案例

@ResponseBody 是一个在 Spring 框架中常用的注解,主要用于 Web 层的控制器(Controller)方法上。它的主要功能是将方法的返回值直接写入 HTTP 响应的主体(Body)部分,而不是使用视图解析器(ViewResolver)生成视图。这意味着,当一个控制器方法被标注了 @ResponseBody,Spring 会将该方法的返回值转换成适合 HTTP 响应的内容类型,通常是 JSON 或 XML。

以下是 @ResponseBody 注解的一些关键点:

自动序列化:当方法的返回值是一个 Java 对象时,@ResponseBody 会使用一个合适的 HttpMessageConverter(如 MappingJackson2HttpMessageConverter 或 Jaxb2RootElementHttpMessageConverter)来将对象序列化为 JSON 或 XML 格式,具体取决于客户端请求头中的 Accept 字段或默认配置。

避免视图渲染:在没有 @ResponseBody 的情况下,控制器方法的返回值通常会被视为视图名,然后通过视图解析器找到对应的视图模板进行渲染。但是,使用 @ResponseBody 后,这个流程被绕过,直接返回数据。

支持多种数据类型:@ResponseBody 支持返回各种类型的数据,包括原始字符串、字节数组、基本数据类型、Java 对象等。对于非对象类型的简单数据,可以直接写入响应体;对于复杂对象,会进行序列化处理。

AJAX 和 RESTful API:@ResponseBody 经常用于构建 AJAX 应用程序或 RESTful 服务,因为这些场景通常不需要完整的 HTML 页面作为响应,而是需要数据。

示例代码:

java

@RestController // 或者 @Controller + @ResponseBody 在类级别

public class MyController {

@GetMapping("/data")

@ResponseBody // 也可以省略,因为类级别有 @RestController

public MyData getData() {

    MyData data = new MyData();

    data.setValue("Hello, World!");

    return data;

}

}

在这个示例中,getData() 方法的返回值 MyData 会被序列化成 JSON 格式(假设客户端请求接受 JSON),并直接写入 HTTP 响应的 Body 部分。

需要注意的是,@ResponseBody 通常与 @RestController 或 @Controller 结合使用,后者会应用于整个控制器类,意味着类中的所有方法都会默认使用 @ResponseBody 行为。如果某个方法不希望有这样的行为,可以在方法级别使用 @ModelAttribute 或直接返回一个 ModelAndView 对象。

3.Spring入门

Spring全家桶
• Spring Framework
• Spring Boot
• Spring Cloud
• Spring Cloud Data Flow
https://spring.io
在这里插入图片描述
Spring Framework
• Spring Core

  • IoC、AOP
    • Spring Data Access
  • Transactions、Spring MyBatis
    • Web Servlet
  • Spring MVC
    • Integration
  • Email、Scheduling、AMQP、Security

Spring IoC
• Inversion of Control

  • 控制反转,是一种面向对象编程的设计思想。
    • Dependency Injection
  • 依赖注入,是IoC思想的实现方式。
    • IoC Container
  • IoC容器,是实现依赖注入的关键,本质上是一个工厂。
    在这里插入图片描述
    Spring框架的IOC(Inversion of Control,控制反转)容器是其核心特性之一,它负责管理应用程序的组件和它们之间的依赖关系。IOC容器简化了组件的配置和管理,使得开发人员能够更专注于业务逻辑而非底层基础设施。

1. 控制反转 (Inversion of Control)

在传统的编程模式中,对象会主动地去创建依赖的实例或者从某个地方获取所需的实例,这种模式下,对象控制着依赖的创建和获取过程。而在控制反转中,这种控制权被“反转”了,对象不再控制依赖的创建和获取,而是由一个外部的容器(在Spring中就是IOC容器)来负责。对象只需要声明它所需要的依赖,剩下的工作都交给IOC容器来完成。

2. Spring的IOC容器

Spring框架提供了两种主要的IOC容器:

  • BeanFactory:这是最基本的IOC容器,它实现了BeanFactory接口。BeanFactory负责读取配置元数据,创建和管理bean以及处理bean之间的依赖注入。然而,BeanFactory并不提供按需加载和单例缓存等功能,这使得它在实际应用中不如ApplicationContext强大和方便。

  • ApplicationContext:这是一个高级的BeanFactory,它继承了BeanFactory的功能,并添加了更多的特性,比如国际化支持、事件发布机制、资源访问机制等。ApplicationContext是Spring推荐使用的容器,因为它提供了更多的企业级功能。

3. Bean的生命周期

在Spring中,bean的生命周期由容器控制。从bean的创建到销毁,Spring提供了多个回调方法,让开发者可以自定义bean的初始化和销毁逻辑。例如,你可以指定一个方法作为初始化方法,在bean创建完成后立即调用;同样,也可以指定一个销毁方法,在容器关闭时调用。

4. 依赖注入 (Dependency Injection)

依赖注入是IOC的一个重要实现方式,它允许在运行时将依赖关系注入到对象中,而不是在编译时就确定。Spring支持三种依赖注入方式:

  • 构造器注入:依赖通过构造函数传入。
  • 属性注入:依赖通过setter方法设置。
  • 字段注入:依赖直接注入到字段中,通常使用@Autowired注解。

5. 配置元数据

Spring的配置元数据可以通过XML文件、注解或Java配置类来提供。这些元数据描述了bean的定义、依赖关系以及配置信息,IOC容器会读取这些元数据来创建和装配bean。

Spring的IOC容器通过控制反转和依赖注入,使得应用程序的结构更加松耦合,提高了代码的可测试性和可维护性。

@EnableAutoConfiguration:自动配置,不用人工配置也能够启动服务
@ComponentScan:自动扫描,自动装配bean(扫描配置所在的包以及子包的bean)。还要有@controller和@service注解,@repository,@component才会被扫描

4.Spring MVC入门

HTTP

• HyperText Transfer Protocol
• 用于传输HTML等内容的应用层协议
• 规定了浏览器和服务器之间如何通信,以及通信时的数据格式。
https://www.ietf.org
https://developer.mozilla.org/zh-CN
在这里插入图片描述HTTP请求是客户端(通常是浏览器)向服务器发送的一种请求,以获取或操作资源。HTTP请求有两种主要类型:GET和POST。

GET请求:用于从服务器检索信息。信息在URL中可见,且有长度限制。GET请求可以被缓存,保留在浏览历史中,并在浏览器的"后退"按钮中保留。

POST请求:用于向服务器发送数据,通常用于表单提交。数据在请求体中发送,不显示在URL中,且没有长度限制。POST请求不会被缓存,也不会保留在浏览器的历史记录中。

三层架构(面试)

  • 表现层、业务层、数据访问层
    • MVC

  • Model:模型层

  • View:视图层

  • Controller:控制层
    • 核心组件

  • 前端控制器:DispatcherServlet
    在这里插入图片描述MVC,全称为Model-View-Controller,是一种广泛使用的软件架构模式,主要用于开发易于维护和修改的用户界面。MVC将应用程序分为三个核心组成部分:

    Model(模型):模型负责管理应用程序的数据逻辑,以及对数据的存储、读取和更新等操作。它是应用程序的核心,独立于任何用户界面。模型直接与数据打交道,当数据发生变化时,它会通知视图和控制器。

    View(视图):视图负责展示模型中的数据给用户,它是用户看到并交互的界面。视图从模型获取数据,然后以某种形式展示出来。当模型数据改变时,视图也会自动更新。

    Controller(控制器):控制器是模型和视图之间的协调者,它接收用户的输入并调用模型和视图去完成用户的需求。控制器处理用户请求,控制应用程序的流程,并决定使用哪个视图来展示数据。

MVC模式的主要优点包括:

提高了代码的复用性和可维护性。
分离了关注点,使得每个部分都专注于其核心功能,简化了开发和测试。
支持多个视图共享同一模型,使得数据可以在不同的界面展示。
控制器可以处理来自不同视图的请求,提高了程序的灵活性。

DispatcherServlet是Spring MVC框架中的核心组件,它扮演着前端控制器的角色。在Spring MVC架构中,所有的HTTP请求首先都会被转发到DispatcherServlet。它的主要职责包括:

初始化上下文:加载配置文件,初始化HandlerMapping、HandlerAdapter、ViewResolver等组件。

请求分发:接收HTTP请求,通过HandlerMapping找到合适的处理器(Controller中的方法),并将其与请求映射起来。

处理请求:调用相应的处理器处理请求。处理器处理完请求后,返回一个ModelAndView对象,其中包含了要渲染的视图名和模型数据。

解析视图:通过ViewResolver找到具体的视图组件,将ModelAndView中的模型数据填充到视图中,生成最终的响应结果。

生成响应:将视图渲染的结果返回给客户端。

DispatcherServlet的工作流程如下:

客户端发送HTTP请求到服务器,请求会被转发到DispatcherServlet。
DispatcherServlet根据请求的URL找到对应的HandlerMapping,从而确定处理该请求的Controller和方法。
DispatcherServlet调用HandlerAdapter执行Controller的方法。
Controller处理完请求后,返回一个ModelAndView对象给DispatcherServlet。
DispatcherServlet使用ViewResolver找到具体的视图组件,并将ModelAndView中的数据填充到视图中。
最终,视图渲染的结果被DispatcherServlet包装成HTTP响应,返回给客户端。

通过DispatcherServlet,Spring MVC能够很好地实现MVC模式,将业务逻辑、数据处理和视图渲染分离,提高代码的可读性和可维护性。
在这里插入图片描述
Thymeleaf
• 模板引擎

  • 生成动态的HTML。
    • Thymeleaf
  • 倡导自然模板,即以HTML文件为模板。
    • 常用语法
  • 标准表达式、判断与循环、模板的布局。
    https://www.thymeleaf.org
    在这里插入图片描述

相关代码:

package com.nowcoder.community.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.text.SimpleDateFormat;

@Configuration
public class AlphaConfig {

@Bean
public SimpleDateFormat simpleDateFormat() {
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}

}

package com.nowcoder.community.controller;

import com.nowcoder.community.service.AlphaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

@Controller
@RequestMapping(“/alpha”)
public class AlphaController {

@Autowired
private AlphaService alphaService;

@RequestMapping("/hello")
@ResponseBody
public String sayHello() {
    return "Hello Spring Boot.";
}

@RequestMapping("/data")
@ResponseBody
public String getData() {
    return alphaService.find();
}

@RequestMapping("/http")
public void http(HttpServletRequest request, HttpServletResponse response) {
    // 获取请求数据
    System.out.println(request.getMethod());
    System.out.println(request.getServletPath());
    Enumeration<String> enumeration = request.getHeaderNames();
    while (enumeration.hasMoreElements()) {
        String name = enumeration.nextElement();
        String value = request.getHeader(name);
        System.out.println(name + ": " + value);
    }
    System.out.println(request.getParameter("code"));

    // 返回响应数据
    response.setContentType("text/html;charset=utf-8");
    try (
            PrintWriter writer = response.getWriter();
    ) {
        writer.write("<h1></h1>");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

// GET请求

// /students?current=1&limit=20
@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";
}

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

// POST请求
@RequestMapping(path = "/student", method = RequestMethod.POST)
@ResponseBody
public String saveStudent(String name, int age) {
    System.out.println(name);
    System.out.println(age);
    return "success";
}

// 响应HTML数据

@RequestMapping(path = "/teacher", method = RequestMethod.GET)
public ModelAndView getTeacher() {
    ModelAndView mav = new ModelAndView();
    mav.addObject("name", "张三");
    mav.addObject("age", 30);
    mav.setViewName("/demo/view");
    return mav;
}

@RequestMapping(path = "/school", method = RequestMethod.GET)
public String getSchool(Model model) {
    model.addAttribute("name", "北京大学");
    model.addAttribute("age", 80);
    return "/demo/view";
}

// 响应JSON数据(异步请求)
// Java对象 -> JSON字符串 -> JS对象

异步请求是一种在网络编程和Web开发中常见的技术,它允许在不阻塞主线程的情况下发送HTTP请求并处理响应。与同步请求相比,异步请求不会暂停程序的执行等待响应,而是继续执行后续的代码,直到响应到达后再处理结果。这种非阻塞的特性对于提高用户体验和程序响应速度至关重要,特别是在处理耗时的网络操作时。

异步请求的优点

提高应用性能:异步请求可以让应用在等待网络响应的同时执行其他任务,避免了长时间的等待导致的UI冻结或程序卡顿。

改善用户体验:在Web应用中,用户可以继续与页面交互,即使某些数据正在后台加载。

资源高效利用:异步处理可以更有效地利用系统资源,避免线程在等待I/O操作时处于空闲状态。


@RequestMapping(path = "/emp", method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> getEmp() {
    Map<String, Object> emp = new HashMap<>();
    emp.put("name", "张三");
    emp.put("age", 23);
    emp.put("salary", 8000.00);
    return emp;
}

@RequestMapping(path = "/emps", method = RequestMethod.GET)
@ResponseBody
public List<Map<String, Object>> getEmps() {
    List<Map<String, Object>> list = new ArrayList<>();

    Map<String, Object> emp = new HashMap<>();
    emp.put("name", "张三");
    emp.put("age", 23);
    emp.put("salary", 8000.00);
    list.add(emp);

    emp = new HashMap<>();
    emp.put("name", "李四");
    emp.put("age", 24);
    emp.put("salary", 9000.00);
    list.add(emp);

    emp = new HashMap<>();
    emp.put("name", "王五");
    emp.put("age", 25);
    emp.put("salary", 10000.00);
    list.add(emp);

    return list;
}

}

package com.nowcoder.community.dao;

import org.springframework.stereotype.Repository;

@Repository(“alphaHibernate”)
public class AlphaDaoHibernateImpl implements AlphaDao {
@Override
public String select() {
return “Hibernate”;
}
}

package com.nowcoder.community.dao;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

@Repository
@Primary
public class AlphaDaoMyBatisImpl implements AlphaDao{
@Override
public String select() {
return “MyBatis”;
}
}

package com.nowcoder.community.service;

import com.nowcoder.community.dao.AlphaDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Service
//@Scope(“prototype”)
public class AlphaService {

@Autowired
private AlphaDao alphaDao;

public AlphaService() {
    System.out.println("实例化AlphaService");
}

@PostConstruct
public void init() {
    System.out.println("初始化AlphaService");
}

@PreDestroy
public void destroy() {
    System.out.println("销毁AlphaService");
}

public String find() {
    return alphaDao.select();
}

}

package com.nowcoder.community;

import com.nowcoder.community.dao.AlphaDao;
import com.nowcoder.community.service.AlphaService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.text.SimpleDateFormat;
import java.util.Date;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class CommunityApplicationTests implements ApplicationContextAware {

private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
	this.applicationContext = applicationContext;
}

@Test
public void testApplicationContext() {
	System.out.println(applicationContext);

	AlphaDao alphaDao = applicationContext.getBean(AlphaDao.class);
	System.out.println(alphaDao.select());

	alphaDao = applicationContext.getBean("alphaHibernate", AlphaDao.class);
	System.out.println(alphaDao.select());
}

@Test
public void testBeanManagement() {
	AlphaService alphaService = applicationContext.getBean(AlphaService.class);
	System.out.println(alphaService);

	alphaService = applicationContext.getBean(AlphaService.class);
	System.out.println(alphaService);
}

@Test
public void testBeanConfig() {
	SimpleDateFormat simpleDateFormat =
			applicationContext.getBean(SimpleDateFormat.class);
	System.out.println(simpleDateFormat.format(new Date()));
}

@Autowired
@Qualifier("alphaHibernate")
private AlphaDao alphaDao;

@Autowired
private AlphaService alphaService;

@Autowired
private SimpleDateFormat simpleDateFormat;

@Test
public void testDI() {
	System.out.println(alphaDao);
	System.out.println(alphaService);
	System.out.println(simpleDateFormat);
}

}

增加学生
<form method="post" action="/community/alpha/student">
    <p>
        姓名: <input type="text" name="name">
    </p>
    <p>
        年龄: <input type="text" name="age">
    </p>
    <p>
        <input type="submit" value="保存">
    </p>
</form>
Teacher

application
ServerProperties
server.port=8080
server.servlet.context-path=/community

ThymeleafProperties
spring.thymeleaf.cache=false

MyBatis入门

安装数据库
• 安装MySQL Server
• 安装MySQL Workbench
https://dev.mysql.com/downloads/mysql
https://dev.mysql.com/downloads/workbench

下载解压后,添加my.ini文件
在这里插入图片描述
[mysql]
default-character-set=utf8
[mysqld]
port=3306
basedir=E:\work\mysql-8.0.38-winx64\mysql-8.0.38-winx64(修改为MySQL的路径)
max_connections=20
character-set-server=utf8
default-storage-engine=INNODB

然后在系统变量path里配置环境变量
E:\work\mysql-8.0.38-winx64\mysql-8.0.38-winx64\bin

以管理员身份运行cmd
cd E:\work\mysql-8.0.38-winx64\mysql-8.0.38-winx64\bin

mysqld --initialize --console(保存好数据库密码password!!!)
A temporary password is generated for root@localhost: ixNM&0%99Crt
mysqld --install

在这里插入图片描述在这里插入图片描述得在管理员身份运行才能建表成功
MySQL服务启动失败,检查是否是端口号冲突!!!!

MyBatis

• 核心组件

  • SqlSessionFactory:用于创建SqlSession的工厂类。
  • SqlSession:MyBatis的核心组件,用于向数据库执行SQL。
  • 主配置文件:XML配置文件,可以对MyBatis的底层行为做出详细的配置。
  • Mapper接口:就是DAO接口,在MyBatis中习惯性的称之为Mapper。
  • Mapper映射器:用于编写SQL,并将SQL和实体类映射的组件,采用XML、注解均可实现。
    • 示例
  • 使用MyBatis对用户表进行CRUD操作。
    http://www.mybatis.org/mybatis-3
    http://www.mybatis.org/spring

到maven repository官网搜索MySQL复制依赖

com.mysql mysql-connector-j 8.0.33

继续搜索mybatis

org.mybatis.spring.boot mybatis-spring-boot-starter 3.0.3

package com.nowcoder.community;

import com.nowcoder.community.dao.UserMapper;
import com.nowcoder.community.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;

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

@Autowired
private UserMapper userMapper;

@Test
public void testSelectUser() {
    User user = userMapper.selectById(101);
    System.out.println(user);

    user = userMapper.selectByName("liubei");
    System.out.println(user);

    user = userMapper.selectByEmail("nowcoder101@sina.com");
    System.out.println(user);
}

@Test
public void testInsertUser() {
    User user = new User();
    user.setUsername("test");
    user.setPassword("123456");
    user.setSalt("abc");
    user.setEmail("test@qq.com");
    user.setHeaderUrl("http://www.nowcoder.com/101.png");
    user.setCreateTime(new Date());

    int rows = userMapper.insertUser(user);
    System.out.println(rows);
    System.out.println(user.getId());
}

@Test
public void updateUser() {
    int rows = userMapper.updateStatus(150, 1);
    System.out.println(rows);

    rows = userMapper.updateHeader(150, "http://www.nowcoder.com/102.png");
    System.out.println(rows);

    rows = userMapper.updatePassword(150, "hello");
    System.out.println(rows);
}

}

application
#ServerProperties
server.port=8080
server.servlet.context-path=/community

#ThymeleafProperties
spring.thymeleaf.cache=false

#DataSourceProperties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/community?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=30000

#MybatisProperties
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.nowcoder.community.entity
mybatis.configuration.useGeneratedKeys=true
mybatis.configuration.mapUnderscoreToCamelCase=true

#logger
logging.level.com.nowcoder.community=debug

user-mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<sql id="insertFields">
    username, password, salt, email, type, status, activation_code, header_url, create_time
</sql>

<sql id="selectFields">
    id, username, password, salt, email, type, status, activation_code, header_url, create_time
</sql>

<select id="selectById" resultType="User">
    select <include refid="selectFields"></include>
    from user
    where id = #{id}
</select>

<select id="selectByName" resultType="User">
    select <include refid="selectFields"></include>
    from user
    where username = #{username}
</select>

<select id="selectByEmail" resultType="User">
    select <include refid="selectFields"></include>
    from user
    where email = #{email}
</select>

<insert id="insertUser" parameterType="User" keyProperty="id">
    insert into user (<include refid="insertFields"></include>)
    values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{status}, #{activationCode}, #{headerUrl}, #{createTime})
</insert>

<update id="updateStatus">
    update user set status = #{status} where id = #{id}
</update>

<update id="updateHeader">
    update user set header_url = #{headerUrl} where id = #{id}
</update>

<update id="updatePassword">
    update user set password = #{password} where id = #{id}
</update>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/766259.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker拉取失败,利用 Git将 Docker镜像重新打 Tag 推送到阿里云等其他公有云镜像仓库里

目录 一、开通阿里云容器镜像服务 二、Git配置 三、去DockerHub找镜像 四、编写images.txt文件 ​五、演示 六、其他注意事项 最近一段时间 Docker 镜像一直是 Pull 不下来的状态&#xff0c;想直连 DockerHub 是几乎不可能的。更糟糕的是&#xff0c;很多原本可靠的国内…

Vue+ElementUi实现录音播放上传及处理getUserMedia报错问题

1.Vue安装插件 npm install --registryhttps://registry.npmmirror.com 2.Vue页面使用 <template><div class"app-container"><!-- header --><el-header class"procedureHeader" style"height: 20px;"><el-divid…

密码学及其应用 —— 密码学的经典问题

1. 古典密码学问题 1.1 问题1&#xff1a;破解凯撒密码 1.1.1 问题 凯撒密码是最简单的单字母替换加密方案。这是一种通过将字母表中的字母固定向右移动几位来实现的加密方法。解密下面的文本&#xff0c;该文本通过对一个去除了空格的法语文本应用凯撒密码获得&#xff1a; …

layui-按钮

1.用法 使用 用button标签 type"button" class"layui-button" 效果&#xff1a; 2.主题设置 前面都要加上layui-bin 3.尺寸设置 可以叠加使用&#xff01; 4.圆角设置 加一个layui-bin-radius 5.按钮图标设置 里面加一个i标签 加class"layui-…

借教室(题解)

P1083 [NOIP2012 提高组] 借教室 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路&#xff1a;二分前缀和 我们将和质检员那题差不多&#xff0c;只需要将候选人二分即可 #include<bits/stdc.h> using namespace std; #define int long long int n,m; int r[100000…

【操作与配置】VSCode配置Python

Python环境配置 可以参见&#xff1a;【操作与配置】Python&#xff1a;CondaPycharm_pycharmconda-CSDN博客 官网下载Python&#xff1a;http://www.python.org/download/官网下载Conda&#xff1a;Miniconda — Anaconda documentation VSCode插件安装 插件安装后需重启V…

disql使用

进入bin目录&#xff1a;cd /opt/dmdbms/bin 启动disql&#xff1a;./disql&#xff0c;然后输入用户名、密码 sh文件直接使用disql&#xff1a; 临时添加路径到PATH环境变量&#xff1a;在当前会话中临时使用disql命令而无需每次都写完整路径&#xff0c;可以在执行脚本之前…

Eclipse + GDB + J-Link 的单片机程序调试实践

Eclipse GDB J-Link 的调试实践 本文介绍如何创建Eclipse的调试配置&#xff0c;如何控制调试过程&#xff0c;如何查看修改各种变量。 对 Eclipse 的要求 所用 Eclipse 应当安装了 Eclipse Embedded CDT 插件。从 https://www.eclipse.org/downloads/packages/ 下载 Ecli…

20240628模拟赛总结

cf好了 让我们开始 T1 Two Regular Polygons 判断能不能构造出题中要求的正多边形 关键是n%m0 Two Regular Polygons #include<bits/stdc.h> using namespace std; int t; int n,m; int main() {cin>>t;for(int i1;i<t;i){cin>>n>>m;if(n%m0)co…

MySQL 代理层:ProxySQL

文章目录 说明安装部署1.1 yum 安装1.2 启停管理1.3 查询版本1.4 Admin 管理接口 入门体验功能介绍3.1 多层次配置系统 读写分离将实例接入到代理服务定义主机组之间的复制关系配置路由规则事务读的配置延迟阈值和请求转发 ProxySQL 核心表mysql_usersmysql_serversmysql_repli…

【C++】相机标定源码笔记- 标定工具库测试

标定工具库测试 一、计算相机内参&#xff1a;对两个相机进行内参标定&#xff0c;并将标定结果保存到指定的文件中 采集图像&#xff1a;相机1-16张 相机2-17张 定义保存相机1/2内参的文件(.yml)路径。 定义相机1/2采集的图片文件夹路径。定义相机1/2存储文件名的向量获取文件…

作为图形渲染API,OpenGL和Direct3D的全方位对比。

当你在网页看到很多美轮美奂的图形效果&#xff0c;3D交互效果&#xff0c;你知道是如何实现的吗&#xff1f;当然是借助图形渲染API了&#xff0c;说起这个不就不得说两大阵营&#xff0c;OpenGL和Direct3D&#xff0c;贝格前端工场在本文对二者做个详细对比。 一、什么是图形…

26.5 Django模板层

1. 模版介绍 在Django中, 模板(Templates)主要用于动态地生成HTML页面. 当需要基于某些数据(如用户信息, 数据库查询结果等)来动态地渲染HTML页面时, 就会使用到模板.以下是模板在Django中使用的几个关键场景: * 1. 动态内容生成: 当需要根据数据库中的数据或其他动态数据来生…

推动能源绿色低碳发展,风机巡检进入国产超高清+AI时代

全球绿色低碳能源数字转型发展正在进入一个重要窗口期。风电作为一种清洁能源&#xff0c;在碳中和过程中扮演重要角色&#xff0c;但风电场运维却是一件十足的“苦差事”。 传统的风机叶片人工巡检方式主要依靠巡检人员利用高倍望远镜检查、高空绕行下降目测检查(蜘蛛人)、叶…

校园水质信息化监管系统——水质监管物联网系统

随着物联网技术的发展越来越成熟&#xff0c;它不断地与人们的日常生活和工作深入融合&#xff0c;推动着社会的进步。其中物联网系统集成在高校实践课程中可以应用到许多项目&#xff0c;如环境气象检测、花卉种植信息化监管、水质信息化监管、校园设施物联网信息化改造、停车…

Qt6 qcustomplot在图表上画一条直线

完整代码如下: 主要注意的是Qt中的QHBoxLayout等Qt类对象在被引用的情况下是可以使用局部变量的,典型的如setLayout这类型的函数接口,都可以使用局部变量,而不是new对象。 另外一点就是qcustomplot中的replot就相当于Qt中的update,由于qcustomplot是属于绘图类的接口库,…

如何用Python向PPT中批量插入图片

办公自动化办公中&#xff0c;Python最大的优势是可以批量操作&#xff0c;省去了用户粘贴、复制、插入等繁琐的操作。经常做PPT的朋友都知道&#xff0c;把图片插入到PPT当中的固定位置是一个非常繁琐的操作&#xff0c;往往调整图片时耗费大量的时间和精力。如何能省时省力插…

新型200V预稳压器可简化故障容受型电源的设计

讨论几种设计故障容受型电源的方法&#xff0c;其中包括新的预稳压器拓扑结构&#xff0c;该结构可简化电路设计及元件选择。 对抗相位故障 如果交流电源到电表之间出现错误连接故障&#xff0c;或是像空调或电磁炉等采用三相电源工作的大功率负载在两个相位之间的连接错误&a…

微信小程序 canvas 处理图片的缩放移动旋转问题

这里使用到了一个插件&#xff0c;canvas-drag&#xff0c;来实现大部分功能的 上效果 直接上代码吧~ wxml <div class"container"><canvas-drag id"canvas-drag" graph"{{graph}}" width"700" height"750" ena…

[漏洞分析] CVE-2024-6387 OpenSSH核弹核的并不是很弹

文章目录 漏洞简介漏洞原理补丁分析漏洞原理 漏洞利用漏洞利用1: SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, from 2005) [无ASLR无NX]漏洞利用原理漏洞利用关键点 漏洞利用2: SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3 (Ubuntu 6.06.1, from 2006) [无ASLR…