什么是Spring
Spring是一个开源的框架,主要是用来简化开发流程
Spring是如何简化Java开发
微服务是一种架构,他要求我们在开发应用的时候,这个应用必须构建成一系列小服务的组合:可以通过Http(rpc)的方式进行互通。
环境的依赖 java1.8、maven3.6.1,SpringBoot:最新版 IDEA
@RestController
public class Hello {
@RequestMapping("/hello")
public String getHello(){
return "Hello SpringBoot";
}
}
pom.xml
启动器
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
主程序
@SpringBootApplication //标注这个类是一个Spring Boot类
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
常见的注解
@SpringBootConfiguration :表示Spring Boot的配置
@Configuration:表是Spring的配置类
@Component:说明这也是一个Spring的组件
@EnableAutoConfiguration:表示自动配置
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackageRegistrar.class):自动配置包注册
@Import(AutoConfigurationImportSelector.class):自动导入选择
结论:springBoot所有自动配置都是在启动的时候扫描并加载,Spring.factories所有的自动配置类都在这里面,但是不一定失效,要判断条件四否成立,只要导入对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效。然后就是配置成功!
SpringBoot谈谈自己的理解
SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的
**配置文件的作用 :**修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;
比如我们可以在配置文件中修改Tomcat 默认启动的端口号!测试一下!
YAML是 “YAML Ain’t a Markup Language” (YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)
*这种语言以数据***作**为中心,而不是以标记语言为重点!
以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml
传统xml配置:
<server>
<port>8081<port>
server>
yaml配置:
server:
prot: 8080
注:yaml的语法要求十分严格,必须按照其中的规范进行编写
字面量:普通的值[数字、布尔值、字符串]
字面量直接写在后面的可以,字符串默认不用加上双引号或者是单引号
K:v
注意:
""双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思
例:name: “kuang \n shen” 输出 :kuang 换行 shen
‘’ 单引号,会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出
例:name: ‘kuang \n shen’ 输出 :kuang \n shen
对象、map(键值对)
#对象、map格式
k:
v1:
v2:
#注:在使用的配置文件是yaml时,空格一定不能省略
student:
name: lisi
age: 3
行内写法
student: {name: lisi,age: 3}
数组
pets:
- cat
- dog
- pig
行内的写法
server:
port: 8081
yaml文件的强大在于,它可以给我们的实体类直接注入匹配的值
yaml可以直接给实体类进行赋值
报红解决的办法
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
在pom.xml文件中添加上述的依赖
@ConfigurationProperties(prefix = “person”)的作用
将配置文件中配置的每一个属性的值,映射到组件之中;
告诉Springboot将本类中的所有属性和配置文件相关的配置进行绑定
参数prefix=”person“:将配置文件中person下面所有的属性一一对应
只有这个组件时容器中的组件,才能使用容器提供的ConfigurationProperties功能
yaml与properties的比较
结论
注:建议在以后的编程的时候使用yaml格式,能够做到根据不同的场合进行采取不同的写法
JSR303中用到的注解
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) string is between min and max included.
日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符合正则表达式的规则
.......等等
除此以外,我们还可以自定义一些数据校验规则
通过properties文件进行多环境的配置
注:根据开发的需要,可能需要多个配置文件以及端口,我们可以通过设置多个properties文件进行分开测试
通过yaml文件进行多环境的配置
server:
port: 8081
#选择要激活那个环境块
spring:
profiles:
active: prod
---
server:
port: 8083
spring:
profiles: dev #配置环境的名称
---
server:
port: 8084
spring:
profiles: prod #配置环境的名称
注:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的
自动装配的原理
注:Spring boot最主要的特点便是自动装配
SpringBoot帮我们配置的东西(是否可以修改)
web开发需解决的问题
总结:
模板引擎
thymeleaf模板引擎:类似于jsp文件,对相关的静态的HTML文件进行相关的处理,使其能够进行数据的接收
thymeleaf模板引擎所需要的maven依赖
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleafartifactId>
dependency>
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleaf-spring4artifactId>
<version>3.0.12.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
注:在进行thymeleafmaven依赖引进的时候,注意版本,SpringBoot2.0+采用的thymeleaf的版本为3.0+、当SpringBoot1.0+的时候我们所需要的maven的依赖为2.0+
HTML文件存放的位置
注:在templates下的HTML文件需要必须通过Controller进行相关的跳转
HTML接收数据
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>你好世界h1>
<div th:text="${msg}" style="color:red;">div>
body>
html>
注:当进行数据读取的时候,需要在开头引入相关的配置
<html lang="en" xmlns:th="http://www.thymeleaf.org">
第一个前后端的信息的交互
后端写法
package com.example.demo.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class testController {
@RequestMapping("/test")
public String test(Model model){
model.addAttribute("msg","你好世界");
return "test";
}
}
前端写法
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>你好世界h1>
<div th:text="${msg}" style="color:red;">div>
body>
html>
遍历文件
package com.example.demo.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Arrays;
@Controller
public class testController {
@RequestMapping("/test")
public String test(Model model){
model.addAttribute("msg","你好世界");
//Arrays.asList将文件返回一个集合
model.addAttribute("user", Arrays.asList("李四","张三"));
return "test";
}
}
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>你好世界h1>
<div th:text="${msg}" style="color:red;">div>
<h3 th:each="user1:${user}" th:text="${user1}">h3>
body>
html>
yaml文件中的配置
spring:
datasource:
username: root
password: lyj18366635303
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
#设置端口号
server:
port: 8090
进行java测试
package com.li.inspur.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
public class testController {
@Autowired
JdbcTemplate jdbcTemplate;
@RequestMapping("/select")
@ResponseBody
public String selectUser(){
String sql="select * from student";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
for (Map<String, Object> map : maps) {
System.out.println(map);
}
return "ok";
}
// restful风格 在使用其风格时,必须是GetMapping的方式进行请求
@GetMapping ("/delete/{id}")
public String deleteUser(@PathVariable("id") int id){
System.out.println("进了这个方法");
String sql="delete from student where id=?";
jdbcTemplate.update(sql,id);
return "deleteUser ok";
}
}
注:在使用restful风格进行传输数据的时候,请求方式必须是GET方式进行请求,必须通过@PathVariable进行对传输的数据进行一一对应
Druid简介
Druid是阿里巴巴开源平台上一个数据连接池实现,结合了C3p0、DBCP、PROXOOL等DB池的优点,同时加入了日志的监控
Druid可以很好的监控DB池连接和SQL的执行情况,天生就是针对监控而生的DB连接池。
SpringBoot2.0以上默认使用HiKari数据源,可以说HiKari与Druid都是当前javaweb上最优秀的数据源。
com.alibaba.druid.pool.DruidDataSource 基本配置参数如下:
参考网站:https://www.cnblogs.com/melodyjerry/p/13762822.html#8springboot%E6%95%B4%E5%90%88druid
所需要的maven依赖
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.12version>
dependency>
druid文件的配置
spring:
datasource:
username: root
password: lyj18366635303
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#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 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
设置后台的检测器
package com.li.inspur.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.servlet.Filter;
import javax.servlet.ServletRegistration;
import javax.sql.DataSource;
import java.util.HashMap;
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource(){
return new DruidDataSource();
}
// 设置后台监控 类似与web.xml
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean<StatViewServlet> statViewServletServletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
// 后台需要有人登录,需要账号密码
HashMap<String,String> hashMap=new HashMap<>();
// 登录的key是固定的参数
hashMap.put("loginUsername","admin");
hashMap.put("loginPassword","admin");
// 允许谁能访问
hashMap.put("allow","");//表示所有人都可以访问
// 禁止谁能访问
// hashMap.put("lisi","10.64.27.3");
statViewServletServletRegistrationBean.setInitParameters(hashMap);
return statViewServletServletRegistrationBean;
}
// 设置过滤器
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
// 设置过滤器
filterFilterRegistrationBean.setFilter(new WebStatFilter());
// 可以过滤的请求
HashMap hashMap=new HashMap();
// 表示这些东西不进行统计~
hashMap.put("exclusions","*.js,*.css,/druid/*");
filterFilterRegistrationBean.setInitParameters(hashMap);
return filterFilterRegistrationBean;
}
}
整合需要的包(mybatis-spring-boot-start)
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.2.0version>
dependency>
yaml文件中的配置
#配置端口号
server:
port: 8090
#配置数据库
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
password:
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.mybatis.pojo
mapper接口的定义
package com.example.mybatis.mapper;
import com.example.mybatis.pojo.Student;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface Studentmapper {
public List<Student> getStudentInformation();
}
注:配置不同模块的接口建议使用不同的注解
在配置mapper接口的时候需要的注解
@Mapper
@Repository
在配置mapper.xml文件的时候注意配置相关的工作空间
在配置service的接口的时候使用的注解
在配置Controller的时候使用的注解
注:网站的安全环境是在网站的搭建的前期来进行思考的
主要的功能:认证与授权
简介:
Spring Security是针对Spring项目的安全框架,也是SpringBoot底层安全模块的默认的技术的选型,它可以实现强大的web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理
记住几个类
SpringSecurity的两个主要目标是“认证和授权”(访问控制)
认证:Authentication
授权:Authorization
package com.example.security.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//表示这个类已经被Spring托管
@EnableWebSecurity
public class Security extends WebSecurityConfigurerAdapter {
// 权限的配置
@Override
protected void configure(HttpSecurity http) throws Exception {
// 首页所有人可以访问,但是功能页只有有权限的人才可以访问
// 链式编程
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1");
// 在没有权限的时候会默认额跳转到登陆页面,需要爱看i其登录页面,可以进行自定义页面
http.formLogin();
// 开启注销功能
http.csrf().disable();//关闭csrf功能,登录失败可能存在的原因
// 开启注销功能
http.logout();
// 开启记住我的功能,可以进行自定义
http.rememberMe();
}
// 用户的认证 springboot2.0.x可以直接的使用
// 密码编码:passwordEncoder
// 在Spring secutiry 5.0+新增了很多的方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 在设置密码的时候密码必须加密,不然报错,在2.0+的版本当中
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("lisi").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
.and()
.withUser("zhangsan").password(new BCryptPasswordEncoder().encode("23456")).roles("vip1","vip2","vip3");
}
}
定义
shiro的三大基本对象
1 Subject 用户
2 SecurityManager 管理所有用户
3 Realm 连接数据
所需要的maven依赖
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.4.1version>
dependency>
或者
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-spring-boot-web-starterartifactId>
<version>1.7.1version>
dependency>
java的实现
shiroConfig
package com.example.spring.config;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//进行配置的时候需要倒着配置
@Configuration
public class shiroConfig {
// shiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
return shiroFilterFactoryBean;
}
// DefaultWebSecurityManger
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
// 创建realm对象,需要自定义
@Bean(name = "userRealm")
public UserRealm userRealm(){
return new UserRealm();
}
}
UserRealm
package com.example.spring.config;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
//进行自定义realm
public class UserRealm extends AuthorizingRealm {
// 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权");
return null;
}
// 认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证");
return null;
}
}
package com.example.spring.config;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
//进行配置的时候需要倒着配置
@Configuration
public class shiroConfig {
// shiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
// 添加shiro的内置过滤器
/*
* anno:无需认证便可以访问
* authc:必须认证才能访问
* user:必须拥有 记住我 功能采用
* perms:拥有对某个资源的权限才能访问
* role:拥有某个角色的权限才可以访问
* */
Map<String,String> hashMap=new LinkedHashMap<>();
hashMap.put("/add","authc");
hashMap.put("/update","authc");
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setFilterChainDefinitionMap(hashMap);
return shiroFilterFactoryBean;
}
// DefaultWebSecurityManger
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
// 创建realm对象,需要自定义
@Bean(name = "userRealm")
public UserRealm userRealm(){
return new UserRealm();
}
}
注:用户的认证需要放在realm中
@RequestMapping("/tologin")
public String login( String username,String password,Model model){
System.out.println("username=>"+username+"password=>"+password);
// 获取用户对象
Subject subject= SecurityUtils.getSubject();
System.out.println("获取的用户对象是"+subject.toString());
// 对其进行封装
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
System.out.println("封装的用户的信息"+usernamePasswordToken);
// 执行登录的方法,如果没有异常说明OK了
try{
subject.login(usernamePasswordToken);
return "index";
}catch (UnknownAccountException e){
model.addAttribute("msg","用户名错误");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg","密码错误");
return "login";
}
}
realm
// 认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证");
// 设置用户名和密码,在数据库中进行搜索
String name="root";
String password="123456";
UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
if (!usernamePasswordToken.getUsername().equals(name)){
return null;//自动抛出异常
}
return new SimpleAuthenticationInfo("",password,"");
// return null;
}
}
在进行用户认证的时候,在Controller中获取用户并进行封装之后,shiro会自动的在realm类中进行认证
}catch (UnknownAccountException e){
model.addAttribute("msg","用户名错误");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg","密码错误");
return "login";
}
}
> realm
```java
// 认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证");
// 设置用户名和密码,在数据库中进行搜索
String name="root";
String password="123456";
UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
if (!usernamePasswordToken.getUsername().equals(name)){
return null;//自动抛出异常
}
return new SimpleAuthenticationInfo("",password,"");
// return null;
}
}
在进行用户认证的时候,在Controller中获取用户并进行封装之后,shiro会自动的在realm类中进行认证