此文章是看b站springboot教学视频写的一些小笔记
在IDEA创建springboot项目
pom.xml里面放的是依赖。
在resources文件下新建public文件夹和resources文件夹。
如果新建class的时候如果没有自动出现public class Hello {},在File→Project Structure→Modules里把java文件夹选中,设为“Sources”类型即可。
一些小知识点
- Collection是最基本的集合接口,一个Collection代表一组Object的集合。
Collection<类名>是个集合。 - 导入依赖后需要刷新才能使用,可点击maven那里的刷新按钮来刷新。
- @RequestMapping处理来指定控制器可以处理哪些URL请求。
使用前,需要使用@Controller 标记该类。
例:
@RequestMapping({"/","/index.html"}) //地址栏输入这俩,会跳转到index.html
public String index(){
return "index";
}
- 在视图控制里进行设置,也可以指定处理URL请求:
@Configuration
public class MyMvcCondig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
- 使用thymeleaf前,记得要导入依赖,把下面代码放在pom.xml中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 关闭默认图标:在application.properties中加上
spring.mvc.favicon.enabled=false
- 更改根URL(改完后根目录变为http://localhost:8080/yang):在application.properties中加上
server.servlet.context-path=/yang
- .properties结尾的文件都是配置文件,可自己新建。
- @ResponseBody:将java对象转为json格式的数据。
静态资源导入
resources文件夹下有resources、static、public文件夹,优先级依次递减。
建立的js文件通过localhost:8080/test.js访问。
- public里放公共的资源
- static放静态的资源,如图片(默认使用static处理静态资源)
- resources放上传的文件
首页
在resources文件夹下新建一个index.html即为首页,localhost:8080/即可访问。
跳转的写法:
//如果是放在templates目录下的页面,只能通过controller来跳转
@Controller
public class IndexController {
@RequestMapping("/index")
public String index(){
return "index"; //作用是 链接到了index.html
}
}
Thymeleaf模板引擎
之前使用的是jsp,现在大多使用Thymeleaf。
如果需要使用Thymeleaf,只需导入对应的依赖。将HTML页面放在templates目录下。
使用:
放入约束/头文件
- 链接→th:href
- 文本→th:text
- 表达式→${…}
- 选择表达式→*{…}
- 消息→#{…}
- URL→@{…}
例子:
java文件中写:
@RequestMapping("/test")
public String test(Model model){
model.addAttribute("msg","hellospringboot");
return "test";
}
HTML文件中写:
<div th:text="${msg}"></div>
<!--所有的HTML元素都可以被thymeleaf接管,方法为th:元素名-->
Thymeleaf语法
完整用法看官方文档
@RequestMapping("/test")
public String test(Model model){
model.addAttribute("msg","<h1>hellospringboot</h1>");
return "test";
}
<div th:text="${msg}"></div>
<div th:utext="${msg}"></div> <!-- 可以识别msg里的标签 -->
<h3 th:each="user:${users}" th:text="${user}"></h3> <!-- 遍历列表中的元素 -->
<h3 th:each="user:${users}">[[${user}]]</h3>
MVC配置原理
在讲源码,听不懂
package com.example.test.config;
import org.apache.tomcat.jni.Local;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
//如果想diy一些定制化的功能,只要写这个组件,然后把它交给springboot,springboot就会帮我们自动装配!
//扩展 springmvw siapatchservlet
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//ViewResolver 实现了视图解析器接口的类,我们就可以把它看做视图解析器
@Bean
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
//自定义了一个自己的视图解析器MyViewResolver
public static class MyViewResolver implements ViewResolver{
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception{
return null;
}
}
}
扩展SpringMVC
在讲源码,听不懂
package com.example.test.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc //导入了一个类:DelegatingWebMvcConfiguration:从容器中获取所有的webmvcconfig
public class MyMvcConfig implements WebMvcConfigurer {
//视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController("/index").setViewName("test");
}
}
员工管理系统:准备工作(视频20)
下载了模板,文件放入对应位置,如下图
视频里创建了四个类:Employee、EmployeeDao、Department、DepartmentDao,放在新建的dao文件夹。Dao为结尾的两个类是充当数据库的作用,在没有数据库时借此来存储数据。
员工管理系统:首页实现(视频21)
使用thymeleaf的时候静态资源加载不进来,需要把html里的内容改为thymeleaf的形式。所有页面的静态资源都需要使用thymeleaf来接管。
需要给html加命名空间,即为下面这个形式:
<html lang="en" xmlns:th="http://www.thymeleaf.org">
然后本地链接要从href变为th:href,形式为th:href="@{}";src改为th:src="@{}"。(注:在线的链接不要改,比如http开头的那些)
<link th:href="@{/css/bootstrap.min.css}" >
<th:src="@{/img/bootstrap-solid.svg}">
更改后的效果没有展示,关掉thymeleaf缓存:在application.properties中加上:
spring.thymeleaf.cache=false
此时重新运行,删除浏览器缓存,就会显示css的效果(注:如果此时还没显示出来,把MyMvcConfig中的@EnableWebMvc注释掉即可)
员工管理系统:国际化(视频22)
国际化即为页面可以中文英文进行切换。
首先要在file encodings里确定所有编码都是UTF-8格式的:
在resources文件夹下新建i18n文件夹,在该文件夹下新建:login.properties和login_zh_CN.properties(这个代表是中文的),接下来再添加英文的,按下图操作即可(在框1处右键点new,然后点第一行):
可以在新版IDEA中下载一个可视化插件,File→Pligins→resource bundle editor插件。
通过可视化插件进行编辑。
在application.properties中加上下面一行代码,表明配置的这个国际化所在的真实位置(是在i18n文件夹下的’login’):
spring.messages.basename=i18n.login
使用国际化信息的时候,格式为"#{}"
<input th:text="#{login.tip}">
<button th:value="#{login.btn}"> //注意text和value的使用
[[#{login.remember}]] //取值
写一个自己国际化解析器:MyLocaleResolver类,让它实现LocaleResolver接口,重写一些方法。
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request){
//获取请求中的语言参数
String language=request.getParameter("l");
//如果没有就使用默认的
Locale locale = Locale.getDefault();
//如果请求的链接携带了国际化的参数
if(!StringUtils.isEmpty(language)){
String[] split = language.split("_"); //把zh_CN分割,得到语言、国家
locale =new Locale(split[0],split[1]);
}
System.out.println(locale);
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response,Locale locale){
}
}
在要点击的按钮处加上本地链接,这样点击的时候,才会去找对应的路径。
要在localhost:8080/index打开。
<a th:href="@{/index(l='zh_CN')}">中文</a>
<a th:href="@{/index(l='en_US')}">English</a>
然后,要在MyMvcConfig类里写以下代码,才能生效:
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//自定义的国际化组件就生效了
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
}
总结,完整步骤为:
1.配置i18n文件
2.如果需要在项目中进行按钮自动切换,需要自定义一个组件LocaleResolver。
3.记得把自己写的组件配置到spring容器 ,@Bean
4.用"#{}"取值
员工管理系统:登录功能实现(视频23)
在用户名和密码输入框的地方加上name属性:
<input type="text" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
<input type="password" name="password" class="form-control" th:placeholder="#{login.password}" required="">
新建一个LoginController类,在里面写登录功能:
@Controller
public class LoginController {
@RequestMapping("/user/login")
public String login(
@RequestParam("username") String username,
@RequestParam("password") String password,
Model model){
//具体的业务:
if(!StringUtils.isEmpty(username)&& "123456".equals(password)){ //账号不为空,且密码正确,则登录成功
return "dashboard";
}
else{
//告诉用户登录失败
model.addAttribute("msg","用户名或密码错误!");
return "index";
}
}
}
当用户名、密码输入错误时,显示提示的代码:
th:if来判断msg是否为空,th:text获得msg的内容。
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
员工管理系统:登录拦截器(视频24)
新建一个LoginHandlerInterceptor类实现HandlerInterceptor接口:
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录成功之后,应该有用户的session:
Object loginUser=request.getSession().getAttribute("loginUser");
if(loginUser==null){ //没有登录
request.setAttribute("msg", "没有权限,请先登录");
request.getRequestDispatcher("/index.html").forward(request, response);
return false;
}else {
return true;//false就是不放行,true是放行
}
}
}
在MyMvcConfig配置里加上:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor())
.addPathPatterns("/**") //拦截所有的
.excludePathPatterns("/index.html","/","user/login","/css/*","/js/**","/img/**"); //这些不拦截,注意要把静态资源加上
}
注:若此时页面未拦截,要清理一下缓存。
登录之后的页面要取用户名的话,形式为:[[${session.loginUser}]]
员工管理系统:展示员工列表(视频25)
th:href中的链接可以与@RequestMapping对应进行跳转。
<a th:href="@{/emps}">
@RequestMapping("/emps")
public String list(Model model){
Collection<Employee> employees = employeeDao.getAll();
model.addAttribute("emps",employees);
return "emp/list";
}
html中代码复用:
在被复用的代码那一段加th:fragment=“xxx”;
在需要使用的地方加th:insert="~{html页面名::xxx}",
或 th:replace="~{html页面名::xxx}"。
(注:可以单独给需要复用的代码单独的一个html,如commons文件夹下的commons.html。)
例子:
<nav th:fragment="sidebar">
<div th:insert="~{dashboard::sidebar}"></div>
或
<div th:replace="~{commons/commons::sidebar}"></div>
除此之外,还可以传递参数:
(class要改为th:class)
(若active传递来的值等于main.html,则运行nav-link active(高亮))
<a th:class="${active=='main.html'?'nav-link active':'nav=link'}" th:href="@{/index.html}">
<div th:replace="~{commons/commons::sidebar(active='main.html')}"></div>
读取数据库,以列表形式循环展示
先写个controller类,能获取所有员工数据。
后续通过emps来调用。
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao;
@RequestMapping("/emps")
public String list(Model model){
Collection<Employee> employees = employeeDao.getAll();
model.addAttribute("emps",employees);
return "emp/list";
}
}
在前端先通过th:each="emp:
e
m
p
s
"
获
取
数
据
,
放
在
e
m
p
变
量
中
。
然
后
再
通
过
t
h
:
t
e
x
t
=
"
{emps}"获取数据,放在emp变量中。然后再通过th:text="
emps"获取数据,放在emp变量中。然后再通过th:text="{emp.getId()}"获取单独数据。
还可以添加一些操作。
<table >
<thead>
<tr>
<th>id</th>
<th>lastName</th>
<th>gender</th>
<th>department</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}"></td>
<td>[[${emp.getLastName()}]]</td> <!--两种方式皆可 -->
<td th:text="${emp.getGender()==0?'女':'男'}"></td> <!--通过gender的值来判断男女 -->
<td th:text="${emp.getDepartment.getDepartmentName()}"></td> <!--注意是两个get -->
<td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td> <!--给日期改格式 -->
<td>
<button class="btn btn-sm btn-primary">编辑</button>
<button class="btn btn-sm btn-danger">删除</button>
</td>
</tr>
</tbody>
</table>
员工管理系统:增加员工实现(视频26)
添加员工的过程:按钮提交+跳转到添加页面+添加员工成功+返回首页
html页面写上:
<h2><a class="btn btn-sm btn-success" th:href="@{/emp}"> 添加员工</a> </h2>
在EmployeeController类里加上:
@GetMapping("/emp")
public String toAddpage(){
return "emp/add";
}
然后再写个添加页面add.html。
添加时需要选择所属部门,在下拉列表里有所有的部门可以进行选择,实现如下:
@GetMapping("/emp")
public String toAddpage(Model model){
//需要查出所有部门的信息
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "emp/add";
}
注意里写的调用。
<select class="form-control" name="department">
<option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
接下来,将员工添加到数据库中。
先在添加的页面add.html里给加上:
<form th:action="@{/emp}" method="post">
为了防止用户输入的日期不适配,在application.properties中加上:
# 时间日期格式化
spring.mvc.format.date=yyyy-MM-dd
在EmployeeController里写添加操作。
注意是@postmapping,与add.html里的相对应。
@PostMapping("/emp")
public String addEmp(Employee employee){
//添加的操作
employeeDao.add(employee); //调用底层业务方法保存员工信息(这方法是在EmployeeDao类里自己写的)
return "redirect:/emps"; //重定向(重定向是:A->B改为A->C,转发是A->B->C)
}
员工管理系统:修改员工信息(视频27)
在主页面“编辑”的地方设置跳转,并传参(注意传参格式):
注:若样式无了,注意路径格式th:href="@{…}"。
<a class="btn btn-sm btn-primary" th:href="@{/emp/{id}(id=${emp.getId()})}">编辑</a>
在EmployeeController里写修改操作。
//去员工的修改页面
@GetMapping("/emp/{id}")
public String toUpdateEmp(@PathVariable("id")Integer id,Model model){
//查出原来的数据
Employee employee = employeeDao.getEmployeeById(id);
model.addAttribute("emp",employee);
//需要查出所有部门的信息
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "emp/update";
}
在前端,获取值的格式为:
th:value="${emp.getLastName()}"
th:checked="${emp.getGender()==1}" //进行判断
th:selected="${dept.getId()==emp.getDepartment().getId()}"
//时间要注意格式,不然页面会报错,不能仅仅只是"${emp.getBirth()}"
th:value="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm')}"
修改好的数据要上传到数据库。
在EmployeeController里写数据上传操作。
@PostMapping("/updateEmp")
public String updateEmp(Employee employee){
employeeDao.add(employee);
return "redirect:/emps";
}
修改数据时要根据id进行修改,不能新增一条数据,于是在html页面中写:
(如果不写这个,就会新增了一条数据)
<input type="hidden" name="id" th:value="${emp.getId()}">
//name对应的值是唯一的
员工管理系统:删除及404处理(视频28)
删除的操作
在html“删除”的链接那里加上:
<a class="btn btn-sm btn-danger" th:href="@{/delemp/{id}(id=${emp.getId()})}">删除</a>
在EmployeeController里写上操作:
//删除员工
@GetMapping("/delemp/{id}")
public String deleteEmp(@PathVariable("id")Integer id,Model model){
employeeDao.delete(id);
return "redirect:/emps";
}
404操作
在templates文件夹下新建error文件夹,把404.html放进去即可。
注销操作
在html的“注销链接处加上”:
<a th:href="@{/user/logout}">注销</a>
在LoginController处加上:
@RequestMapping("/user/logout")
public String logout(HttpSession session){
session.invalidate();
return "redirect:/index.html";
}
整合JDBC使用(视频31)
- Spring Boot底层都是采用Spring Data的方式进行统一处理各种数据库,Spring Data也是Spring中与Spring Boot、Spring Cloud齐名的知名项目。
- Spring Data官网:https://spring.io/projects/spring-data
创建新项目
必须选中JDBC API 和 Mysql Driver。
连接数据库
输入正确的user和password,点击schemas,会显示所有的数据库,选择一个数据库进行连接,点击OK。
在下图位置新建一个文件:
内写:
其中,mybatis是数据库名,可随意起名。
spring:
datasource:
username: root
password: yanglejia2008
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.jdbc.Driver
获得数据库连接
在test文件夹下的SpringbootStudy03DataApplicationTests类中写:
@SpringBootTest
class SpringbootStudy03DataApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
//查看默认的数据源:com.zaxxer.hikari.HikariDataSource
System.out.println(dataSource.getClass());
//获得数据库连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
//xxxx template:springboot已经配置好模板bean,拿来即用。增删改查CRUD
//关闭
connection.close();
}
}
增删改查数据库
@RestController
public class JdbcController {
@Autowired
JdbcTemplate jdbcTemplate;
//查询数据库的所有信息(没有实体类,如何获取数据库中的东西?->>使用map)
@GetMapping("/userList")
public List<Map<String,Object>> userList(){
String sql= "select * from user";
List<Map<String, Object>> list_maps = jdbcTemplate.queryForList(sql);
return list_maps;
}
//增加(每运行之后打开网页就会增加一条。注:仅运行不打开网页是不会增加的)
@GetMapping("/addUser")
public String addUser(){
String sql = "insert into mybatis.user(id,name,pwd) values(6,'6','111') ";
jdbcTemplate.update(sql);
return "add-OK";
}
//修改(根据id修改)
@GetMapping("/updateUser/{id}")
public String updateUser(@PathVariable("id") int id){
String sql = "update mybatis.user set name=?,pwd=? where id= "+id;
//封装
Object[] objects = new Object[2];
objects[0]="小明2";
objects[1]="zzzzzz";
jdbcTemplate.update(sql,objects);
return "update-OK";
}
//删除(根据id修改)
@GetMapping("/deleteUser/{id}")
public String deleteUser(@PathVariable("id") int id){
String sql = "delete from mybatis.user where id=?";
jdbcTemplate.update(sql,id);
return "delete-OK";
}
}
运行,在主类点击运行,然后打开http://localhost:8080/xxx(根据各自的GetMapping)即可看到被取出的数据:
整合Druid数据源(视频32)
- Druid德鲁伊是阿里巴巴开源平台上的一个数据库连接池实现,结合了多个DB池的优点,同时加入了日志监控。Druid可以很好的监控DB池连接和SQL的执行情况,是针对监控而生的DB连接池。
- springboot2.0以上默认使用Hikari数据源,Hikari与Druid都是当前Java Web上最优秀的数据源。
步骤:
导入druid依赖,在网页https://mvnrepository.com/artifact/com.alibaba/drui上。
导入log4j依赖:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
在application.yml上加上
type: com.alibaba.druid.pool.DruidDataSource
#SpringBoot默认是不注入这些的,需要自己绑定
#druid数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Priority
#则导入log4j 依赖就行
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
新建config文件夹,在其下新建DruidConfig文件,内写:
@Configuration
public class DruidConfig {
//与application.yml连接起来
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
//后台监控(只要进入特定网址就会开始监控后台):web.xml,ServletRegistrationBean
//因为springboot内置了servlet容器,所以没有web.xml。替代方法:ServletRegistrationBean
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");//注意必须是一个*,两个**会报错
//后台需要有人登陆,账号密码配置
HashMap<String, String> initParameters = new HashMap<>();
//增加配置(两个key都是固定的)
initParameters.put("loginUsername","admin");
initParameters.put("loginPassword", "123456");
//允许谁可以访问(value为空则所有人都可访问;localhost则本机可以访问;或为特定的人)
initParameters.put("allow", "");
//禁止谁能访问
//initParameters.put("yang", "192.168.11.123");
bean.setInitParameters(initParameters);//设置初始化参数
return bean;
}
//filter设置过滤器
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
//设置过滤器
bean.setFilter(new WebStatFilter());
//可以过滤那些请求
HashMap<String, String> initParameters = new HashMap<>();
//这些不进行统计
initParameters.put("exclusion","*.js,*.css,/druid/*");
bean.setInitParameters(initParameters);
return bean;
}
}
打开http://localhost:8080/druid即可进行登录,登录完成即可查看日志数据。其中,若对数据库进行操作,在“SQL监控”就会有数据显示:
整合Mybatis框架(视频33)
新建一个项目springboot-study04-mybatis,选中spring web、JDBC API、Mysql Driver,点击确定。
导入依赖:
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
连接数据库:在application.properties中写:
spring.datasource.username=root
spring.datasource.password=yanglejia2008
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 整合mybatis
mybatis.type-aliases-package=com.example.springbootstudy04mybatis.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
测试连接是否成功:在Tests.java里写:
@SpringBootTest
class SpringbootStudy04MybatisApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println(dataSource.getClass());
System.out.println(dataSource.getConnection());
}
}
点击该类的run,看输出是否正确,若出现报错解决即可。
注:出现过报错Public Key Retrieval is not allowed,解决方法是在连接后面添加 allowPublicKeyRetrieval=true。
在右侧的Database里连接一下数据库中的mybatis库(库名随意)。
导入lombok依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
在上图位置处新建一个User实体类,按照数据库中的User的属性写:
@Data
@NoArgsConstructor //无参构造
@AllArgsConstructor //有参构造
public class User {
private int id;
private String name;
private String pwd;
}
再写一个Mapper接口类,位置也如图。
@Mapper //注解表示了这是一个mybatis的mapper类
@Repository //在Dao层
public interface UserMapper {
List<User> queryUserList();
User queryUserById(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
新建UserMapper.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.example.springbootstudy04mybatis.mapper.UserMapper">
<select id="queryUserList" resultType="User">
select * from user
</select>
<select id="queryUserById" resultType="User">
select * from user where id= #{id}
</select>
<insert id="addUser" parameterType="User">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
<update id="updateUser" parameterType="User">
update user set name=#{name},pwd=#{pwd} where id#{id}
</update>
<delete id="deleteUser" parameterType="User">
delete from user where id#{id}
</delete>
<!-- 若要开启缓存,标签用cache或加上usercache="true"-->
</mapper>
新建一个UserController类,通过使用userMapper来进行操作:
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
//查询
@GetMapping("/queryUserList")
public List<User> queryUserList(){
List<User> userList = userMapper.queryUserList();
for(User user:userList)
System.out.println(user);
return userList;
}
//添加一个用户
@GetMapping("/addUser")
public String addUser(){
userMapper.addUser(new User(10,'aa',"222"));
return "ok";
}
//修改一个用户
@GetMapping("/updateUser")
public String updateUser(){
userMapper.updateUser(new User(11,"aa","22222"));
return "ok";
}
//根据id删除用户
@GetMapping("/deleteUser")
public String deleteUser(){
userMapper.deleteUser(10);
return "ok";
}
}
打开localhost:8080/xxx即可看到对应操作对应的结果,数据库中数据也有所更改。
总体步骤为:导入包->配置文件->mybatis配置->编写sql->service层调用dao层->controller层调用service层。
SpringSecurity环境搭建(视频34)
安全是非功能性需求,应该在设计之初就要考虑。
知名框架有shiro、springsecurity,两个很像,包含认证、授权。
创建新项目springboot-study05-security,选spring web。
引入thymeleaf依赖:
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
在application.properties里关闭缓存:
spring.thymeleaf.cache=false
在controller类中写,(将页面与html对应):
@Controller
public class RouterController {
@RequestMapping({"/", "/index"})
public String index(){
return "index";
}
@RequestMapping("/toLogin")
public String toLogin(){
return "views/login"; //指向html文件
}
@RequestMapping("/level1/{id}")
public String level1(@PathVariable("id") int id){ //使用上一行传进来的id
return "views/level1/"+id;
}
@RequestMapping("/level2/{id}")
public String level2(@PathVariable("id") int id){
return "views/level2/"+id;
}
@RequestMapping("/level3/{id}")
public String level3(@PathVariable("id") int id){
return "views/level3/"+id;
}
}
用户认证和授权+注销及权限控制+记住我及首页定制(视频35+36+27)
SpringSecurity是针对spring项目的安全框架,也是spring boot底层安全模块默认的技术选型,可以实现强大的web安全控制,仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理。
springsecurity的两个主要目标是“认证”和“授权”。
记住几个类:
- WebSecurityConfigurerAdapter:自定义Security策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式
用户认证和授权 开始学习:
导入security:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
新建config文件夹,新建SecurityConfig文件,内写:
给页面进行授权,如是vip1、vip2、vip3才可以访问的页面;
对不用用户可以给予不同角色vip1、vip2、vip3,可访问的页面不同。
//AOP:拦截器
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人都可以访问(permitAll),功能页只有对应有权限的人才能访问
//请求授权的规则
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/*").hasRole("vip1")
.antMatchers("/level2/*").hasRole("vip2")
.antMatchers("/level3/*").hasRole("vip3");
//没有权限,则默认会到登录页面("/login"),即使这个登录没写也会自动有(加上loginPage之后,登陆页面会转变成自己写的页面)。
http.formLogin().loginPage("/toLogin");
}
//认证,springboot 2.1.x可以直接使用的
//密码编码:PasswordEncoder,密码必须要进行加密才能使用
//在spring security 5.0+ 新增了很多的加密方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//这些数据正常来说应该从数据库中读(and用来拼接用户)
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("yang").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3","vip1")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
}
}
用户认证和授权完成
下面是注销及权限控制
在html页面写,其中/logout是固定用法:
<a class="item" th:href="@{/logout}">
<i class="address card icon"></i> 注销
</a>
在授权那部分代码里加:
//开启注销功能,跳到首页
http.logout().logoutSuccessUrl("/");
注销功能完成
接下来,想实现vip1角色的用户只能看见vip1的东西,不能看见vip2、3的东西这个功能。
先导入security与thymeleaf的整合包(也可以一开始创建项目时就勾选thymeleaf和springsecurity,IDEA会自动导入依赖):
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
在需要使用的html页面加上xmlns:sec:
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
先实现“没登录时显示登陆按钮,登陆成功显示用户名、角色信息以及注销按钮”:
<!--如果未登陆,显示登陆按钮-->
<div sec:authorize="!isAuthenticated()"> <!--isAuthenticated()判断是否登陆,注意感叹号-->
<a class="item" th:href="@{/toLogin}">
<i class="address card icon"></i> 登录
</a>
</div>
<!--如果已登陆,显示用户名、角色和注销按钮-->
<div sec:authorize="isAuthenticated()"> <!--isAuthenticated()判断是否登陆-->
<a class="item">
用户名:<span sec:authentication="name"></span>
角色:<span sec:authentication="principal.authorities"></span>
</a>
</div>
接下来,实现“vip1角色的用户只能看见vip1的东西,不能看见vip2、3的东西”这个功能。
在需要判断显示的部分加上,表明这是vip1能显示的:
<div sec:authorize="hasRole('vip1')">
实现记住我功能
在授权那部分代码里加:
//开启记住我功能
http.rememberMe();
注:视频37里还有定制的登录面,但没听懂,需要的时候再去查。还有记住我的一点小操作,同上。
Shiro快速开始(视频38)
什么是Shiro?
- Apache Shiro 是一个java的安全(权限)框架。
- Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。
- Shiro可以完成认证、授权、加密、会话管理、web集成、缓存等
- 下载地址http://shiro.apache.org/
开始学习
新建一个maven项目springboot-study06-shiro,创建一个module(如下图)
注,要补充的知识:
th:selected
th:checked
th:value
th:text
return “redirect:/emps”
@PostMapping
@GetMapping
@Mapper //注解表示了这是一个mybatis的mapper类
@Data
@NoArgsConstructor
@AllArgsConstructor
@bean
@ConfigurationProperties
@Configuration
method=“post”
MVC?(m:数据和业务;c:交接;v:html)