目录
1.项目搭建
1.1 创建SpringBoot
1.2 导入静态资源
1.3 bean.User.java
package com.node.demo.bean;
import lombok.Data;
@Data
public class User {
private String UserName;
private String Password;
}
1.4 controller.LoginController.java
package com.node.demo.controller;
import com.node.demo.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpSession;
import javax.websocket.Session;
@Controller
public class LoginController {
@GetMapping("/")
public String login(){
return "login";
}
@PostMapping("/login")
public String main(User user, HttpSession session, Model model){
if(StringUtils.hasLength(user.getUserName()) && "123456".equals(user.getPassword())){//如果user.getName()有长度且user.getPassword()为123456,则登陆成功
//把登陆成功的用户保存起来
session.setAttribute("loginUser",user);
return "redirect:/index.html";//当如果是@PostMapping进入到index页面,刷新的话就会不断重复提交刷新表单,所以需要一个重定向搭配index页面
}else {
model.addAttribute("msg","账号密码错误");
//回到登录页面
return "login";
}
}
//登陆成功重定向到main.html 重定向防止表单重复提交
@GetMapping("/index.html")
public String mainPage(HttpSession session,Model model){
//是否登陆-->拦截器、过滤器
Object loginUser= session.getAttribute("#");
if(loginUser!=null){
return "index.html";
}else {
model.addAttribute("msg","请重新登陆");
return "login";
}
}
}
1.5 修改login.html
xmlns:th="http://www.thymeleaf.org"
1.6 修改index.html
1.7 测试
2.静态资源公共html
把静态资源每个页面都用到的html、css、JavaScript都放到一个common.html里面,这样就不用在其他html页面重复使用了
2.1导入静态资源的table资源
2.2 编写TableController
package com.node.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class TableController {
@GetMapping("/basic_table")
public String basic_table(){
return "table/basic_table";
}
@GetMapping("/dynamic_table")
public String dynamic_table(){
return "table/dynamic_table";
}
@GetMapping("/responsive_table")
public String responsive_table(){
return "table/responsive_table";
}
@GetMapping("/editable_table")
public String editable_table(){
return "table/editable_table";
}
}
2.3 寻找公共资源
2.3.1 从index中找(或其他html)找到后删除
2.3.2 创建common.html放到里面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:fragment="commonhead">
<meta charset="UTF-8">
<title>所有公共模板信息</title>
<!--common-->
<link href="css/style.css" th:href="@{/css/style.css}" rel="stylesheet">
<link href="css/style-responsive.css" th:href="@{/css/style-responsive.css}" rel="stylesheet">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="js/html5shiv.js" th:src="@{/js/html5shiv.js}"></script>
<script src="js/respond.min.js" th:src="@{/js/respond.min.js}"></script>
<![endif]-->
</head>
<body>
<div th:fragment="commonscript">
<script th:src="@{/js/jquery-1.10.2.min.js}"></script>
<script th:src="@{/js/jquery-ui-1.9.2.custom.min.js}"></script>
<script th:src="@{/js/jquery-migrate-1.2.1.min.js}"></script>
<script th:src="@{/js/bootstrap.min.js}"></script>
<script th:src="@{/js/modernizr.min.js}"></script>
<script th:src="@{/js/jquery.nicescroll.js}"></script>
<script th:src="@{/js/scripts.js}"></script>
</div>
</body>
</html>
2.3.3 index(或其他html)引用
3.遍历数据
3.1 TableController
@GetMapping("/dynamic_table")
public String dynamic_table(Model model){
//表格内容的遍历
List<User> users = Arrays.asList(new User("zhangsan", "123456"),
new User("lisi", "123444"),
new User("haha", "aaaaa"),
new User("hehe ", "aaddd"));
model.addAttribute("users",users);
return "table/dynamic_table";
}
3.2 dynamic_table.html
<div class="panel-body">
<div class="adv-table">
<table class="display table table-bordered table-striped" id="dynamic-table">
<thead>
<tr>
<th>用户名</th>
<th>密码</th>
</tr>
</thead>
<tbody>
<tr class="gradeX" th:each="user:${users}">
<td th:text="${user.userName}"></td>
<td >[[${user.userName}]]</td> <!-- 行内写法-->
</tr>
</tbody>
4.拦截器
4.1 LoginInterceptor.java
package com.node.demo.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/*
* 登陆拦截器
* 1.配置拦截器拦截哪些请求
* 2.把这些配置放在容器中
* */
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//目标方法执行之前,登陆检查逻辑
HttpSession session=request.getSession();
Object loginUser = session.getAttribute("loginUser");
if(loginUser!=null){
return true;
}
//拦截 跳到登录页
request.setAttribute("msg","请先登陆");
request.getRequestDispatcher("/").forward(request,response); //转发
/*
* 重定向与转发:
* 转发:是服务器内部的跳转,浏览器的地址栏不会发生变化。从一个页面到另一个页面的跳转还是同一个请求,也即是只有一个请求响应。可以通过request域来传递对象。
* 重定向:是浏览器自动发起对跳转目标的请求,浏览器的地址栏会发生变化。从一个页面到另一个页面的跳转是不同的请求,也即是有两个或两个以上的不同的请求的响应。无法通过request域来传递对象。
* */
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
4.2 AdminWebConfig.java
package com.node.demo.config;
import com.node.demo.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 1、编写一个拦截器实现HandlerInterceptor接口
* 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors) 相当于SSM中的SpringMVC的xml配置文件
* 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】
*/
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //所有请求都会被拦截,包括静态资源
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images");//放行不拦截
}
}
4.3拦截器简单理解
5.文件上传
5.1 导入静态资源
5.2 修改静态资源
<!--enctype="multipart/form-data":表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思
-->
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="exampleInputEmail1">邮箱</label>
<input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">名字</label>
<input type="text" name="username" class="form-control" id="exampleInputPassword1" >
</div>
<div class="form-group">
<label for="exampleInputFile">头像</label>
<input type="file" name="headerImg" id="exampleInputFile">
</div>
<div class="form-group">
<label for="exampleInputFile">生活照</label>
<input type="file" name="photos" multiple>
</div>
5.3 controller
package com.node.demo.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
/*
* 文件上传测试
* */
@Slf4j
@Controller
public class FormTestController {
@GetMapping("/form_layouts")
public String form_layouts(){
return "form/form_layouts";
}
@PostMapping("/upload")
/*
email、username、headrImg、photos对应html的表单name属性
* @RequestPart("headrImg")MultipartFile headrImag, //自动封装上传的单文件
@RequestPart("photos") MultipartFile[] photos//自动封装上传的多文件
*@RequestPart:用在multipart/form-data表单提交请求的方法上(多数用于文件上传),
* @RequestParam和@RequestPart对比,@RequestPart适用于复杂的请求域(像JSON,XML)
* */
public String ipload(@RequestParam("email") String email,
@RequestParam("username") String username,
@RequestPart("headerImg")MultipartFile headerImg, //自动封装上传的单文件
@RequestPart("photos") MultipartFile[] photos ) throws IOException {
log.info("上传的信息:email={},username={},headerImg={},photos={}",
email,username,headerImg.getSize(),photos.length);
if(!headerImg.isEmpty()){
//保存到文件服务器,OSS服务器
String originalFilename = headerImg.getOriginalFilename();
headerImg.transferTo(new File("E:\\idea\\SpringBoot-后台管理系统\\src\\main\\resources\\static\\images\\upload\\"+originalFilename));
}
if(photos.length > 0){
for (MultipartFile photo : photos) {
if(!photo.isEmpty()){
String originalFilename = photo.getOriginalFilename();
photo.transferTo(new File("E:\\idea\\SpringBoot-后台管理系统\\src\\main\\resources\\static\\images\\upload\\"+originalFilename));
}
}
}
return "index";
}
}
5.4 测试
5.5 原理
5.5.1 文件限制原理
文件上传自动配置类-MultipartAutoConfiguration-MultipartProperties
6. 异常处理
6.1 错误处理
6.1.1 默认规则
- 默认情况下,Spring Boot提供/error处理所有错误的映射
- 对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据
- 要对其进行自定义,添加View解析为error
- 要完全替换默认行为,可以实现 ErrorController 并注册该类型的Bean定义,或添加ErrorAttributes类型的组件以使用现有机制但替换其内容。
- error/下的4xx,5xx页面会被自动解析;
7.数据库操作
7.1 SQL
7.1.1 数据源的自动配置-HikariDataSource
7.1.1.1 导入JDBC
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
7.1.1.2 导入驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
因为官方不知道我们接下要操作什么数据库,所以只导入了JDBC场景,驱动还是需要我们自己手动导入
如果需要改版本
- 方法一:直接依赖引入具体版本(maven的就近依赖原则)
- 方法二:重新声明版本(maven的属性的就近优先原则)
<properties>
<java.version>1.8</java.version>
<mysql.version>5.1.49</mysql.version>
</properties>
7.1.1.2 分析JDBC自动配置
DataSourceAutoConfiguration : 数据源的自动配置
- 底层配置好的连接池是:HikariDataSource
DataSourceTransactionManagerAutoConfiguration: 事务管理器的自动配置
JdbcTemplateAutoConfiguration: JdbcTemplate的自动配置,可以来对数据库进行crud
JndiDataSourceAutoConfiguration: jndi的自动配置
XADataSourceAutoConfiguration: 分布式事务相关的
7.1.1.3 修改配置项
spring:
datasource:
url: jdbc:mysql://localhost:3306/db_account
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
7.1.1.4 测试
在单元测试DemoApplicationTests.java中
package com.node.demo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
@Slf4j
@SpringBootTest
class DemoApplicationTests {
@Autowired
JdbcTemplate jdbcTemplate;
@Test
void contextLoads() {
//jdbcTemplate.queryForObject("select * from student"); //查询一个对象
Long aLong = jdbcTemplate.queryForObject("select count(*) from student", Long.class);//查询有几条数据,封装成long
log.info("记录总数:{}",aLong);
}
}
7.1.2 Druid数据源
Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。
官方:https://github.com/alibaba/druid
官方文档:https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
整合第三方技术的两种方式
• 自定义
• 找starter
7.1.2.1 自定义方式
7.1.2.1.1 引入数据源
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="20" />
<property name="initialSize" value="1" />
<property name="maxWait" value="60000" />
<property name="minIdle" value="1" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="20" />
7.1.2.1.2 创建MyDruidConfig
package com.node.demo.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.lang.reflect.Array;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
@Configuration
public class MyDruidConfig {
@ConfigurationProperties("spring.datasource") //DataSource和配置文件的属性绑定
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource druidDataSource=new DruidDataSource();
// druidDataSource.setUrl();
// druidDataSource.setUsername();
//加入监控功能和防火墙功能
druidDataSource.setFilters("stat,wall");
return druidDataSource;
}
/*
* 配置driod的监控功能
* */
@Bean
public ServletRegistrationBean servletRegistrationBean(){
StatViewServlet statViewServlet=new StatViewServlet();
ServletRegistrationBean<StatViewServlet> registrationBean=new ServletRegistrationBean<>(statViewServlet,"/druid/*");
/*监控页面访问密码*/
registrationBean.addInitParameter("loginUsername","admin");
registrationBean.addInitParameter("loginPassword","123456");
return registrationBean;
}
/*
* WebStatFilter 用于采集web-jdbc关联监控的数据*/
@Bean
public FilterRegistrationBean webStatFFilter(){
WebStatFilter webStatFilter = new WebStatFilter();
FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>(webStatFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));//监控所有路径
filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
7.1.2.1.4 测试
7.1.2.2 引入starter方式
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
7.1.2.3 不在需要MyDruidConfig,直接配置文件里面修改
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
aop-patterns: com.atguigu.admin.* #监控SpringBean
filters: stat,wall # 底层开启功能,stat(sql监控),wall(防火墙)
stat-view-servlet: # 配置监控页功能
enabled: true
login-username: admin
login-password: admin
resetEnable: false
web-stat-filter: # 监控web
enabled: true
urlPattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
filter:
stat: # 对上面filters里面的stat的详细配置
slow-sql-millis: 1000
logSlowSql: true
enabled: true
wall:
enabled: true
config:
drop-table-allow: false
SpringBoot配置示例:
https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
配置项列表
https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8
7.1.3 整合MyBatis
官方文档:https://mybatis.org/mybatis-3/zh/index.html
GitHub官方:https://github.com/mybatis
GitHub官方文档:https://github.com/mybatis/spring-boot-starter/wiki/Quick-Start
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
- 全局配置文件
- SqlSessionFactory: 自动配置好了
- SqlSession:自动配置了 SqlSessionTemplate 组合了SqlSession
- @Import(AutoConfiguredMapperScannerRegistrar.class);
- Mapper: 只要我们写的操作MyBatis的接口标准了 @Mapper 就会被自动扫描进来
@EnableConfigurationProperties(MybatisProperties.class) : MyBatis配置项绑定类。
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
public class MybatisAutoConfiguration{}
@ConfigurationProperties(prefix = "mybatis")
public class MybatisProperties
7.1.3.1 方法一:配置整合
导入包
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
7.1.3.1.1 Student
package com.node.demo.bean;
import lombok.Data;
@Data
public class Student {
private Integer id;
private String name;
private String sex;
private Integer age;
}
7.1.3.1.2 mybatis-conffig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
7.1.3.1.3 StudentMapper
package com.node.demo.mapper;
import com.node.demo.bean.Student;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface StudentMapper {
List<Student> queryStudentList();
Student getStuId(int id);
int addStu(Student student);
int updateStu(Student student);
int deleteStu(int id);
}
7.1.3.1.4 StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.node.demo.mapper.StudentMapper">
<select id="queryStudentList" resultType="com.node.demo.bean.Student">
select * from student
</select>
<select id="getStuId" resultType="com.node.demo.bean.Student">
select * from student where id=#{id}
</select>
<select id="addStu" resultType="com.node.demo.bean.Student">
insert into student (id,name,sex,age) values (#{id},#{name},#{sex},#{age})
</select>
<select id="updateStu" resultType="com.node.demo.bean.Student">
update student set name=#{name},sex=#{sex} where id =#{id}
</select>
<select id="deleteStu" resultType="com.node.demo.bean.Student">
delete from student where id=#{id}
</select>
</mapper>
7.1.3.1.5 application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
aop-patterns: com.atguigu.admin.* #监控SpringBean
filters: stat,wall # 底层开启功能,stat(sql监控),wall(防火墙)
stat-view-servlet: # 配置监控页功能
enabled: true
login-username: admin
login-password: admin
resetEnable: false
web-stat-filter: # 监控web
enabled: true
urlPattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
filter:
stat: # 对上面filters里面的stat的详细配置
slow-sql-millis: 1000
logSlowSql: true
enabled: true
wall:
enabled: true
config:
drop-table-allow: false
# 配置mybatis规则
mybatis:
config-location: classpath:mybatis/mybatis-conffig.xml
mapper-locations: classpath:mybatis/mapper/*.xml
7.1.3.1.7 LoginController
@Controller
public class LoginController {
/* 配置整合Mybatis*/
@Autowired
StudentMapper studentMapper;
@ResponseBody
@GetMapping("/stu")
public List<Student> queryStudentList(){
List<Student> studentList=studentMapper.queryStudentList();
for(Student student:studentList){
System.out.println(student);
}
return studentList;
}
}
7.1.3.1.8 测试
7.1.3.2 方法二:注解模式
@Mapper
public interface CityMapper {
@Select("select * from city where id=#{id}")
public City getById(Long id);
public void insert(City city);
}
7.1.3.4 方法三:混合模式
7.1.3.5 最佳实战
• 引入mybatis-starter
• 配置application.yaml中,指定mapper-location位置即可
• 编写Mapper接口并标注@Mapper注解
• 简单方法直接注解方式
• 复杂方法编写mapper.xml进行绑定映射
• @MapperScan(“com.atguigu.admin.mapper”) 简化,其他的接口就可以不用标注@Mapper注解
7.1.4 整合Mybatis-Plus
Github文档:https://github.com/baomidou/mybatis-plus
官方文档:https://baomidou.com/
优点:XML跳转、生成代码、重置模板、JPA提示、生成查询
自动配置
- MybatisPlusAutoConfiguration 配置类,MybatisPlusProperties 配置项绑定。mybatis-plus:xxx 就是对mybatis-plus的定制
- SqlSessionFactory 自动配置好。底层是容器中默认的数据源
- mapperLocations 自动配置好的。有默认值。classpath*:/mapper/**/*.xml;任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件。 建议以后sql映射文件,放在 mapper下
- 容器中也自动配置好了 SqlSessionTemplate
- @Mapper 标注的接口也会被自动扫描;建议直接 @MapperScan(“com.atguigu.admin.mapper”) 批量扫描就行
7.1.4.1 数据库
create schema mybatisplus
use mybatisplus
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
7.1.4.1 导入包
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
7.1.4.2 主程序
7.1.4.3 User
package com.node.demo.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
//@TableName("user_tb1") 你的类名是User,会自动配置你数据库表的user表,如果user表改成了user_tb1,则需要这个注解
public class User {
/*
* 所有属性都应该在数据库中*/
@TableField(exist = false)
private String UserName;
@TableField(exist = false)//表示不在数据库中
private String Password;
private Integer id;
private String name;
private Integer age;
private String email;
}
7.1.4.4 UserMapper
package com.node.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.node.demo.bean.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<User> {
}
7.1.4.5 DemoApplicationTests
package com.node.demo;
import com.node.demo.bean.User;
import com.node.demo.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
@SpringBootTest
class DemoApplicationTests {
@Autowired
UserMapper userMapper;
@Test
void testUserMapper(){
User user=userMapper.selectById(1L);
log.info("用户信息:{}",user);
}
}
7.1.4.6 测试
7.1.5 整合Mybatis-Plus-CRUD
一般操作:需要操作查询,先调用Service(接口)的一个方法,在去ServiceImpl实现这个方法,ServiceImpl再调用Mapper里面的方法操作数据库
7.1.5.6 数据列表展示
7.1.5.6.1 UserMapper
package com.node.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.node.demo.bean.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<User> {
}
7.1.5.6.2 UserService
package com.node.demo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.node.demo.bean.User;
public interface UserService extends IService<User> {
}
IService:是所有Service的总接口(顶级),不在需要注解写方法。:要查询的数据
7.1.5.6.3 UserServiceImpl
package com.node.demo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.node.demo.bean.User;
import com.node.demo.mapper.UserMapper;
import com.node.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
ServiceImpl<UserMapper, User>:Service的顶级
7.1.5.6.4 TableController
package com.node.demo.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.node.demo.bean.User;
import com.node.demo.service.UserService;
import com.node.demo.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Arrays;
import java.util.List;
@Controller
public class TableController {
@GetMapping("/basic_table")
public String basic_table(){
return "table/basic_table";
}
@Autowired
UserServiceImpl userService;
@GetMapping("/dynamic_table")
public String dynamic_table(@RequestParam(value = "pn",defaultValue = "1")Integer pn, Model model){
/*//表格内容的遍历
List<User> users = Arrays.asList(new User("zhangsan", "123456"),
new User("lisi", "123444"),
new User("haha", "aaaaa"),
new User("hehe ", "aaddd"));
model.addAttribute("users",users);*/
List<User> list= userService.list();
model.addAttribute("users",list);
return "table/dynamic_table";
}
@GetMapping("/responsive_table")
public String responsive_table(){
return "table/responsive_table";
}
@GetMapping("/editable_table")
public String editable_table(){
return "table/editable_table";
}
}
7.1.5.6.5 静态资源
7.1.5.6.6 测试
7.1.5.7 分页
7.1.5.7.1 MybatisConfig(配置分页插件)
package com.node.demo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfig {
/*
* 分页插件
* */
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
PaginationInnerInterceptor paginationInnerInterceptor=new PaginationInnerInterceptor();
paginationInnerInterceptor.setOverflow(true);
paginationInnerInterceptor.setMaxLimit(500L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
7.1.5.7.2 TableController
package com.node.demo.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.node.demo.bean.User;
import com.node.demo.service.UserService;
import com.node.demo.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Arrays;
import java.util.List;
@Controller
public class TableController {
@GetMapping("/basic_table")
public String basic_table(){
return "table/basic_table";
}
@Autowired
UserServiceImpl userService;
@GetMapping("/dynamic_table")
public String dynamic_table(@RequestParam(value = "pn",defaultValue = "1")Integer pn, Model model){
//表格内容的遍历-->有分页
//分页查询数据
Page<User> userPage=new Page<>(pn,2);
//分页查询结果
Page<User> page = userService.page(userPage, null);//第二个:queryWrapper-->查询对象
long current = page.getCurrent();//当前页
long pages = page.getPages();//总页数
long total = page.getTotal();//总记录数
List<User> records=page.getRecords(); //获取所有数据
model.addAttribute("page",page);
return "table/dynamic_table";
}
@GetMapping("/responsive_table")
public String responsive_table(){
return "table/responsive_table";
}
@GetMapping("/editable_table")
public String editable_table(){
return "table/editable_table";
}
}
7.1.5.7.3 修改静态资源
<tr>
<th>用户ID</th>
<th>用户名</th>
<th>年龄</th>
<th>邮箱</th>
</tr>
</thead>
<tbody>
<tr class="gradeX" th:each="user:${page.records}">
<td th:text="${user.id}"></td>
<td>[[${user.name}]]</td> <!-- 行内写法-->
<td th:text="${user.age}"></td>
<td th:text="${user.email}"></td>
</tr>
</tbody>
<div class="dataTables_info" id="editable-sample_info">当前第[[${page.current}]]页
总计[[${page.pages}]]页 共[[${page.total}]]条记录
</div>
<ul>
<li class="prev disabled"><a th:href="@{/dynamic_table(pn=${page.current}-1)}">← 前一页</a></li>
<li th:class="${num==page.current?'active':''}" th:each="num:${#numbers.sequence(1,page.pages)}">
<!--th:each="num:${#numbers.sequence(1,page.pages)}:遍历出,第一页到总计页数-->
<a th:href="@{/dynamic_table(pn=${num})}">[[${num}]]</a>
</li>
<li class="prev disabled"><a th:href="@{/dynamic_table(pn=${page.current}+1)}">下一页 → </a></li>
</ul>
7.1.5.7.4 测试
7.1.5.8 删除
7.1.5.8.1 dynamic_table.html
<tr>
<th>用户ID</th>
<th>用户名</th>
<th>年龄</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr class="gradeX" th:each="user:${page.records}">
<td th:text="${user.id}"></td>
<td>[[${user.name}]]</td> <!-- 行内写法-->
<td th:text="${user.age}"></td>
<td th:text="${user.email}"></td>
<td>
<a th:href="@{/user/delete/{id}(id=${user.id},pn=${page.current})}"
class="btn btn-danger btn-sm" type="button">删除</a>
</td>
</tr>
7.1.5.8.2 TableController
/*删除*/
@GetMapping("/user/delete/{id}")
public String deleteUser(@PathVariable("id")Long id,
@RequestParam(value = "pn",defaultValue = "1")Integer pn,
RedirectAttributes ra){
//RedirectAttributes ra:代表着保持当删除当前这页的id时,把当前页pn存起来,再到html里面 @${里面的地址}保持当前页面
userService.removeById(id);
ra.addAttribute("pn",pn);
return "redirect:/dynamic_table";
}
7.1.5.8.9 测试
删除前
删除后
7.2 NoSQL
7.2.1 Redis
官方:http://www.redis.cn/
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。