栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring boot学习笔记——狂神说

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring boot学习笔记——狂神说

SpringBoot学习笔记 1.1 简介

Spring Boot 是 Pivotal 团队在 Spring 的基础上提供的一套全新的开源框架,其目的是为了简化 Spring 应用的搭建和开发过程。Spring Boot 去除了大量的 XML 配置文件,简化了复杂的依赖管理。

springboot配置文件名称是固定的:

  • application.properties 语法结构:key=value
  • application.yaml. 语法结构:key:空格 value
1.2 导入依赖

  org.springframework.boot
  spring-boot-starter-web



  org.springframework.boot
  spring-boot-devtools

1.3 Spring boot核心配置文件(application.properties)
#更改项目的端口号
server.port=8090

改变banner

1.4 Spring boot核心配置文件(application.yaml)
#key:空格value
server:
  port: 8091
#对象
student:
  name: songyaxuan
  age: 18
#行内写法
students: {name: liuyaowen,age: 16}
#数组
pets:
  -cat
  -dog
pet: [cat,dog]

yaml可以给实体类赋值

原来用@value给实体类赋值:

@Component
public class Dog {
    @Value("鼠标")
    private String name;
    @Value("1")
    private Integer age;
    }
@SpringBootTest
class SpbootApplicationTests {
    @Autowired
    private Dog dog;
    @Test
    void contextLoads() {
        System.out.println(dog);
    }
}

现在通过yaml赋值:

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birth;
    private Map maps;
    private List lists;
    private Dog dog;
}
 
server:
  port: 8091
person:
  name: songysxuan
  age: 18
  happy: true
  birth: 2004/03/04
  maps: {k1: v2,k2: v2}
  lists:
    -music
    -liu
  dog:
    name: shubiao
    age: 1

@SpringBootTest
class SpbootApplicationTests {
    @Autowired
    private Person person;
    @Test
    void contextLoads() {
        System.out.println(person);
    }
}

绑定指定配置文件并给实体类属性赋值:

tnt.properties:

name=shidaishaoniantuan
age=2

Person.java:

@Component
@PropertySource(value = "classpath:tnt.properties")
public class Person {
    //yaml支持el表达式
    @Value("${name}")
    private String name;
    @Value("${age}")
    private Integer age;
    }

测试类:

@SpringBootTest
class SpbootApplicationTests {
    @Autowired
    //private Dog dog;
    private Person person;
    @Test
    void contextLoads() {
        System.out.println(person.getName());
        System.out.println(person.getAge());
    }
}

1.5 Springboot Web开发

需要解决的问题:

  • 导入静态资源
  • 首页定制
  • jap–模版引擎thymeleaf
  • 装配扩展springMVC
  • 增删改查
  • 拦截器
1.5.1 静态资源

导入依赖:


  org.webjars
  jquery
  3.4.1

访问静态资源:

http://localhost:8080/webjars/jquery/3.4.1/jquery.js

或者创建目录(优先级:resource>statis>public)


1.5.2 首页定制

在templates目录下的所有页面,只能通过controller来跳转!

@RestController
public class IndexController {
    @RequestMapping("/index")
    public String index(){
        return "index";
    }
}

1.5.3 模版引擎thymeleaf

导入依赖:


  org.springframework.boot
  spring-boot-starter-thymeleaf

导入依赖以后只需要将html放入templates中,就可以通过controller访问来。

html文件中引入:



    
    Title


 
1.5.4 装配扩展MVC

先创建一个包config,在里面写一个类

//扩展mvc,implements WebMvcConfigurer并且不可以加注解@EnableWebMvc
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    //视图跳转
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
          //请求/candy时页面跳转到hello页面
        registry.addViewController("/candy").setViewName("hello");
    }
}

1.6 项目实战 1.6.1 准备工作

引入Lombok:


  org.projectlombok
  lombok

@Data:使用这个注解可以省去实体类中大量的get()、 set()、 toString()等方法。

@AllArgsConstructor:有参构造

@NoArgsConstructor:无参构造

注意:以上注解都是在Lombok中的!!!

package com.candy.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
//有参构造
@AllArgsConstructor
//无参构造
@NoArgsConstructor
public class Department {
    private Integer id;
    private String  departmentName;
}

导入模板:

编写实体类和dao层:

Employee.java:

package com.candy.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;//0女1男
    private Department department;
    private Date birth;
}

DepartmentDao.java:

package com.candy.dao;
import com.candy.pojo.Department;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class DepartmentDao {
    private static Map departments = null;
    static {
    departments = new HashMap();//创建一个部门表

    departments.put(101,new Department(101,"教学部"));
    departments.put(102,new Department(102,"市场部"));
    departments.put(103,new Department(103,"教研部"));
    departments.put(104,new Department(104,"运营部"));
    departments.put(105,new Department(105,"财务部"));

    }
    //获得所有部门信息
    public Collection getDepartments(){
        return  departments.values();
    }
    //通过id得到部门
    public Department getDepartmenrById(Integer id){
        return departments.get(id);
    }
}

EmployeeDao.java:

package com.candy.dao;
import com.candy.pojo.Department;
import com.candy.pojo.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Repository
public class EmployeeDao {
    private static Map employees = null;
    @Autowired
    private DepartmentDao departmentDao;
    static {
        employees = new HashMap();//创建一个员工表
        employees.put(1001,new Employee(1001,"马嘉祺","11@qq.com",1,new Department(101,"教学部"),new Date()));
        employees.put(1002,new Employee(1002,"丁程鑫","12@qq.com",1,new Department(101,"教学部"),new Date()));
        employees.put(1003,new Employee(1003,"宋亚轩","13@qq.com",1,new Department(102,"市场部"),new Date()));
        employees.put(1004,new Employee(1004,"刘耀文","14@qq.com",1,new Department(102,"市场部"),new Date()));
        employees.put(1005,new Employee(1005,"张真源","15@qq.com",1,new Department(103,"教研部"),new Date()));
        employees.put(1006,new Employee(1006,"严浩翔","16@qq.com",1,new Department(104,"运营部"),new Date()));
        employees.put(1007,new Employee(1007,"贺峻霖","17@qq.com",1,new Department(104,"运营部"),new Date()));

    }
    //主键自增
    private static Integer initId = 1008;
    //增加一个员工
    public void add(Employee employee){
        if (employee.getId()==null){
            employee.setId(initId++);
        }      employee.setDepartment(departmentDao.getDepartmenrById(employee.getDepartment().getId()));
        employees.put(employee.getId(),employee);
    }
    //查询所有员工
    public Collection getAll(){
        return employees.values();
    }
    //根据ID查询员工
    public Employee getEmploeeById(Integer id){
        return employees.get(id);
    }
    //删除员工
    public void del(Integer id){
        employees.remove(id);
    }
}
1.6.2 首页实现

先配置路径,可以访问index(在config的MyMvcConfig.java):

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("index.html").setViewName("index");
    }
}

导入thymeleaf在模板中,并按照规则修改标签中的属性

#关闭thymeLeaf缓存
spring.thymeleaf.cache=false


	
		
		
		
		
		Signin Template for Bootstrap
		
		
		
		
	

1.6.3 页面国际化

实现页面中文和英文语言切换!!!

先在resource目录下创建一个包:

然后在application.properties中写好配置文件的路径:

#配置文件的位置
spring.messages.basename=i18n.login

在前端页面中使用语法取值:

	

为了实现中文和English的按钮,我们自己需要自定义国际化,自己写一个类:

package com.candy.comfig;

import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;


public class MyLocalResolver 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("_");
        locale =  new Locale(split[0],split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}

然后在mymvcconfig中注册:

   //自定义国际化
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocalResolver();
    }


注意:需要先在idea设置的file encoding中将编码语言全部设置为utf-8,否则可能会乱码。

1.6.4 登陆功能实现

在前端页面中设置按钮请求:

		

然后写一个controller类管理登陆业务:

package com.candy.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class LoginController {
    @RequestMapping("/user/login")
    public String login(
            @RequestParam("username") String username,
            @RequestParam("password") String password,
            Model model
             ){
           if(!StringUtils.isEmpty(username)&&"123".equals(password)){
                //登陆成功之后重定向页面
               return "redirect:/main.html";
           }else {
               model.addAttribute("msg","用户名或者密码错误");
               return "index";
           }
    }
}

重定向页面需要在MyMvcConfig.java中配置:

  registry.addViewController("main.html").setViewName("dashboard");

1.6.5 登陆拦截器

需要自己写一个拦截类:

package com.candy.comfig;

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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;
       }
    }
}

在loginController.java中添加session(并将用户名放入session中保存):

最后在MyMvcConfig.java中注册配置类:

 @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerInterceptor())
                .addPathPatterns("
        Map filterMap = new LinkedHashMap();
        filterMap.put("/user/add","authc");
        filterMap.put("/user/update","authc");
        bean.setFilterChainDefinitionMap(filterMap);
        return bean;
    }

访问/user/add被拦截:

实现拦截后跳转到登陆页面:

创建login.html:


login

username:

password:

LOGIN

在controller层写跳转方法:

@RequestMapping("toLogin")
public String toLogin(){
  return "login";
}

最后在拦截之后设置登陆请求:

1.9.4 实现用户认证

用户认证放在Realm中

先去controller中添加处理登陆过程:

@RequestMapping("/login")
public String login(String username,String password,Model model){
  //获取当前用户
  Subject subject = SecurityUtils.getSubject();
  //封装用户的登陆数据
  UsernamePasswordToken token = new UsernamePasswordToken(username,password);
  try{
    subject.login(token);//执行登陆的方法
    return "index";
  }catch (UnknownAccountException e){//用户名不存在
    model.addAttribute("msg","用户名不存在");
    return "login";
  }catch (IncorrectCredentialsException e){//密码不存在
    model.addAttribute("msg","密码错误");
    return "login";
  }
}

然后去静态页面绑定数据:

最后去Realm中模拟数据并添加认证:

//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  System.out.println("认证了");
  //用户名、密码
  String name = "root";
  String password = "123";
  UsernamePasswordToken userToken = (UsernamePasswordToken)token;
  if (!userToken.getUsername().equals(name)){
    return null;//抛出异常 UnknownAccountException
  }
  //密码认证 shiro做
  return new SimpleAuthenticationInfo("",password,"");
}

测试:

1.9.5 整合mybatis

导入依赖:


  org.mybatis.spring.boot
  mybatis-spring-boot-starter
  2.1.1


  mysql
  mysql-connector-java
  runtime



  log4j
  log4j
  1.2.17



  com.alibaba
  druid
  1.2.7


    org.projectlombok
    lombok
    1.16.10

新建一个application.yaml:

spring:
  datasource:
    username: root
    password: root12345
    url: jdbc:mysql://localhost:3306/mybts?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
druid:
  #     配置初始化大小、最小、最大线程数
  initialSize: 5
  minIdle: 5
  #     CPU核数+1,也可以大些但不要超过20,数据库加锁时连接过多性能下降
  maxActive: 20
  #     最大等待时间,内网:800,外网:1200(三次握手1s)
  maxWait: 60000
  timeBetweenEvictionRunsMillis: 60000
  #     配置一个连接在池中最大空间时间,单位是毫秒
  minEvictableIdleTimeMillis: 300000
  validationQuery: SELECT 1
  testWhileIdle: true
  #     设置从连接池获取连接时是否检查连接有效性,true检查,false不检查
  testOnBorrow: false
  #     设置从连接池归还连接时是否检查连接有效性,true检查,false不检查
  testOnReturn: false
  #     可以支持PSCache(提升写入、查询效率)
  poolPreparedStatements: true
  #   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
  filters: stat,wall,log4j
  #     保持长连接
  keepAlive: true
  maxPoolPreparedStatementPerConnectionSize: 20
  useGlobalDataSourceStat: true
  connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:
  type-aliases-package: com.candy.pojo
  mapper-locations:
    - classpath:mapper
    private Boolean enable;
    private String applicationName;
    private String applicationVersion;
    private String applicationDescription;
    
    private String tryHost;

    public Boolean getEnable() {
        return enable;
    }
    public void setEnable(Boolean enable) {
        this.enable = enable;
    }
    public String getApplicationName() {
        return applicationName;
    }
    public void setApplicationName(String applicationName) {
        this.applicationName = applicationName;
    }
    public String getApplicationVersion() {
        return applicationVersion;
    }
    public void setApplicationVersion(String applicationVersion) {
        this.applicationVersion = applicationVersion;
    }
    public String getApplicationDescription() {
        return applicationDescription;
    }
    public void setApplicationDescription(String applicationDescription) {
        this.applicationDescription = applicationDescription;
    }
    public String getTryHost() {
        return tryHost;
    }
    public void setTryHost(String tryHost) {
        this.tryHost = tryHost;
    }
}

然后在写swaggerconfiguration:

package com.candy.config;
import com.candy.SwaggerProperties;
import io.swagger.models.auth.In;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.*;

@Configuration
@EnableOpenApi
public class SwaggerConfiguration {
    private final SwaggerProperties swaggerProperties;

    public SwaggerConfiguration(SwaggerProperties swaggerProperties) {
        this.swaggerProperties = swaggerProperties;
    }
    @Bean
    public Docket createReatApi(){
        return new Docket(DocumentationType.OAS_30).pathMapping("/")
                //定义是否开启swagger
                .enable(swaggerProperties.getEnable())
                //将api的元信息设置为包含json ResourceListing响应中
                .apiInfo(apiInfo())
                //设置接口调试地址
                .host(swaggerProperties.getTryHost())
                //选择哪些接口作为swagger的doc发布
                .select()
                //配置要扫描接口的方式 any:全部 basePackage:指定包
                .apis(RequestHandlerSelectors.basePackage("com.candy"))
                //过滤路径
                .paths(PathSelectors.any())
                .build()
                //支持的通讯协议集合
                .protocols(newHashSet("https","http"))
                //授权信息设置,必要的header token等认证信息
                .securitySchemes(securitySchemes())
                //授权信息全局应用
                .securityContexts(securityContexts());


    }
    //api页面上半部分展示信息
    private ApiInfo apiInfo(){
        return new ApiInfoBuilder().title(swaggerProperties.getApplicationName()+"ApiDoc")
                .description(swaggerProperties.getApplicationDescription())
                 //作者信息
                .contact(new Contact("sixcandy","null","1161187988@qq.com"))
                .version("application version:"+swaggerProperties.getApplicationVersion())
                .build();
    }
    private Set newHashSet(String type1,String type2){
        Set set = new HashSet<>();
        set.add(type1);
        set.add(type2);
        return set;
    }
    private List securitySchemes(){
         ApiKey apiKey = new ApiKey("BASE_TOKEN","token", In.HEADER.toValue());
        return Collections.singletonList(apiKey);
    }
    private List securityContexts(){
        return Collections.singletonList(
                SecurityContext.builder()
                        .securityReferences(Collections.singletonList(new SecurityReference("BASE_TOKEN",new AuthorizationScope[]{new AuthorizationScope("global","")} )))
                        .build()
        );
    }
}

测试:

给api文档写注释:

添加一个user类:

package com.candy.pojo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel("用户实体类")
public class User {
    @ApiModelProperty("用户名")
    public String username;
    @ApiModelProperty("密码")
    public String password;
}

改造controller:

@RestController
public class HelloController {
    @GetMapping (value = "/hello")
    public String hello(){
        return "hello";
    }
    @PostMapping("/user")
    public User user(){
        return new User();
    }
}

测试:


完结撒花!!!芜湖!!!

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号