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)

关于swagger的简介点击这里

在springboot中使用logback点我总结就是1.添加依赖2.在资源文件夹新建一个logback.xml,写上相应的配置.3.在需要添加日志的地方.添加日志.

在springboot中使用测试点我

就是在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文件中添加

  1. 在pom.xml中添加新的插件

  1. 找到项目文件的根目录,在cmd命令行中输入:mvn clean package

出现build success即为打包完成

  1. 在项目中的target目录下出现一个可执行的jar文件

此时在此文件夹下运行:java -jar demo-0.0.1-SNAPSHOT.jar命令完成项目部署

1.乐优商城,.项目介绍和面试建议在最后一个视频.
前台页面的打开方法:
live-server --port=9002

在controller前加一个@CrossOrigin 这样整个Controller下的所有方法都支持跨域访问。

关于token,请点击这里

关于SpringMVC的异常处理
  1. 在Controller里写一个异常处理方法,给方法加一个@ExceptionHandler的注解,那么Controller遇到异常时就会调用该方法.
  2. 统一的异常处理类,写一个父类,父类里有这个异常处理方法,然后所有的Controller类都继承这个父类,那么所有的Controller就都有了异常处理方法.
  3. 写一个统一的Handler,用@ControllerAdvice来注解, 里面的方法使用@ExceptionHandler来注解.那么所有的异常都会交给这个类的对应方法来处理了.(注:@ControllerAdvice有升级版,@RestControllerAdvice,这个注解修饰的类里面的所有方法都默认添加@ResponseBody注解.)

springboot的拦截器

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的核心类

  1. Authentication
    用来表示用户信息,在用户登录认证之前,Spring Scurity会把相关信息封装为一个Authentication具体实现类的对象,在登陆认证成功之后又会生成一个信息更全面,包含用户权限等信息的Authentication对象,然后把他保存在SecurityContextHolder所持有的SecurityContext中,供后续的程序进行调用,如访问权限的鉴定等。
  2. SecurityContextHolder
    是用来保存SecurityContext的,SecurityContextHolder中持有的是当前用户的详细信息。
    举个例子,比如,我们要获取用户名,可以这样写String username = SecurityContextHolder.getContext().getAuthentication().getName();
  3. UserDetails
    包含了一些可以获取用户名,密码,权限的方法。多使用其实现类User
  4. UserDeatilsService
  5. GrantedAuthority
  6. DaoAuthenticationProvider
  7. 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的属性

posted @ 2019-11-24 15:58  时光轻轻吹  阅读(250)  评论(0编辑  收藏  举报