Spring学习笔记
@RestController
/*@RestController注解,相当于@Controller+@ResponseBody两个注解的结合,返回json数据不需要在方法前面加@ResponseBody注解了,
但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面*/
@GetMapping("/{id}")
//GetMapping是一个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写。
//可以在@RequestMapping注解中用{}来表明它的变量部分
//在路由中定义变量规则后,通常我们需要在处理方法(也就是@RequestMapping注解的方法)中获取这个URL的具体值,
// 并根据这个值(例如用户名)做相应的操作,SpringMVC提供的@PathVariable可以帮助我们,还可以有多个,用不同的{}来取值就好.
@RequestMapping("/user")//有没有这个'/'都无所谓的
@MapperScan("com.gaolei.user.mapper")
/*之前是,直接在Mapper类上面添加注解@Mapper,这种方式要求每一个mapper类都需要添加此注解,麻烦。通过使用@MapperScan可以指定要扫描的Mapper类的包的路径*/
@Table(name = "tb_user")
//声明此对象映射到数据库的数据表,通过它可以为实体指定表(talbe),
// name 用来命名 当前实体类 对应的数据库 表的名字
@Data//免去写getter以及setter,以及tostring,equals等方法,非常实用,但是要安装lombok插件
@Id//主键字段
@GeneratedValue(strategy = GenerationType.IDENTITY)//主键自动生成策略
type-aliases-package 别名扫描包
@Bean
/*Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。
产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。
默认bean的名称就是其方法名。*/
User user=restTemplate.getForObject(url,User.class);
//发送GET请求,将HTTP response转换成一个指定的object对象
/*
* 参数1: String类型 或 URI类型的请求地址
* 参数2: 指定返回的实体类型,class对象
* 参数3: uri参数,可以是变长数组或map
* 返回值:responseType指定的Object类型
*/
@EnableDiscoveryClient//能够让注册中心能够发现,扫描到该服务,支持多种微服务注册中心
微服务eureka注册服务三步走:第一步添加依赖,第二步添加注解,第三步增加配置文件信息
@SpringCloudApplication//此注解是springcloud标准服务注解,一个顶多个用,写着一个,启动器就不用写其他的注解了
@HystrixCommand(fallbackMethod = "queryByIdFallback")//开启熔断处理和线程降级,有错就调用括号里面的方法,错误处理的方法,参数和返回值必须和注解的方法一致
@DefaultProperties(defaultFallback = "queryByIdFallback")//默认属性,所有方法熔断都会调用括号里面的方法,加在类上面,方法上依旧要加HystrixCommand注解,只是不用写括号里面的方法名了,通用的错误处理方法,不能有参数.
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")//设置为2秒钟熔断
})//开启熔断处理和线程降级,有错就调用括号里面的方法
@Component//把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
spa是单页面应用.webpack是前端打包工具.
</dependencyManagement>这个标签只会绑定版本,并不会真正的导入<dependencies>才会真正导入,这个一定要记住
@RequestMapping如果没有指定请求方式,将接收Get,Post,Head,Options等所有的请求方式
@GetMapping是一个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写。
@PostMapping是一个组合注解,是@RequestMapping(method = RequestMethod.POST)的缩写。
通过@ControllerAdvice注解可以将对于控制器的全局配置放在同一个位置。
注解了@Controller的类的方法可以使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上。
@ControllerAdvice注解将作用在所有注解了@RequestMapping的控制器的方法上
@ExceptionHandler:用于全局处理控制器里的异常。
一个枚举类举例:
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum ExceptionEnums {
PRICE_CANNOT_BE_NULL(400,"价格不能为空");
private int code;
private String msg;
}
@RequestParam
GET和POST请求传的参数会自动转换赋值到@RequestParam 所注解的变量上
ResponseEntity<>这是一个范型类,里面可以传递任意参数,它用来返回rest风格的请求.想返回啥类型都用它来包装一下.返回值的话如下所示:
return ResponseEntity.status(HttpStatus.OK).body(真正的类型);
当然可以简写,return ResponseEntity.ok(类型);//这是返回成功,其他还是按照上面的方法写.
//通用Mapper的select方法,里面传一个对象参数.将对象里的非空字段作为查询的对象参数.
用springboot+springcloud+通用Mapper,所有的单表Mapper操作,不需要写mapper的配置文件,只需要写一个mapper接口即可.
构造函数的声明不可以带范型
/**
* 新增品牌
* @param brand
* @param cids
* @return
*/
@PostMapping
//这里直接写brand是因为springmvc会直接把前端传来的数据和brand对象的参数对应,而cids则需要填充,因为没有对应的,当然
//和前端参数名字一样的话也可以省略掉@RequestParam注解.总之springmvc的参数封装很智能
public ResponseEntity<Void> saveBrand(Brand brand, @RequestParam("cids")List<Long> cids){
brandService.saveBrand(brand,cids);
return ResponseEntity.status(HttpStatus.CREATED).build();//没返回值直接build就好
}
//在mybatis的mapper里,有一种用注解写SQL语句的方式,直接在方法上面添加注解,@Insert或者其他的注解,里面写SQL语句即可.然后方法的参数用@Param来注解,这样在SQL语句里就可以取到参数了.举个例子(一条插入语句):
public interface BrandMapper extends Mapper<Brand> {
@Insert("INSERT INTO tb_category_brand (category_id, brand_id) VALUES (#{cid},#{bid}) ")
int insertCategoryBrand(@Param("cid") Long cid,@Param("bid") Long bid);
}
@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性
@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
@Column(name = "`numeric`")//这个注解是给通用mapper看的,告诉通用mapper,在生成查询语句的时候,不要使用变量的名字,而使用括号里的名字.
关于@PathVariable和@RequestParam的区别如下:
地址① http://localhost:8989/SSSP/emps?pageNo=2
地址② http://localhost:8989/SSSP/emp/7
如果想获取地址①中的 pageNo的值 ‘2’ ,则使用 @RequestParam ,
如果想获取地址②中的 emp/7 中的 ‘7 ’ 则使用 @PathVariable
@KeySql//Java 方式生成主键,可以和发号器一类的服务配合使用
@Transient是希望该属性不会在数据表中产生字段,但又可以在程序中使用它。于是,我们决定这么写。
/*
我总结的查询数据库数据(单表)的大致方法就是,首先有分页用分页助手加分页,没分页,下一步,加过滤条件,用反射创一个pojo的example
类,然后example创建过滤条件criteria,往criteria里加过滤条件,之后mapper调用selectByExample方法,把example对象传进去.
会得到一个pojo的list,整个过程结束.
*/
关于@RequestBody:
1、@requestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。
2、通过@requestBody可以将请求体中的JSON字符串绑定到相应的bean上,当然,也可以将其分别绑定到对应的字符串上。
例如说以下情况:
$.ajax({
url:"/login",
type:"POST",
data:'{"userName":"admin","pwd","admin123"}',
content-type:"application/json charset=utf-8",
success:function(data){
alert("request success ! ");
}
});
@requestMapping("/login")
public void login(@requestBody String userName,@requestBody String pwd){
System.out.println(userName+" :"+pwd);
}
这种情况是将JSON字符串中的两个变量的值分别赋予了两个字符串,但是呢假如我有一个User类,拥有如下字段:
String userName;
String pwd;
那么上述参数可以改为以下形式:@requestBody User user 这种形式会将JSON字符串中的值赋予user中对应的属性上
需要注意的是,JSON字符串中的key必须对应user中的属性名,否则是请求不过去的。
默认是使用getmapping的,postmapping要发送表单才可以.然后用requestmapping好像通用.
关于前端传到后端的参数封装问题,很简单.就是你只要后端的那个类有这个属性,那么就可以自动封装到这个类的属性上,不一定要所有的属性都全才行,有就可以.很方便,只要能够转换成功,格式正确,就完全没有问题.
@RunWith注解的作用:在使用所有注释前必须使用@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境 [Spring框架]在org.springframework.test.annotation 包中提供
Feign是Netflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。
在Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。
Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。
Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。
Spring Cloud Feign具备可插拔的注解支持,支持Feign注解、JAX-RS注解和Spring MVC的注解。
feign可以实现微服务之间的远程调用.利用feign,微服务1就可以调用微服务2.很方便
Sku是小分类,Spu是大分类.
RabbitMQ的默认账号和密码都是guest,自己新增的是账号密码leyou
十次方虚拟机的账号是root,密码是itcast. MySQL的账号和密码都是root. IP地址是 192.168.179.132
@Configuration 的注解类表示这个类可以使用 Spring IoC 容器作为 bean 定义的来源。@Bean 注解告诉 Spring,一个带有 @Bean 的注解方法将返回一个对象,该对象应该被注册为在 Spring 应用程序上下文中的 bean。
controller必须要跟启动类在一个包里面,要不然扫描不到的.
@Entity 表明该类 (UserEntity) 为一个实体类,它默认对应数据库中的表名是user_entity。这里也可以写成
@Entity(name = "xwj_user")
或者
@Entity
@Table(name = "xwj_user", schema = "test")
查看@Entity注解,发现其只有一个属性name,表示其所对应的数据库中的表名
@Table 当实体类与其映射的数据库表名不同名时需要使用 @Table注解说明,该标注与 @Entity 注解并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。
@Table注解的常用选项是 name,用于指明数据库的表名
@Table注解还有两个选项 catalog 和 schema 用于设置表所属的数据库目录或模式,通常为数据库名
如果缺省@Table注解,则class字段名即表中的字段名,所以需要@Column注解来改变class中字段名与db中表的字段名的映射规则
@Column注释定义了将成员属性映射到关系表中的哪一列和该列的结构信息,属性如下:
1)name:映射的列名。如:映射tbl_user表的name列,可以在name属性的上面或getName方法上面加入;
2)unique:是否唯一;
3)nullable:是否允许为空;
4)length:对于字符型列,length属性指定列的最大字符长度;
5)insertable:是否允许插入;
6)updatetable:是否允许更新;
7)columnDefinition:定义建表时创建此列的DDL;
8)secondaryTable:从表名。如果此列不建在主表上(默认是主表),该属性定义该列所在从表的名字
如果是主键id,还会用到@Id注解
@Id注释指定表的主键,它可以有多种生成方式:
1)TABLE:容器指定用底层的数据表确保唯一;
2)SEQUENCE:使用数据库德SEQUENCE列莱保证唯一(Oracle数据库通过序列来生成唯一ID);
3)IDENTITY:使用数据库的IDENTITY列莱保证唯一;
4)AUTO:由容器挑选一个合适的方式来保证唯一;
5)NONE:容器不负责主键的生成,由程序来完成。
如果一个类带了@Service注解,将自动注册到Spring容器,不需要再在applicationContext.xml文件定义bean了,类似的还包括@Component、@Repository、@Controller。
@Transactional
在出现异常的情况下,保证数据的一致性;数据提交操作回滚至异常发生前的状态
IDEA打开rundashboard的方法:找到.idea文件夹,找不到就是隐藏了,
打开workspace.xml文件之后,找到component为RunDashboard的节点处,然后在component标签里添加
<option name="configurationTypes">
<set>
<option value="SpringBootApplicationConfigurationType" />
</set>
</option>
swagger是当前最好用的Restful API文档生成的开源项目,通过swagger-spring项目实现了springMVC框架的无缝集成功能,方便生成restful风格的接口文档,
同时,swagger-ui还可以测试spring restful风格的接口功能
作用:
1、接口的文档在线自动生成
2、功能测试
先介绍它的常用注解
@Api 注解可以用来标记 Controller 的功能
@ApiOperation 注解用来标记一个方法的作用
@ApilmplicitParam 注解用来描述一个参数,可以配置参数的中文含义,也可以给参数设置默认值,这样在接口测试的时候可以避免手动输入
@ApilmplicitParams 如果有多个参数,则需要使用多个 @ApilmplicitParam 注解来描述, 多个 @ApilmplicitParam 注解需要放在一个 @ApilmplicitParams 注解中
@ApiModel 如果参数是一个对象,则需要在对象所在的类上加上此注解
@ApiModelProperty 如果参数是一个对象,则需要在对应的属性上加上此注解,还需要在对象所在的类上加上 @ApiModel
@ApiIgnore 注解标识此参数可以忽略
@EnableScheduling开启定时任务
关于日志系统
slf4j是什么
slf4j只是一套标准,通俗来讲,就是定义了一系列接口,它并不提供任何的具体实现。所以,我们使用这套接口进行开发,可以任意的切换底层的实现框架。
比如,一开始项目用的是log4j的实现,后来发现log4j的性能太差了,想换成logback,由于我们代码中都是面向slf4j接口的,这样我们只要吧log4j的依赖换成logback就可以了。
@Autowired注解会让spring自动帮你生成,你就不用new了,不然要自己new一个,而且spring可以保证我们用的都是同一个.而且也不用写这个变量的set和get
对于XPATH的@来说,不加中括号就是选取属性的值,加中括号就是选取有该属性的标签
SpringData JPA 在保存和删除前都会自动进行判断的,不用管存在不存在.
PagingAndSortingRepository 可以进行分页和排序
使用springdatajpa的@Query查询的时候要注意,select后面加的不是表名,而是对象名
JPQL语法:省略掉 select *
直接从from开始写起,而且,不要写表名,要写对应的实体类名.
jpql 不可以写select * 可以写其他的select count 等等..
只需要编写dao层接口,不需要写接口的实现类.
普通crud,继承JpaRepository即可.
复杂的查询,比如分页之类的,继承JpaSpecificationExecutor即可
默认的findONE方法可以根据ID查询一个,立即加载,而getone则是延迟加载.
save操作也能进行更新,只要保证你传进去的对象有ID就好,他会自动给你更新.但是会把其他的置为null,所以慎用~~
对于多个占位符参数赋值(也就是 ? )的时候,默认情况下,占位符的位置需要和方法参数中的位置保持一致.
可以这么写 ?2 取方法参数里的第二个参数.
进行数据库更新的时候,一个是要加上@Transictional注解(增删改都要加这个),,还要加上一个@Rollback(value = "false") 禁止回滚.
你要是想写sql语句,你就在查询语句后面加一个 nativequery = true, 这样就可以直接写sql语句了.
dao要继承JpaSpecificationExecutor开可以, 以上是一个使用specification的详细步骤,首先写一个匿名内部类,从root里面获取要查询的属性,在cb里构造查询.多个条件拼接的话可以用and, 用or.最后把匿名内部类传入到dao里的方法即可.
同时还需要注意 equals和其他方法有点不同:
排序的话,这样使用:
关于分页:
更多的关于springdatajpa的消息请看视频或者疯狂springboot2那本书.
配置一对多关系:
多对一类似.
级联删除,在主表上配置:
关于多对多:
多对多中,被动的一方放弃维护权
写一个这个就行了.
级联添加:(也就是另一个表的内容,他会自动帮你添加)
[更多关于springdatajpa的详细内容请点击这里](D:\Java学习资料\Java最新技术IDEA\Spring Data JPA\课件资料\day03\02-资料\SpringDataJPA第三天讲义.doc)
在springboot中使用logback点我总结就是1.添加依赖2.在资源文件夹新建一个logback.xml,写上相应的配置.3.在需要添加日志的地方.添加日志.
就是在test模块,写一个类,比如这样
@RunWith(SpringRunner.class)//这两个注解是重点
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test//还有这个注解
public void addUser() throws Exception {
Assert.assertEquals(Integer.valueOf(1),userService.addUser("zhihao.miao"));
Assert.assertEquals(Integer.valueOf(0),userService.addUser(null));
}
}
如何将springboot打包成jar包呢:
1. 在pom.xml文件中添加
- 在pom.xml中添加新的插件
- 找到项目文件的根目录,在cmd命令行中输入:mvn clean package
出现build success即为打包完成
- 在项目中的target目录下出现一个可执行的jar文件
此时在此文件夹下运行:java -jar demo-0.0.1-SNAPSHOT.jar命令完成项目部署
1.乐优商城,.项目介绍和面试建议在最后一个视频.
前台页面的打开方法:
live-server --port=9002
在controller前加一个@CrossOrigin
这样整个Controller下的所有方法都支持跨域访问。
关于SpringMVC的异常处理
- 在Controller里写一个异常处理方法,给方法加一个@ExceptionHandler的注解,那么Controller遇到异常时就会调用该方法.
- 统一的异常处理类,写一个父类,父类里有这个异常处理方法,然后所有的Controller类都继承这个父类,那么所有的Controller就都有了异常处理方法.
- 写一个统一的Handler,用@ControllerAdvice来注解, 里面的方法使用@ExceptionHandler来注解.那么所有的异常都会交给这个类的对应方法来处理了.(注:@ControllerAdvice有升级版,@RestControllerAdvice,这个注解修饰的类里面的所有方法都默认添加@ResponseBody注解.)
springboot的拦截器
[关于spring配置类的详细信息,请点击这里](https://www.cnblogs.com/dubhlinn/p/10662763.html)
写配置类的话,就是你自己写一个spring容器生成类的方法,spring就用你的方法来生成这个类,但是对象还是要交给spring来管理。
SpringSecurity
创建一个自定义类继承WebSecurity-ConfigurerAdapter,并在该类中使用@EnableWebSecurity注解,就可以通过重写config方法来配置所需要的安全配置。
WebSecurity-ConfigurerAdapter提供了两个方法用于重写开发者需要的安全配置。分别是
protected void configure(HttpSecurity httpSecurity) throws Exception{ }
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{ }
用户认证
比如我们添加一个用户:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//新添一个用户,用户名是“gaolei”,密码是“1763140594”,权限是USER
auth.inMemoryAuthentication().withUser("gaolei").password("1763140594").roles("USER");
}
用户授权
spring security 是通过configure(HttpSecurity http)来完成用户授权的。HttpSecurity的authorizeRequests()方法有多个子节点。每个mathcer按照他们的声明顺序执行,指定用户可以访问的多个URL模式。
- antMatchers 使用Ant风格的匹配路径
- regexMatchers 使用正则表达式风格的匹配路径
在匹配了请求路径后,可以针对当前用户的信息对请求路径进行安全处理,spring security提供的安全处理方法有如下:
- anyRequest 匹配所有请求路径
- access(String) SpringEL 表达式结果为true时可以访问
- anonymous() 匿名可以访问
- denyAll() 用户不能访问
- fullyAuthenticated() 用户完全认证可以访问
- hasAnyAuthority(String...) 如果有参数吗,参数表示权限,则其中任何一个权限可以访问
- hasAnyRole(String...) 如果有参数,参数表示角色,则其中任何一个角色可以访问
- hasAuthority(String...) 如果有参数吗,参数表示权限,则其权限可以访问
- hasIpAddress(String)如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
- hasRole(String...) 如果有参数,参数表示角色,则其角色可以访问
- permitAll() 用户可以任意访问
- remerberMe() 允许通过remerber-me登陆的用户访问
-authenticated()用户登陆后可以访问。
示例代码·:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() //开始请求权限配置
.antMatchers("/login").permitAll() //请求匹配“/login”,所有用户都可以访问
.antMatchers("/", "/home").hasRole("USER") //请求匹配“/”和“/home”,拥有“ROLE_USER”角色的用户可以访问
.antMatchers("/admin/**").hasAnyRole("ADMIN", "DBA") //请求匹配“/admin/**”,拥有"ADMIN", "DBA"这两个角色的用户可以访问
.anyRequest().authenticated();//其余所有的请求都需要认证(用户登录)之后才可以访问。
.and()
.formLogin() //开始设置登陆操作
.loginPage("/login") //设置登陆页面的访问地址
.usernameParameter("loginName").passwordParameter("password") //登陆时接收传递的参数“loginName”的值作为用户名,接收传递参数的“password”的值作为密码
.defaultSuccessUrl("/success") //指定登录成功后转向的页面
.failureUrl("/login?error") //指定登陆失败后转向的页面和传递的参数
.and()
.logout() //设置注销操作
.permitAll() //所有用户都可以访问
.and()
.excetpionHandling().accessDeniedPage("/accessDenied"); //指定异常处理的页面
}
spring security的核心类
- Authentication
用来表示用户信息,在用户登录认证之前,Spring Scurity会把相关信息封装为一个Authentication具体实现类的对象,在登陆认证成功之后又会生成一个信息更全面,包含用户权限等信息的Authentication对象,然后把他保存在SecurityContextHolder所持有的SecurityContext中,供后续的程序进行调用,如访问权限的鉴定等。 - SecurityContextHolder
是用来保存SecurityContext的,SecurityContextHolder中持有的是当前用户的详细信息。
举个例子,比如,我们要获取用户名,可以这样写String username = SecurityContextHolder.getContext().getAuthentication().getName();
- UserDetails
包含了一些可以获取用户名,密码,权限的方法。多使用其实现类User - UserDeatilsService
- GrantedAuthority
- DaoAuthenticationProvider
- PasswordEncoder
使用spring security
在pom文件中引入spring security:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
创建spring security的认证处理类
public class MyPasswordEncoder implements PasswordEncoder {
@Override
public String encode (CharSequence arg0) {
return arg0.toString();
}
@Override
public boolean matches(CharSequence arg0, String arg1) {
return arg1.equals(arg0.toString());
}
}
public class AppSecurityConfigurer extends WebSecurityConfigurerAdatper {
//注入认证处理类,处理不同用户跳转不同的页面
@Autowired
AppAuthenticationSuccessHandler appAuthenticationHandler;
//用户授权操作
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login", "/css/**", "/js/**", "/img/**").permitAll()
.antMatchers("/", "/home").hasRole("USER")
.antMatchers("/admin/**").hasAnyRole("ADMIN", "DBA")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login")
.successHandler(appAuthenticationHandler)
.usernameParameter("loginname").passwordParameter("password")
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedPage("/accessDenied")
}
//用户认证操作
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder()).withUser("gaolei").password("1763140594").roles("USER");
}
}
//认证成功处理类
@Component
public class AppAuthenticationHandler extends SimpleUrlAuthenticationSuccessHandler {
//Spring Security 通过RedirectStrategy 对象负责所有重定向事务
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
//重写handle方法,方法中通过RedirectStrategy对象重定向到指定的URL
@Override
protected void handle (HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws Exception {
//通过datermineTargetUrl方法放回需要跳转的URL
String targetUrl = determineRTargetUrl(authentication);
//重定向请求到指定的URL
redirectStrategy.sendRedirect(request, response, targetUrl);
}
//从Authentication对象中提取当前登录用户的角色,并根据其角色返回适当的URL
protected String determineTargetUrl(Authentication authentication) {
String url = "";
//获取当前登陆用户的角色权限集合
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
List<String> roles = new ArrayList<>();
//将角色名称添加到list集合
for(GrantedAuthority a : authorities) {
roles.add(authorities);
}
//判断不同角色跳转到不同的URL
if(isAdmin(roles)) {
url = "/admin";
} else if (isUser(roles)) {
url = "/home";
} else {
url = "/accessDenied";
}
System.out.println("url = " + url);
return url;
}
private boolean isUser(List<String> roles) {
if (roles.contains("ROLES_USER")) {
return true;
}
return false;
}
private boolean isAdmin(List<String> roles) {
if (roles.contains("ROLES_ADMIN")) {
return true;
}
return false;
}
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
protected RedirectStrategy getRedirectStrategy () {
return this.redirectStrategy;
}
}
这里有一个使用spring security的具体代码示例
或者也可以看疯狂springboot讲义也可以。
@Value(“${}”)注解用于从配置文件中获取属性. (用的多一些)
@Value(#{“”}) 获取其他bean的属性