SpringBoot 企业级简化开发(二)

简介: SpringBoot 企业级简化开发

SpringBoot 企业级简化开发(一)https://developer.aliyun.com/article/1469559

SpringBoot web开发

jar:webapp在哪里

最大特点:自动装配

SpringBoot帮我们配置了什么,能不能进行修改,能修改那些东西,能不能拓展

  • xxxxAutoConfiguration..向容器中自动配置组件
  • XXXXProperties:实现自动配置类装配配置文件中自定义的内容!

要解决的问题:

  • 导入静态资源,如何导入!
  • 首页问题
  • 模版引擎,thymeleaf
  • 装配扩展SpringMvc
  • 剩下的就只有增删改了
  • 拦截器
  • 扩展国际化

静态资源

@Override 
public void addResourceHandlers(ResourceHandlerRegistry registry) {
      if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
        return;
      }
      addResourceHandler(registry, "/webjars/", "classpath:/META-INF/resources/webjars/");
      addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
        registration.addResourceLocations(this.resourceProperties.getStaticLocations());
        if (this.servletContext != null) {
          ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
          registration.addResourceLocations(resource);
        }
      });
    }

什么是webjars

一个网站是和maven仓库类似的导入依赖的网站

导入的依赖结构是

我们的静态资源路径方法中

addResourceHandler(registry, "/webjars/", "classpath:/META-INF/resources/webjars/");

就是去类路径下找到/META-INF/resources/webjars/下的文件,

例子:

访问http://localhost:8080/webjars/jquery/3.6.0/jquery.js

实测成功

总结:

  1. SpringBoot处理静态资源的方式
  1. 优先级:resources>static(默认)》public

首页如何定制

在web配置类中共有对首页的一系列处理

如何找得到资源下的index?

调用查找资源方法,找到index并且返回,没找到的话相对处理后返回空

SpringBoot页面跳转:

@Controller
public class HelloController {
@RequestMapping("/a")
    public String hello(){
        return "index";
    }
}

注意:

  • 在template目录下的所有页面,只能通过controller来跳转
  • 需要模版引擎的支持

模版引擎:Thymeleaf

我们以前用jsp来展示数据,模版引擎的作用就是我们来写一个页面模版,比如一些值,表达式,tomcat支持jsp但是由于我们用的是嵌入式的tomcat,所以他现在默认是不支持jsp的

thymeleaf:

Thymeleaf 是适用于 Web 和独立环境的现代服务器端 Java 模板引擎,能够处理 HTML、XML、JavaScript、CSS 甚至纯文本。

Thymeleaf 的主要目标是提供一种优雅且高度可维护的模板创建方式。为了实现这一点,它建立在自然模板的概念之上,以不影响模板用作设计原型的方式将其逻辑注入模板文件。这改善了设计的沟通并弥合了设计和开发团队之间的差距。

Thymeleaf也已经从一开始就设计了Web标准记-尤其是HTML5 -允许您创建充分验证模板,如果这是一个需要你。

thymeleaf与mvc时讲到的视图解析器十分相似,

Springboot推荐使用模版引擎来简化开发,

引入依赖:

<dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

使用只需要导入依赖,我们将html放到templeats下就可以跳转了

注意:如果导入jar失败尝试回退版本,即可

thymeleaf基础语法:

<!--所有的html元素都可以被thymeleaf接管,如何接管? th:元素-->
<div th:text="${msg}"></div>

表达式:

  • ${x}将返回x存储在 Thymeleaf 上下文中或作为请求属性的变量。
  • ${param.x}将返回一个名为(可能是多值的)的请求参数x
  • ${session.x}将返回一个会话属性x
  • ${application.x}将返回一个名为的servlet 上下文属性x

常用语法:

  • 简单的表达:
  • 变量表达式: ${...}
  • 选择变量表达式: *{...}
  • 消息表达: #{...}
  • 链接 URL 表达式: @{...}
  • 片段表达式: ~{...}
  • 文字
  • 文本字面量:'one text', 'Another one!',...
  • 数字字面量:0, 34, 3.0, 12.3,...
  • 布尔文字:true,false
  • 空字面量: null
  • 文字标记:one, sometext, main,...
  • 文字操作:
  • 字符串连接: +
  • 字面替换: |The name is ${name}|
  • 算术运算:
  • 二元运算符:+, -, *, /,%
  • 减号(一元运算符): -
  • 布尔运算:
  • 二元运算符:and,or
  • 布尔否定(一元运算符):!,not
  • 比较与相等:
  • 比较器:>, <, >=, <=( gt, lt, ge, le)
  • 等式运算符:==, !=( eq, ne)
  • 条件运算符:
  • 如果-那么: (if) ? (then)
  • 如果-然后-其他: (if) ? (then) : (else)
  • 默认: (value) ?: (defaultvalue)

常用代码示例:

controller:index

@Controller
public class HelloController {
@RequestMapping("/index")
    public String hello(Model model){
    model.addAttribute("msg","<h1>hello SpringBoot</h1>");
       model.addAttribute("users", Arrays.asList("hyc","lhy"));
        return "index";
    }
}

index.html

<!--所有的html元素都可以被thymeleaf接管,如何接管? th:元素-->
<!--不转义-->
<div th:text="${msg}"></div>
<!--转义-->
<div th:utext="${msg}"></div>
<hr>
<!--th:text显式数据-->
<h3 th:each="user:${users}" th:text="${user}"></h3>
<!--行内显式数据-->
<h3 th:each="user:${users}" >[[${user}]]</h3>
</body>

SpringBoot装配并且扩展SpringMvc

以视图解析器为例子:

原理:孙建平,真是我的好兄弟应该说是不是你的好办法真是我的好儿子我真的。

ContentNegotiatingViewResolver类中有方法,getCandidateViews()获取候选的视图,选择最好的视图返回,

官方文档是这样说的:

Spring Boot 为 Spring MVC 提供了自动配置,适用于大多数应用程序。

自动配置在 Spring 的默认值之上添加了以下功能:

  • 包括ContentNegotiatingViewResolverBeanNameViewResolverbean。
  • 支持提供静态资源,包括对 WebJars 的支持。
  • 自动注册ConverterGenericConverterFormatterbean类。
  • 支持HttpMessageConverters
  • 的自动注册MessageCodesResolver
  • 静态index.html支持。
  • ConfigurableWebBindingInitializerbean 的自动使用。

如果您想保留那些 Spring Boot MVC 自定义并进行更多(拦截器、格式化程序、视图控制器和其他功能),您可以添加自己@Configuration的类型类,WebMvcConfigurer但不添加 @EnableWebMvc.

如果你想提供的定制情况RequestMappingHandlerMappingRequestMappingHandlerAdapter或者ExceptionHandlerExceptionResolver,仍然保持弹簧引导MVC自定义,你可以声明类型的豆WebMvcRegistrations,并用它来提供这些组件的定制实例。

如果你想利用Spring MVC中的完全控制,你可以添加自己的@Configuration注解为@EnableWebMvc,或者添加自己的@Configuration-annotatedDelegatingWebMvcConfiguration中的Javadoc中所述@EnableWebMvc

如果我们想自定义视图解析器参考如下代码:

package com.hyc.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;
//如果你想diy或者自定义动能,只需要写这个组件然后将它交给SpringBoot,SpringBoot就会帮我们自动装配
//拓展mvc
@Configuration
public class MyMvc implements WebMvcConfigurer {
//public interface ViewResolver 实现了视图解析器的类我们就可以把他看成试图解析器
@Bean
public MyViewResolver myViewResolver(){
    return new MyViewResolver();
}
//自定义了一个自己的视图解析器,只要我们自定义了试图解析器,SpringBoot就会帮我们自动装配
public static class MyViewResolver implements ViewResolver {
    @Override
    public View resolveViewName(String s, Locale locale) throws Exception {
        return null;
    }
}
}

装配原理小结:

  1. 芸芸之多的配置,原理其实是一样的,通过获取webmvc的自动配置原理分析,我们要学会一种方式,去在源码中得出结论,都是属于自己,一通百通
  2. Spring整个框架的底层有太多精妙的设计细节,阅读源码可以让我们对编写代码和理解原理的能力大大提升!
  3. 在自动配置很多组件的时候,SpringBoot会先查看容器中有没有用户自己配置的@bean,如果有就用用户配置的,如果没有就用默认配置,组件存在多个的时候,如视图解析器,就将用户配置的和自己默认的组合起来

员工管理系统

1、首页配置

1.首页配置,自己设置页面跳转

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

2.首页设置,thymeleaf

xmlns:th="http://www.thymeleaf.org"

常用的thymeleaf文件头

注意点:所有的页面静态资源使用thymeleaf接管:url:@{}

页面国际化

  1. 我们需要配置i18n文件
  2. 我们如果需要在项目中进行按钮自动切换,我们需要自定义国际化组件
package com.hyc.managesystem.config;
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");
        System.out.println(language);
        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) {
    }
}


  1. 记得将自己写的组件配置到配置文件中
@Bean
    public LocaleResolver localeResolver(){
        return  new myLocalresolver();
    }


  1. 使用#{}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0oH1S1RT-1648917634756)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20210503093036786.png)]

位置如下

1.2、编写pojo层

员工表

//员工表
@Data
@NoArgsConstructor
public 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();
    }
}

部门表

//部门表
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department {
    private int id;  //部门id
    private String departmentName;  //部门名字
}

添加lombok依赖

<!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

1.3、编写dao层

这里我们模拟数据库,springboot和数据库的连接在后序课程中。

部门dao

package com.kuang.dao;
import com.kuang.pojo.Department;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
//部门dao
@Repository
public class DepartmentDao {
    //模拟数据库中的数据
    private static Map<Integer, Department>departments = null;
    static {
        departments = new HashMap<Integer, Department>(); //创建一个部门表
        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<Department> getDepartments(){
        return departments.values();
    }
    //通过id得到部门
    public Department getDepartmentById(Integer id){
        return departments.get(id);
    }
}

员工dao

package com.kuang.dao;
import com.kuang.pojo.Department;
import com.kuang.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
@Repository //被string托管
public class EmployeeDao {
    //模拟数据库中的数据
    private static Map<Integer, Employee> employees= null;
    //员工所属的部门
    @Autowired
    private DepartmentDao departmentDao;
    static {
        employees = new HashMap<Integer,Employee>(); //创建一个部门表
        employees.put(1001,new Employee(  1001,"AA","1622840727@qq.com",1,new Department(101,"教学部")));
        employees.put(1002,new Employee(  1002,"BB","2622840727@qq.com",0,new Department(102,"市场部")));
        employees.put(1003,new Employee(  1003,"CC","4622840727@qq.com",1,new Department(103,"教研部")));
        employees.put(1004,new Employee(  1004,"DD","5628440727@qq.com",0,new Department(104,"运营部")));
        employees.put(1005,new Employee(  1005,"FF","6022840727@qq.com",1,new Department(105,"后勤部")));
    }
    //主键自增
    private static Integer ininId = 1006;
    //增加一个员工
    public void save(Employee employee){
        if(employee.getId() == null){
            employee.setId(ininId++);
        }
        employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
        employees.put(employee.getId(),employee);
    }
    //查询全部的员工
    public Collection<Employee>getALL(){
         return employees.values();
    }
    //通过id查询员工
    public Employee getEmployeeById(Integer id){
        return employees.get(id);
    }
    //删除一个员通过id
    public void delete(Integer id){
        employees.remove(id);
    }
}

2、首页实现

2.1、引入Thymeleaf

pom.xml导入依赖

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>

2.2、编写MyMvcConfig

package com.kuang.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//扩展使用SpringMVC
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
    }
}

更改静态资源路径

所有的静态资源都需要使用thymeleaf接管:@{}

application.properties 修改

# 关闭模板引擎的缓存
spring.thymeleaf.cache=false
server.servlet.context-path=/kuang

2.3、测试首页

输入路径

http://localhost:8080/kuang/index.html

测试成功!

3、页面国际化

3.1、 File Encodings设置

先在IDEA中统一设置properties的编码问题!

编写国际化配置文件,抽取页面需要显示的国际化页面消息。我们可以去登录页面查看一下,哪些内容

我们需要编写国际化的配置!

3.2、配置文件编写

1、我们在resources资源文件下新建一个i18n目录,存放国际化配置文件

2、建立一个login.properties文件,还有一个login_zh_CN.properties;发现IDEA自动识别了我们要做国际化操作;文件夹变了!

3、我们可以在这上面去新建一个文件;

弹出如下页面:我们再添加一个英文的;

这样就快捷多了!

4、接下来,我们就来编写配置,我们可以看到idea下面有另外一个视图;

这个视图我们点击 + 号就可以直接添加属性了;我们新建一个login.tip,可以看到边上有三个文件框可以输入

我们添加一下首页的内容!

然后依次添加其他页面内容即可!

然后去查看我们的配置文件;

login.properties :默认

login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

英文:

login.btn=Sign in
login.password=Password
login.remember=Remember me
login.tip=Please sign in
login.username=Username

中文:

login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

OK,配置文件步骤搞定!

配置文件生效探究

我们去看一下SpringBoot对国际化的自动配置!这里又涉及到一个类:MessageSourceAutoConfiguration

里面有一个方法,这里发现SpringBoot已经自动配置好了管理我们国际化资源文件的组件 ResourceBundleMessageSource;

// 获取 properties 传递过来的值进行判断
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    if (StringUtils.hasText(properties.getBasename())) {
        // 设置国际化文件的基础名(去掉语言国家代码的)
        messageSource.setBasenames(
            StringUtils.commaDelimitedListToStringArray(
                                       StringUtils.trimAllWhitespace(properties.getBasename())));
    }
    if (properties.getEncoding() != null) {
        messageSource.setDefaultEncoding(properties.getEncoding().name());
    }
    messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
    Duration cacheDuration = properties.getCacheDuration();
    if (cacheDuration != null) {
        messageSource.setCacheMillis(cacheDuration.toMillis());
    }
    messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
    messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
    return messageSource;
}

我们真实的情况是放在了i18n目录下,所以我们要去配置这个messages的路径;

spring.messages.basename=i18n.login

配置页面国际化值

去页面获取国际化的值,查看Thymeleaf的文档,找到message取值操作为:#{...}。我们去页面测试下:

IDEA还有提示,非常智能的!

我们可以去启动项目,访问一下,发现已经自动识别为中文的了!

但是我们想要更好!可以根据按钮自动切换中文英文!

配置国际化解析

在Spring中有一个国际化的Locale (区域信息对象);里面有一个叫做LocaleResolver (获取区域信息对象)的解析器!

我们去我们webmvc自动配置文件,寻找一下!看到SpringBoot默认配置:

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver() {
   // 容器中没有就自己配,有的话就用用户配置的
   if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
       return new FixedLocaleResolver(this.mvcProperties.getLocale());
   }
   // 接收头国际化分解
   AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
   localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
   return localeResolver;
}

AcceptHeaderLocaleResolver 这个类中有一个方法

public Locale resolveLocale(HttpServletRequest request) {
    Locale defaultLocale = this.getDefaultLocale();
    // 默认的就是根据请求头带来的区域信息获取Locale进行国际化
    if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
        return defaultLocale;
    } else {
        Locale requestLocale = request.getLocale();
        List<Locale> supportedLocales = this.getSupportedLocales();
        if (!supportedLocales.isEmpty() && !supportedLocales.contains(requestLocale)) {
            Locale supportedLocale = this.findSupportedLocale(request, supportedLocales);
            if (supportedLocale != null) {
                return supportedLocale;
            } else {
                return defaultLocale != null ? defaultLocale : requestLocale;
            }
        } else {
            return requestLocale;
        }
    }
}

那假如我们现在想点击链接让我们的国际化资源生效,就需要让我们自己的Locale生效!

我们去自己写一个自己的LocaleResolver,可以在链接上携带区域信息!

修改一下前端页面的跳转连接:

<!-- 这里传入参数不需要使用 ?使用 (key=value)-->
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>

我们去写一个处理的组件类!

package com.kuang.component;
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 MyLocaleResolver 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 httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
    }
}

为了让我们的区域化信息能够生效,我们需要再配置一下这个组件!在我们自己的MvcConofig下添加bean;

@Bean
public LocaleResolver localeResolver(){
    return new MyLocaleResolver();
}

我们重启项目,来访问一下,发现点击按钮可以实现成功切换!搞定收工!

注意点

image.png


SpringBoot 企业级简化开发(三)https://developer.aliyun.com/article/1469562


目录
相关文章
|
13天前
|
安全 Java 开发者
详解SpringBoot的核心特性
SpringBoot是一个用于简化Spring应用程序开发的框架,它提供了一系列核心特性,使得开发者能够更快速、更简单地构建和部署Spring应用程序。本文将详细介绍SpringBoot的五个核心特性,并为每个特性提供三个子特性的详细解释。
20 1
|
2月前
|
安全 前端开发 Java
SpringBoot 企业级简化开发(五)
SpringBoot 企业级简化开发
35 0
|
2月前
|
前端开发 Java 微服务
SpringBoot 企业级简化开发(一)
SpringBoot 企业级简化开发
108 1
|
2月前
|
前端开发 Java 数据库
SpringBoot 企业级简化开发(三)
SpringBoot 企业级简化开发
35 0
|
2月前
|
安全 Java 数据库连接
SpringBoot 企业级简化开发(四)
SpringBoot 企业级简化开发
29 0
SpringBoot 企业级简化开发(四)
|
2月前
|
Java 应用服务中间件 Maven
简化springboot部署,太灵活方便了!
简化springboot部署,太灵活方便了!
10 0
|
2月前
|
存储 安全 Java
235基于SpringBoot的房屋交易平台的设计与实现
235基于SpringBoot的房屋交易平台的设计与实现
235基于SpringBoot的房屋交易平台的设计与实现
|
9月前
|
Java 测试技术 Spring
从零玩转SpringBoot3-基础特性2
从零玩转SpringBoot3-基础特性
136 0
|
SQL Java 数据库
如何利用SpringBoot 搭建微服务?
这篇就利用SpringBoot 搭建微服务,带大家从代码的角度来加深对微服务的概念,理解了概念才会知道微服务怎么架构的,组件与组件之间是如何互通通信的
466 1
如何利用SpringBoot 搭建微服务?
|
Java Maven Spring
SpringBoot多环境适配之道
本文是应用配置中心的第三篇,第一篇介绍了配置演化之路,第二篇介绍了在传统项目中以Maven作为多环境支持的方式。这篇将以SpringBoot为例,重点阐述在SpringBoot中如何适配多环境。
136 0
SpringBoot多环境适配之道