最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

Java开发、SpringBoot开发(狂神说Java) 每日消息

来源:博客园
目录
  • Java SpringBoot 开发学习(狂神说Java)
    • SpringBoot概述
    • 微服务
    • SpringBoot程序
      • 安装
      • 测试
      • 配置文件
    • 原理
      • 自动配置
      • 主启动类
      • yaml语法
    • 给属性赋值的几种方式
    • JR303校验
    • 多环境配置及配置文件位置
    • SpringBoot Web开发理论
      • 静态资源
      • 首页
      • 模板引擎
      • Thymeleaf语法
      • MVC配置原理,扩展SpringMVC
        • 视图解析
        • 视图跳转
    • 员工管理系统(基于Spring Boot)
      • 准备工作
      • 首页实现
      • 页面国际化
      • 登录功能
      • 登录拦截器
      • 员工列表展示
      • 添加员工
      • 修改员工信息
      • 删除及404处理

Java SpringBoot 开发学习(狂神说Java)

SpringBoot概述

Spring

  • Spring开源框架(容器),简化开发

  • 4种策略:


    (资料图片仅供参考)

  • 1.基于POJO的轻量级和最小侵入性编程

  • 2.通过IOC,依赖注入(DI)和面向接口实现松耦合

  • 3.基于切面(AOP)和惯例进行声明式变成

  • 4.通过切面和模板减少样式代码

SpringBoot的核心思想:约定大于配置

微服务

  • 微服务是一种架构风格。MVC三层架构,MVMM,微服务架构。

  • 业务=>模块,把每个功能独立出来,吧独立出来的功能元素动态组合

SpringBoot程序

安装

jdk1.8,maven3.6.1,springboot,IDEA

  • 直接官网下载,import

  • IDEA直接创建

测试

  • Application程序主入口,application.properties核心配置文件

  • Application同级目录建立controller进行测试(访问locahost:8080/hello/hello)

  • Maven-Lifecycle-package打成jar包,java -jar xxx.jar运行服务

配置文件

  • 端口号修改 server.port=8081

  • 修改log:配置文件同目录创建banner.txt,从springboot banner等创建粘贴

原理

自动配置

步骤

  • springboot在启动的时候,从类路径下/META-INF/spring.factories获取指定的值

  • 将这些自动配置的类导入容器,自动配置就会生效,帮我进行自动配置

  • 以前需要自动配置的东西,sprintboot做了

  • 整个javaEE,解决方案和自动配置的东西都在sprint-bbot-autoconfigure-version.jar这个包下

  • 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器

  • 容器中也会存在非常多的xxxxAutoConfiguration,就是这些类给容器中导入了这个场景需要的所有组件,并自动配置

  • 有了自动配置类,免去了手动编写配置文件的工作

sprintboot所有的自动配置都在启动类种扫描并加载:sprint.factories所有的自动配置类都在这里,但是不一定生效,要判断条件是否成立。只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功了。

  • springboot dependecies: 核心依赖在父工程中

  • 写或者引入Sprintboot依赖时,不需要指定版本,因为有这些版本仓库

启动器

  •     org.springframework.boot    spring-boot-starter
  • sprintboot将所有功能场景都变成一个个的启动器

  • 官网可以寻找需要使用的starter

主程序

  • SpringBootApplication 标注类是一个springboot的应用,启动类下的所有资源被导入

  • SpringApplication.run(SpringbootHelloworldApplication.class, args);将springboot启动

  • @SprintBootConfiguration: sprintboot配置    @Configuration: sprint配置类    @component:  一个sprint组件@EnableAutoConfiguration:自动配置    @AutoConfigurationPackage: 自动配置包        @Import(AutoConfigurationPackages.Registrar.class) :自动配置 包注册    @Import(AutoConfigurationImpoSelector.class): 自动配置导入选择

主启动类

SpringApplication

  • 1.推断应用的类型时普通的项目还是web项目

  • 2.查找并加载所有可用初始化器,设置到initializers属性中

  • 3.找出所有的应用程序监听器,设置到listeners属性中

  • 4.推断并设置main方法的定义类,找到运行的主类

yaml语法

官方文档:https://docs.spring.io/spring-boot/docs/2.6.11/reference/htmlsingle/#using.build-systems.starters

  • 删除默认配置文件,新建application.yaml

  • 语法: key: 空格 value

  • server:  port: 8081//2server: {port: 8081, xxx: yyy}//3server:    - port    - xxx

给属性赋值的几种方式

  • @Value("xxx"),测试时用@Autowired自动装配,才能使用private Dog dog;

  • yaml可用直接给实体类赋值,实体类使用@ConfigurationProperties(perfix = "person")。 松散绑定last-name和lastName一样的。 原理是通过set方法实现

person:    name: A1oe    age: 3    lists:        - code        - music    dog:        name: "旺财"
  • properties,@propertySource(value = "classpath:A1oe.properties") => @Value("$name") SPEL表达式

JR303校验

  • 类上面@Validated

  • 属性上面@Email(message="xxx") 等

多环境配置及配置文件位置

springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件:(优先级从上到下)

1.当前目录  1.当前目录中的/config子目录  2.当前目录2.类路径  1.类路径/config直接子目录  2.类路径

多环境切换(yaml使用"---"进行分割)

  • 在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml , 用来指定多个环境版本;如:application-test.yml:代表测试环境配置、application-dev.yml:代表开发环境配置

  • Springboot并不会直接启动这些配置文件,它默认使用application.properties主配置文件,如果没有就会找application.yml。

  • 需要通过一个配置来选择需要激活的环境

spring:  profiles:    active: dev #使用开发环境。

SpringBoot Web开发理论

  • xxxAutoConfiguration: 向容器中自动配置文件

  • xxxProperties: 自动配置类,装配配置文件中自定义的一些内容

解决的问题:

  • 导入静态资源

  • 首页

  • jsp,模板引擎Thymeleaf

  • 装配扩展SpringMVC

  • 增删改查数据库

  • 拦截器

  • 国际化

静态资源

  • 默认情况下,Spring Boot 从类路径中的/static (或/public 或/resources 或/META-INF/resources)目录或 ServletContext的根目录提供静态内容。

  • 优先级:resources>static>public

  • 一般static放静态资源,resources放上传的文件,public放公共访问的资源

首页

首页

  • index.html放静态资源下可直接访问,但是一般使用controller跳转

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

图标

模板引擎

导入themyleaf依赖,刷新Maven

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

ThymeleafProperties.java查看目录,解析templates下的.html文件

templates目录创建test.html,使用IndexController调用。访问localhost:8080/test,显示页面

package com.example.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class IndexController {    @RequestMapping("/test")    public String test(){        return "test";    }}

Thymeleaf使用文档:https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html

Variable Expressions: ${...}Selection Variable Expressions: *{...}Message Expressions: #{...}Link URL Expressions: @{...}Fragment Expressions: ~{...}

所有的html元素都可以被thymeleaf替换接管: th:元素名。

在/test路由显示hello springboot

package com.example.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class IndexController {    @RequestMapping("/test")    public String test(Model model){        model.addAttribute("msg","hello springboot");        return "test";    }}
        Title

Thymeleaf语法

Thymeleaf使用文档:https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html

例子:遍历users,使用each

package com.example.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import java.util.Arrays;@Controllerpublic class IndexController {    @RequestMapping("/test")    public String test(Model model){        model.addAttribute("msg","hello springboot");        model.addAttribute("users", Arrays.asList("AAA","BBB"));        return "test";    }}
        Title

[[ ${user} ]]

MVC配置原理,扩展SpringMVC

Spring Boot官方文档[Web](https://springdoc.cn/spring-boot/web.html#web.servlet.spring-mvc.auto-configuration)

如果你想保留那些Spring Boot MVC定制,并进行更多的[MVC定制](https://docs.spring.io/spring-framework/docs/6.0.5/reference/html/web.html#mvc)(Interceptor、Formatter、视图控制器和其他功能),你可以添加你自己的@Configuration类,类型为WebMvcConfigurer,但**不**含@EnableWebMvc

视图解析

config-MyMvcConfig.java下

package com.example.config;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;@Configurationpublic class MyMvcConfig implements WebMvcConfigurer {        @Bean    public ViewResolver myViewResolver(){        return new MyViewResolver()    }        public static class MyViewResolver implements ViewResolver{        @Override        public View resolveViewName(String viewName, Locale locale) throws Exception {            return null;        }    }}

视图跳转

addViewControllers,将/a1oe跳转到/test

package com.example.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class MyMvcConfig implements WebMvcConfigurer {    @Override    public void addViewControllers(ViewControllerRegistry registry) {        registry.addViewController("/a1oe").setViewName("test");    }}

结论:springboot中,有很多xxxx Configuration 帮助我们进行扩展配置,看见了需要注意。

员工管理系统(基于Spring Boot)

准备工作

BootStrap模板下载:[bootstrap模板 bootstrap模板免费下载](https://sc.chinaz.com/tag_moban/bootstrap.html)

页面放templates,资源放static(静态资源找不到的话可以私信找我要)。

建立部门信息表和员工信息表,需要引入依赖lombok

  • Department.java

  • Employee.java

package com.example.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;//部门表@Data@AllArgsConstructor // 有参@NoArgsConstructor // 无参public class Department {    private Integer id;    private String departmentName;}
package com.example.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.util.Date;//员工表@Data@AllArgsConstructor@NoArgsConstructorpublic class Employee {    private Integer id;    private String lastName;    private String email;    private Integer gender; // 0女 1男;    private Department department;    private Date birth;    public Employee(Integer id, String lastName, String email, Integer gender, Department department) {        this.id = id;        this.lastName = lastName;        this.email = email;        this.gender = gender;        this.department = department;        //默认的创建日期        this.birth = new Date();    }}

Da层模拟数据库

  • DepartmentDao

  • EmployeeDao

package com.example.dao;import com.example.pojo.Department;import org.springframework.stereotype.Repository;import java.util.Collection;import java.util.HashMap;import java.util.Map;//部门Dao@Repositorypublic 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 getDepartmentById(Integer id){        return departments.get(id);    }}
package com.example.dao;import com.example.pojo.Department;import com.example.pojo.Employee;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;import java.util.Collection;import java.util.HashMap;import java.util.Map;//员工Dao@Repositorypublic class EmployeeDao {    //模拟数据库数据    private static Map employees = null;    //员工有所属的部门    @Autowired    private DepartmentDao departmentDao;    static {        employees = new HashMap();  //创建一个部门表        employees.put(1001,new Employee(1001,"AA","A123456@qq.com",1,new Department(101,"教学部")));        employees.put(1002,new Employee(1002,"BB","B123456@qq.com",0,new Department(102,"市场部")));        employees.put(1003,new Employee(1003,"CC","C123456@qq.com",1,new Department(103,"教研部")));        employees.put(1004,new Employee(1004,"DD","D123456@qq.com",0,new Department(104,"运营部")));        employees.put(1005,new Employee(1005,"EE","E123456@qq.com",1,new Department(105,"后勤部")));    }   //主键自增    private static Integer InitId = 1006;    //增加一个员工    public void save(Employee employee){        if (employee.getId()==null){            employee.setId(InitId++);        }        employee.setDepartment(departmentDao.getDepartmentById(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 delete(Integer id){        employees.remove(id);    }}

首页实现

两种方式

  • IndexController,但不建议
@Controllerpublic class IndexController{    @RequestMapping({"/","/index.html"})    public String index() {        return "index";    }}
  • config目录下的MyMvcConfig,重写addViewControllers接管
package com.example.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class MyMvcConfig implements WebMvcConfigurer {    @Override    public void addViewControllers(ViewControllerRegistry registry) {        registry.addViewController("/").setViewName("index");        registry.addViewController("/index.html").setViewName("index");    }}

静态资源加载,修改html文件,使用thymeleaf接管,举例如下:

index.html中404.html,dashboard.html中<script type="text/javascript" th:src="@{/js/jquery-3.2.1.slim.min.js}"></script><script type="text/javascript" th:src="@{/js/popper.min.js}"></script><script type="text/javascript" th:src="@{/js/bootstrap.min.js}"></script>

页面国际化

  • 确认IDEA设置中FIle Encoding的所有编码为UTF-8
  • resourcces下创建文件夹i18n目录(internationalization缩写),存放国际化配置文件

  • 创建配置文件login.properties和中文的login_zh_CN.properties(文件合并,自动创建一个下级目录)

  • 再使用新的方法在新的目录这上面去新建一个文件,再添加一个英文的

  • 可视化配置,点击Text旁边的Resource Bundle
  • 配置message路径,spring.messages.basename=i18n.login

  • Thymeleaf中使用#号转换国际化消息

  • 国际化解析器,LocaleResolver。写一个自己的LocaleResolver。思路就是点击中文或English时进行跳转,然后使用组件类进行处理。
中文English
package com.example.config;import org.springframework.web.servlet.LocaleResolver;import org.thymeleaf.util.StringUtils;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.Locale;public class MyLocaleResolver implements LocaleResolver {    //解析请求    @Override    public Locale resolveLocale(HttpServletRequest request) {        //获取l参数        String language = request.getParameter("l");        Locale locale = Locale.getDefault();  //如果没有就使用默认的        //如果不为空        if (!StringUtils.isEmpty(language)){            //zh_CN            String[] split = language.split("_");            //语言,地区            locale = new Locale(split[0], split[1]);        }        return locale;    }    @Override    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {    }}

为了让我们的类能够生效,需要再配置一下这个组件,在我们自己的MvcConofig下添加Bean

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

登录功能

  • 首先需要修改登录页面的表单,修改请求地址、提交的参数和返回信息的输出
  • 解决密码泄露问题:加一个main.html映射在MyMvcConfig中,然后再控制器中跳转到main.html
@Override    public void addViewControllers(ViewControllerRegistry registry) {        registry.addViewController("/").setViewName("index");        registry.addViewController("/index.html").setViewName("index");        registry.addViewController("/main.html").setViewName("dashboard");    }
if (!StringUtils.isEmpty(username) && "123456".equals(password)){            return "redirect:/main.html";        }

登录拦截器

  • 只有登录成功才能进main.html

  • 需要先给登录拥护session,再LoginController中添加

package com.example.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.thymeleaf.util.StringUtils;import javax.servlet.http.HttpSession;@Controllerpublic class LoginContoller {    @RequestMapping("/user/login")    public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model    ,HttpSession session){        //具体业务        if (!StringUtils.isEmpty(username) && "123456".equals(password)){            session.setAttribute("loginUser",username);            return "redirect:/main.html";        } else {            model.addAttribute("msg","用户名或密码错误");            return "index";        }    }}
  • 然后在config中创建LoginHanlderInterceptor拦截器,实现HandlerInterceptor接口
package com.example.config;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class LoginHandleInterceptor 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;        }    }}
  • 在MyMvcConfig中重写拦截器方法,添加我们的拦截器(需要排除某些页面和静态资源)
package com.example.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.LocaleResolver;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class MyMvcConfig implements WebMvcConfigurer {    @Override    public void addViewControllers(ViewControllerRegistry registry) {        registry.addViewController("/").setViewName("index");        registry.addViewController("/index.html").setViewName("index");        registry.addViewController("/main.html").setViewName("dashboard");    }    //自定义国际化生效    @Bean    public LocaleResolver localeResolver() {        return new MyLocaleResolver();    }    //添加拦截器    @Override    public void addInterceptors(InterceptorRegistry registry) {        // 添加拦截路径,排除index.html路径        registry.addInterceptor(new LoginHandleInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/",        "/user/login","/css/*","/js/**","/img/**");    }}

员工列表展示

  • list.html和dashboard.html中修改地址
        

添加员工

@GetMapping("/emp")    public String toAddpage(Model model){        //查出所有部门信息        Collection departments = departmentDao.getDepartments();        model.addAttribute("departments", departments);        return "emp/add";    }

@Autowired    DepartmentDao departmentDao;@PostMapping("/emp")    public String addEmp(Employee employee) {        //添加的操作        employeeDao.save(employee);        return "redirect:/emps";    }

修改员工信息

编辑
  • 后台接收参数,并返回查询出的信息到update.html
//去员工修改页面    @GetMapping("/emp/{id}")    public String toUpdateEmp(@PathVariable("id") Integer id, Model model){        //查出原来的数据        Employee employee = employeeDao.getEmploeeById(id);        model.addAttribute("emp", employee);        //查出所有部门的信息        Collection department = departmentDao.getDepartments();        model.addAttribute("departments",department);        return "emp/update";    }
  • 编写update.html

  • 添加更新路由功能
@PostMapping("/updateEmp")    public String updateEmp(Employee employee) {        employeeDao.save(employee);        return "redirect:/emps";    }

删除及404处理

关键词: