SpringBoot之Web开发

2022-03-12 14:10:49 浏览数 (1)

一、Web 开发

自动配置原理:

xxxAutoConfiguration: 帮助我们给容器中自动配置组件; xxxProperyties: 配置类来

1、 SpringBoot 对静态资源的映射规则

代码语言:javascript复制
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {
// 可是设置和静态资源有关的参数,缓存时间等
WebMvcAuotConfiguration:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
	if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
        return;
	}
    Integer cachePeriod = this.resourceProperties.getCachePeriod();
    if (!registry.hasMappingForPattern("/webjars/**")) {
    	customizeResourceHandlerRegistration(
			registry.addResourceHandler("/webjars/**")
                .addResourceLocations(
					"classpath:/META‐INF/resources/webjars/")
                .setCachePeriod(cachePeriod));
	}
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    // 静态资源文件夹的映射
    if (!registry.hasMappingForPattern(staticPathPattern)) {
		customizeResourceHandlerRegistration(
        	registry.addResourceHandler(staticPathPattern)
				.addResourceLocations(
					this.resourceProperties.getStaticLocations())
			.setCachePeriod(cachePeriod));
	}
}
    // 配置欢迎页映射
    @Bean
	public WelcomePageHandlerMapping welcomePageHandlerMapping(
		ResourceProperties resourceProperties) {
       return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(),
		this.mvcProperties.getStaticPathPattern());
	}
    // 配置喜欢的图标
    @Configuration
	@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
    public static class FaviconConfiguration {
	private final ResourceProperties resourceProperties;
	public FaviconConfiguration(ResourceProperties resourceProperties) {
        this.resourceProperties = resourceProperties;
	}
    @Bean
	public SimpleUrlHandlerMapping faviconHandlerMapping() {
		SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        mapping.setOrder(Ordered.HIGHEST_PRECEDENCE   1);
    	//所有 **/favicon.ico
		mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
		faviconRequestHandler()));
		return mapping;
	}
    @Bean
	public ResourceHttpRequestHandler faviconRequestHandler() {
		ResourceHttpRequestHandler requestHandler = new
		ResourceHttpRequestHandler();
		requestHandler
			.setLocations(this.resourceProperties.getFaviconLocations());
		return requestHandler;
	}
}
  1. ==所有的/webjars/**,都去 classpath:/META-INF/resources/web/找资源== webjars :以 jar 包的方式引入静态资源;http://www.webjars.org/

导入依赖:

代码语言:javascript复制
<!--引入jquery-webjar 访问的时候只需要写webjars下面的资源名称即可-->
<dependency>
	<groupId>org.webjars.bower</groupId>
    <artifactId>jquery</artifactId>
    <version>3.3.1</version>
</dependency>

测试:localhost:8080/webjars/jquery/3.3.1/dist/jquery.js

  1. ==”/**访问当前项目的任何资源,都去(静态资源的文件夹)找映射。==
  • “classpath:/META-INF/resources/“
  • “classpath:/resources/“
  • “classpath:/static/“
  • “classpath:/public/“
  • “/“:当前项目

例如: localhost:8080/abc == 去静态资源文件夹里面找 abc

  1. ==欢迎页: 静态资源文件下的所有 index.html 页面;被”/**“映射==
  1. ==所有的 **/favicaon.ico 都是在静态资源文件下找==

2、引擎模板

jsp、velocity、Freemarker、Thymeleaf

SpringBoot 推荐的 Tymeleaf,语法更简单,功能更强大;

① 引入 thymeleaf
代码语言:javascript复制
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
   <version>2.3.1.RELEASE</version>
</dependency>

测试

代码语言:javascript复制
@RequestMapping(value = "/success")
    public String success(){
        return "success";
}

切换 thymeleaf 版本

代码语言:javascript复制
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<!-- 布局功能的支持程序  thymeleaf3主程序  layout2以上版本 -->
<thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>

==启动报错==:

代码语言:javascript复制
***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration$ThymeleafDefaultConfiguration.templateEngine(ThymeleafAutoConfiguration.java:142)

The following method did not exist:

==解决方案==:

代码语言:javascript复制
<properties>
    <springboot-thymeleaf.version>3.0.9.RELEASE</springboot-thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
</properties>

原因分析

​ 这里用的 org.springframework.boot 下的 spring-boot-starter-thymeleaf,使用<thymeleaf.version>做标签时的可能与 org.thymeleaf 头冲突,导致包获取不正确。

② Thymeleaf 使用
代码语言:javascript复制
@ConfigurationProperties(
    prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
    private static final Charset DEFAULT_ENCODING;
    public static final String DEFAULT_PREFIX = "classpath:/templates/";
    public static final String DEFAULT_SUFFIX = ".html";
    private boolean checkTemplate = true;
    private boolean checkTemplateLocation = true;
    private String prefix = "classpath:/templates/";
    private String suffix = ".html";
    private String mode = "HTML";
    //

​ 只要我们把 HTML 页面的放在 classpath:/templates/, thymeleaf 就能自动渲染。

使用

  1. 导入 thymeleaf 的名称空间
代码语言:javascript复制
<html lang="en" xmlns:th="http://www.thymeleaf.org"></html>
  1. 使用 thymeleaf 语法
代码语言:javascript复制
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <h1>success 测试成功</h1>
    <div th:text="${hello}"></div>
  </body>
</html>
③ 语法规则
  1. th:text: 改变当前元素里面的内容。 th: 任意 html 属性;来替换原生的值。
  1. 表达式
代码语言:javascript复制
Simple expression: (表达式语法)
	Variable Expressions:${...}: 获取变量值; OGNL;
				1)、获取对象的属性、调用方法
                2)、使用内置的基本对象:
                    # ctx: the context object.
                    #vars: the context variables.
					#locale : the context locale.
					#request : (only in Web Contexts) the HttpServletRequest object.
					#response : (only in Web Contexts) the HttpServletResponse object.
					#session : (only in Web Contexts) the HttpSession object.
					#servletContext : (only in Web Contexts) the ServletContext object.
                 ${session.foo}
				3)、内置的一些工具对象
     #execInfo : information about the template being processed.
	#messages : methods for obtaining externalized messages inside variables expressions, in the
	same way as they would be obtained using #{…} syntax.
    #uris : methods for escaping parts of URLs/URIs
	#conversions : methods for executing the configured conversion service (if any).
	#dates : methods for java.util.Date objects: formatting, component extraction, etc.
	#calendars : analogous to #dates , but for java.util.Calendar objects.
	#numbers : methods for formatting numeric objects.
	#strings : methods for String objects: contains, startsWith, prepending/appending, etc.
	#objects : methods for objects in general.
	#bools : methods for boolean evaluation.
	#arrays : methods for arrays.
	#lists : methods for lists.
    #sets : methods for sets.
	#maps : methods for maps.
	#aggregates : methods for creating aggregates on arrays or collections.
	#ids : methods for dealing with id attributes that might be repeated (for example, as a
	result of an iteration).

    Selection Variable Expressions: *{.....}: 选择表达式:和${}在功能上是一样;
		补充: 配合 th:object="${session.user}"
    <div th:object="${session.user}">
    <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
	<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
	<p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
	</div>

    Message Expressions: #{...}: 获取国际化内容
    Link URL Expressions: @{....}: 定义URL;
		@{/order/process(execId=${execId},execType='FAST')}
		Fragment Expressions: ~{...}:片段引用表达式
		<div th:insert="~{commons :: main}">...</div>
Literals(字面量)
    Text literals: 'one text' , 'Another one!
	Number literals: 0 , 34 , 3.0 , 12.3 ,…
	Boolean literals: true , false
	Null literal: null
	Literal tokens: one , sometext , main ,…
Text operations:(文本操作)
	String concatenation:  
	Literal substitutions: |The name is ${name}|
	Arithmetic operations:(数学运算)

	Binary operators:   , ‐ , * , / , %
	Minus sign (unary operator): ‐
Boolean operations:(布尔运算)
    Binary operators: and , or
	Boolean negation (unary operator): ! , not
Comparisons and equality:(比较运算)
	Comparators: > , < , >= , <= ( gt , lt , ge , le )
	Equality operators: == , != ( eq , ne )
Conditional operators:条件运算(三元运算符)
	If‐then: (if) ? (then)
	If‐then‐else: (if) ? (then) : (else)
	Default: (value) ?: (defaultvalue)
Special tokens:
	No‐Operation: _

3、SpringMVC 自动配置

​ 可以参考文档:https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features-developingweb-applications

① Spring MVC auto-configuration

Spring Boot 自动配置好了 SpringMVC

以下是 SpringBoot 对 SpringMVC 的默认配置:==(WebMvcAutoConfiguration)==

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
    • 自动配置 ViewResource(视图解析器:根据方法的返回值得视图对象的(View), 视图对象决定如何渲染(转发?重定向?))
    • ContextNegotiatingViewResolver: 组合所有的视图解析器的;
    • ==如何定制:我们可以给自己容器中添加一个视图解析器;自动的将其组合进来;==
  • Support for serving static resources, including support for WebJars (see below). 静态资源文件夹路径,webjars
  • Static index.html support。静态首页的访问
  • Custom Favicon support (see below). favicon.ico
  • 自动注册 of Converter , GenericConverter, Formatter bean
    • Converter: 转换器;public String hello(User user): 类型转换使用 Converter
    • Formatter 格式化器: 2020.8.29 == Date;
代码语言:javascript复制
@Bean
@ConditionalOnProperty(prefix = "spring.mvc", name = "date‐format")//在文件中配置日期格
式化的规则
public Formatter<Date> dateFormatter() {
	return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件
}

==自己添加的格式化器转换器,我们只需要放在容器中即可==

  • Support for HttpMessageConverters (see below)
    • HttpMessageConverter: SpringMVC 用来转换 Http 请求和响应的 :User—json;
    • HttpMessageConverters 是从容器中确定;获取所有的 HttpMessageConverter; 给自己的容器中添加 HttpMessageConverter,只需要将自己的组件注册容器中(@Bean, @Component)
  • Automatic registration of MessageCodesResolver (see below). 定义错误的代码生成规则
  • Automatic use of a ConfigurableWebBindingInitializer bean (see below). ==我们可以配置一个 ConfigurableWebBindingInitialzer 来替换默认的:(添加到容器)==
代码语言:javascript复制
初始化WebDataBinder;
请求数据=====JavaBean;

org.springframework.boot.autoconfigure.web 的所有的自动场景;

If you want to keep Spring Boot MVC features, and you just want to add additional ==MVC configuration==(interceptors, formatters, view controllers etc.) you can add your own @Configuration class of type WebMvcConfigurerAdapter , but without @EnableWebMvc . If you wish to provide custom instances of RequestMappingHandlerMapping , RequestMappingHandlerAdapter or ExceptionHandlerExceptionResolver you can declare a WebMvcRegistrationsAdapter instance providing such components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc .

② 扩展 SpringMVC
代码语言:javascript复制
<mvc:view-controller path="/hello" view-name="success"/>
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/hello"/>
        <bean></bean>
    </mvc:interceptor>
</mvc:interceptors>

==编写一个配置类(@Configuration),是 WebMvcConfigAdapter 类型;不能标注@EnableWebMVC==

既保留所有的自动配置,也能用我们扩展的配置;

注:WebMvcConfigurerAdapter该方法在 spring boot 2.0,Spring 5.0 之后,已经被废弃

代码语言:javascript复制
// 使用WebMvcConfigurer可以来扩展SpringMVC的功能
@Configuration
public class MyMvcConfig implements WebMvcConfigurer{
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // super.addViewControllers(registry);
        // 浏览器发送 /oy 请求到 success
        registry.addViewController("/oy").setViewName("success");
    }
}

测试:

原理:

代码语言:javascript复制
1. WebMvcAutoConfiguration是SpringMVC的自动配置类
  1. 在做其他的自动配置时会导入:@Import(EnableWebMvcConfiguration.class)
代码语言:javascript复制
@Configuration
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
	private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
	// 从容器中获取所有的WebmvcConfigurer
	@Autowired(required = false)
	public void setConfigurers(List<WebMvcConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
		this.configurers.addWebMvcConfigurers(configurers);
		//一个参考实现;将所有的WebMvcConfigurer相关配置都来一起调用;
	@Override
	// public void addViewControllers(ViewControllerRegistry registry) {
	// for (WebMvcConfigurer delegate : this.delegates) {
	// delegate.addViewControllers(registry);
	// }
}
  1. 容器中所有的 WebMvcConfigurer 都会一起起作用
  2. 我们的配置类也会被调用; 效果:SpringMVC 的自动配置和我们的扩展配置都会起作用;
③、全面接管 SpringMVC;

SpringBoot 对 SpringMVC 的自动配置不需要了,所有都是我们自己配置;所有的 SpringMVC 的自动配置都失效了

我们需要在配置类中添加@EnableWebMvc 即可;

代码语言:javascript复制
// 使用WebMvcConfigurer可以来扩展SpringMVC的功能
@Configuration
@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
       /* super.addViewControllers(registry);*/
        // 浏览器 /oy 请求来到 success
        registry.addViewController("/oy").setViewName("success");
    }
}

原理:(为什么@EnableWebMvc 自动配置就失效了)

  1. @EnableWebMvc 的核心
代码语言:javascript复制
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {

2.

代码语言:javascript复制
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

3.

代码语言:javascript复制
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,WebMvcConfigurerAdapter.class })
//容器中没有这个组件的时候,这个自动配置类才生效
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE   10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
  1. @EnableWebMvc 将 WebMvcConfiguationSupport 组件导入进来
  2. 导入的 WebMvcConfiguration 只是 SpringMVC 最基本功能;

5、如何修改 SpringBoot 的默认设置

模式:

  1. SpringBoot 在自动配置很多组件的时候,先看容器中有没有自己配置的(@Bean、@Component)如果有就用户自己配置,如果没有,才自动配置和自己默认组合起来;
  2. 在 SpringBoot 中国会有非常多的 xxxConfigurer 帮助我们进行扩展配置
  3. 在 SpringBoot 中会有很多的 xxxCustomize 帮助我们进行定制配置

6、RestfulCRUD

配置 pom 配置文件

代码语言:javascript复制
   <properties>
       <!-- 布局功能的支持程序  thymeleaf3主程序  layout2以上版本 -->
       <springboot-thymeleaf.version>3.0.9.RELEASE</springboot-thymeleaf.version>
       <thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
</properties>
<!--配置thymeleaf模板-->
   <dependencies>
       <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-thymeleaf</artifactId>
               <version>2.3.1.RELEASE</version>
       </dependency>
   </dependencies>
① 默认访问首页

方式一:(不推荐)

代码语言:javascript复制
// 在Controller中配置
	@RequestMapping({"/","/index.html"})
    public String index(){
        return "index";
    }

方式二:(推荐)

代码语言:javascript复制
// 使用WebConfigurerAdapter可以来扩展SpringMVC的功能
// 使用@EnableWebMvc 不要接管SpringMVC
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
//        super.addViewControllers(registry);
        //浏览器发送得 /oy 请求来到 success
        registry.addViewController("/oy").setViewName("success");
    }

    // 所有的webMvcConfigAdapter组件都会一起起作用
    @Bean // 将组件注册在容器
    public MyMvcConfig MyMvcConfig1(){
        MyMvcConfig config = new MyMvcConfig(){
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
            }
        };
        return config;
    }
}

【application.properties】

代码语言:javascript复制
server.servlet.context-path=/curd

测试:

提前在 POM.xml 文件中引入 bootstrap 依赖(后面需要)

代码语言:javascript复制
<!--引入bootstrap-->
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.0.0</version>
</dependency>
② 国际化
  1. 编写国际化配置文件:
  1. SpringBoot 自动配置好了管理国际化资源文件的组件(2.x 版本):
代码语言:javascript复制
@Bean
   @ConfigurationProperties(
       prefix = "spring.messages"
   )
   public MessageSourceProperties messageSourceProperties() {
       return new MessageSourceProperties();
   }

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

1.x 版本:

代码语言:javascript复制
@ConfigurationProperties(prefix = "spring.messages")
public class MessageSourceAutoConfiguration {
    /**
    * Comma‐separated list of basenames (essentially a fully‐qualified classpath
    * location), each following the ResourceBundle convention with relaxed support for
    * slash based locations. If it doesn't contain a package qualifier (such as
    * "org.mypackage"), it will be resolved from the classpath root.
    */
	private String basename = "messages";
	//我们的配置文件可以直接放在类路径下叫messages.properties;
	@Bean
	public MessageSource messageSource() {
	ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
	if (StringUtils.hasText(this.basename)) {
		//设置国际化资源文件的基础名(去掉语言国家代码的)
		messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(
		StringUtils.trimAllWhitespace(this.basename)));
	}
    if (this.encoding != null) {
		messageSource.setDefaultEncoding(this.encoding.name());
	}
   messageSource.setFallbackToSystemLocale(this.fallbackToSystemLocale);
	messageSource.setCacheSeconds(this.cacheSeconds);
	messageSource.setAlwaysUseMessageFormat(this.alwaysUseMessageFormat);
	return messageSource;
}
  1. application.properties 文件中配置:
代码语言:javascript复制
#指定管理国际化资源文件
spring.messages.basename=i18n.login
  1. 去页面获取的国际化的值
代码语言:javascript复制
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="description" content="" />
    <meta name="author" content="" />
    <title>Signin Template for Bootstrap</title>
    <!-- Bootstrap core CSS -->
    <link
      href="asserts/css/bootstrap.min.css"
      th:href="@{/webjars/bootstrap/4.0.0/css/bootstrap.css}"
      rel="stylesheet"
    />
    <!-- Custom styles for this template -->
    <link
      href="asserts/css/signin.css"
      th:href="@{/asserts/css/signin.css}"
      rel="stylesheet"
    />
  </head>

  <body class="text-center">
    <form class="form-signin" action="dashboard.html">
      <img
        class="mb-4"
        src="asserts/img/bootstrap-solid.svg"
        th:src="@{/asserts/img/bootstrap-solid.svg}"
        alt=""
        width="72"
        height="72"
      />
      <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">
        Please sign in
      </h1>
      <label class="sr-only" th:text="#{login.username}">Username</label>
      <input
        type="text"
        class="form-control"
        placeholder="Username"
        th:placeholder="#{login.username}"
        required=""
        autofocus=""
      />
      <label class="sr-only" th:text="#{login.password}">Password</label>
      <input
        type="password"
        class="form-control"
        placeholder="Password"
        th:placeholder="#{login.password}"
        required=""
      />
      <div class="checkbox mb-3">
        <label>
          <input type="checkbox" value="remember-me" /> [[#{login.remember}]]
        </label>
      </div>
      <button
        class="btn btn-lg btn-primary btn-block"
        type="submit"
        th:text="#{login.btn}"
      >
        Sign in
      </button>
      <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
      <a class="btn btn-sm">中文</a>
      <a class="btn btn-sm">English</a>
    </form>
  </body>
</html>

测试:(更改浏览器语言)

原理:

国际化 Locale(区域信息对象); LocaleResolver(获取区域信息对象)

代码语言:javascript复制
@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;
}
默认的就是根据请求头带来的区域信息Localhost进行国际化
  1. 点击切换国际化

【MyLocaleResolver.calss】

代码语言:javascript复制
// 可以在连接上携带区域的信息
public class MyLocaleResolver implements LocaleResolver{
    @Override
    public Locale resolveLocale(HttpServletRequest httpServletRequest) {
        String l = httpServletRequest.getParameter("l");
        Locale locale = Locale.getDefault();
        if(!StringUtils.isEmpty("_")){
            String[] split = l.split("_");
            locale = new Locale(split[0], split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

    }
}

【MyMvcConfig.class】

代码语言:javascript复制
@Bean
public LocaleResolver localeResolver(){
    return new MyLocaleResolver();
}

【login.html】

代码语言:javascript复制
<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>
③ 登录

开发期间模板的引擎页面修改以后,要实时生效

  1. 禁用模板引擎的缓存
代码语言:javascript复制
# 禁用缓存
spring.thymeleaf.cache=false
  1. 页面修改完成完成以后 ctrl f9 : 重新编译;

【MyLocaleResolver.class】

代码语言:javascript复制
public class MyLocaleResolver implements LocaleResolver{
    @Override
    public Locale resolveLocale(HttpServletRequest httpServletRequest) {
        String l = httpServletRequest.getParameter("l");
        Locale locale = Locale.getDefault();
        if(!StringUtils.isEmpty(l)){
            String[] split = l.split("_");
            locale = new Locale(split[0], split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

    }
}

【LonginController.class】

代码语言:javascript复制
@Controller
public class LonginController {

    @PostMapping(value = "/user/login")
    public String login(@RequestParam("username") String username, @RequestParam("password") String passsword, Map<String , Object> map, HttpSession session){
        if(!StringUtils.isEmpty(username) && "123456".equals(passsword)){
            // 登陆成功,防止表单重复提交,可以重定向到主页
            session.setAttribute("loginUser",username);
            return "redirect:/main.html";
        }else{
            // 登录失败
            map.put("msg","用户名密码错误");
            return "login";
        }
    }
}

【MyMvcConfig.class】

代码语言:javascript复制
@Bean
   public MyMvcConfig MyMvcConfig1(){
       MyMvcConfig config = new MyMvcConfig(){
           @Override
           public void addViewControllers(ViewControllerRegistry registry) {
               registry.addViewController("/").setViewName("login");
               registry.addViewController("/index.html").setViewName("login");
               registry.addViewController("/main.html").setViewName("dashboard");
           }
       };
       return config;
   }

登录错误提示消息

【login.html】

代码语言:javascript复制
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
④ 拦截器进行登陆检查

拦截器

代码语言:javascript复制
/**
*@Description 登录检查
*@Author OY
*@Date 2020/9/3
*@Time 16:07
*/
public class LoginHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Object user = request.getSession().getAttribute("loginUser");
        if(user == null){
            // 未登入,返回登录界面
            request.setAttribute("msg","没有权限请先登陆");
            request.getRequestDispatcher("/index.html").forward(request,response);
            return false;
        }else{
            // 以登录,放行请求
            return true;
        }

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

注册拦截器:【MyMvcConfig.class】

注: 拦截器必须配置不拦截 css 样式,不然页面的 css 样式会失效

代码语言:javascript复制
// 所有的webMvcConfig组件都会一起起作用
    @Bean // 将组件注册在容器
    public MyMvcConfig MyMvcConfig1(){
        MyMvcConfig config = new MyMvcConfig(){
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
                registry.addViewController("/main.html").setViewName("dashboard");
            }

            // 注册拦截器
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                // 静态资源: *.css , *.js
                // SpringBoot已经做好了静态资源映射
/*                registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/")
                            .excludePathPatterns("/index.html","/","/user/login","/asset/**","/webjars/**");*/

                registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
                        .excludePathPatterns("/index.html",
                                "/",
                                "/user/login","/static/**", "/webjars/**");
//
            }
        };
        return config;
    }
⑤ CRUD-员工列表

实验要求:

  1. RestfulCURD: CURD 满足 Rest 风格

URL:/ 资源名称 / 资源标识 HTTP 请求的方式区分对资源 CRUD 操作

普通 CURD(uri 来区分操作)

RestfulCRUD

查询

getEmp

emp—GET

添加

addEmp?xxx

emp—POST

修改

updateEmp?id=xxx&xxx=xx

emp/{id}—PUT

删除

deleteEmp?id=1

emp/{id}—DELETE

  1. 实验的请求架构

实验功能

请求 URL

请求方式

查询所有员工

emps

GET

查询某个员工(来到修改页面)

emp/1

GET

来到添加页面

emp

GET

添加员工

emps

POST

来到修改页面(查出员工进行信息回显)

emp/1

GET

修改员工

emp

PUT

删除员工

emp/1

DELETE

  1. 员工列表

thymeleaf 公共页面元素的抽取

1、抽取公共片段 <div th:fragment=”copy”> © 2011 The Good Thymes Virtual Grocery </div> 2、引入公共片段 <div th:insert=”~{footer:: copy}”>

0 人点赞