(1) Introduction
SpringBoot is the basic step for Web development
① Create a SpringBoot application and select the required module.
② SpringBoot will default to the required environment configuration, only a small amount of configuration through the configuration file can make the project run;
③ Write the main business code;
When configuring SpringBoot, you can configure the configuration items and content by referring to the Automatic configuration principles of SpringBoot.
SpringBoot automatic configuration principle use:
What is SpringBoot already configured in this scenario?
2 Can the configured scenarios be modified? What can I change?
③ Can you extend the current scenario?
XxxAutoConfiguration: automatic configuration class in SpringBoot, help us to automatically configure components in the container;
XxxProperties: the corresponding configuration property class in the automatic configuration class, which encapsulates the content of the configuration file;
(2) SpringBoot mapping rules for static resources
1. Path for storing static resources
WebMvcAutoConfiguration: The WebMVC automatic configuration class, responsible for the automatic configuration of WebMVC
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {...// Configure the default static folder location
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
// Configure the mapping path for static resources of the WebJars type
if(! registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
// Configure the mapping path for common static resources
if(! registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern) .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())) .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl)); }}...// Configure the welcome page lookup path
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
returnwelcomePageHandlerMapping; }... }Copy the code
As you can see from the source code, static resources of the webjars type can be found in classpath:/ meta-INF /resources/webjars/
Webjars: Introduce front-end static resources through JAR packages
Blog about Webjars: Introduction to WebJars
The addResourceHandlers method in the WebMvcAutoConfiguration class calls the getStaticLocations method to get the static resource mapping path configured in the ResourceProperties property configuration class.
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/"."classpath:/resources/"."classpath:/static/"."classpath:/public/" };
/** * Locations of static resources. Defaults to classpath:[/META-INF/resources/, * /resources/, /static/, /public/]. */
privateString[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS; .public String[] getStaticLocations() {
return this.staticLocations; }...// Configure path mapping for the welcome page
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
return welcomePageHandlerMapping;
}
// Get the path to the welcome page
private Optional<Resource> getWelcomePage(a) {
String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
}
// Get the welcome page index.html file
private Resource getIndexHtml(String location) {
return this.resourceLoader.getResource(location + "index.html"); }... }Copy the code
Through the above source code analysis can be clearly obtained, static resource search file directory:
"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" Copy the code
2. Static resource path mapping
Static resources and storage paths
All the resources in webjars/** URI correspond to classpath:/ meta-INF /resources/webjars/ The browser URI localhost:8080/webjars/** corresponds to the resource path CLASspath :/ meta-INF /resources/webjars/
For example, use Webjars to import jquery and access it in a browser using the same URI
1) Configure pom. XML to import jquery
<! Create jQuery from webJAR
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.2.0</version>
</dependency>
Copy the code
2) Package structure after import
3) Enter the URI access in the browser
② All resources in the browser /** URI correspond to resources in the following paths
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
Copy the code
For example, create hello. HTML in the static folder and access it in the browser
1) The file path in hello.html
2) The browser’s access URI
③ Configure the welcome page; All index. HTML in the static resource path is mapped to the browser’s /** path
For example, create index. HTML in the public directory and access it in the browser
1) The directory where the index. HTML file is located
2) The browser accesses the URI
(3) template engine
1. Introduction to the template engine
The goal of a template engine is to separate the display from the data. There are many types of template engines such as JSP, Velocity, Freemarker, Thymeleaf, and so on, but the template engine essentially combines template files and data to produce the final HTML code.
SpringBoot integrates Thymeleaf as a template engine. However, in the mainstream environment where the front and back ends are separated, more and more companies choose to provide services with a back end and multiple front ends in order to adapt to the flexible environment, and the use scenarios of template engines serving single applications become less and less. The Thymeleaf template engine is only briefly introduced and used here.
A brief introduction to template engines
Thymeleaf template engine
Thymeleaf is a modern server-side Java templating engine for Web and standalone environments.
The main goal of Thymeleaf is to bring elegant natural templates to your development workflow -HTML that displays correctly in a browser and works as a static prototype, thereby enhancing collaboration across development teams.
With modules for the Spring Framework, lots of integration with your favorite tools, and the ability to plug in your own functionality, Thymeleaf is ideal for modern HTML5 JVM Web development — although it can do a lot of things.
Thymeleaf website
3. Grammar rules for Thymeleaf
① th:text: changes the text content of the current element. Where th: XXX can be placed in any HTML element, replacing the value of the native attribute.
Th: function of the XXX attribute
② Use expression in Thymeleaf
Simple Expressions :(expression syntax)
Variable Expressions: ${... } : get the variable value; OGNL grammar;
1) Get the property of the object and call the method
------------------------------------
2) Use built-in base objects:
#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) Built-in tool objects:
#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: *{... } : select expression: and ${} function is the same;
Supplement: Cooperate Th: object = "${session. The 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: #{... } : Get internationalized content
Link URL Expressions: @{... } : Define URL;
@{/order/process(execId=${execId},execType='FAST')}
Fragment Expressions: ~{... } : fragment reference expression
<div th:insert="~{commons :: main}">...
----------------------------------------
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 :(text operations)
String concatenation: +
Literal substitutions: |The name is ${name}|
-----------------------------------------
Arithmetic (1) The operations of mathematics
Binary Operators: +, *, /, %
Minus Sign (unary operator) : ‐
----------------------------------------
Boolean (Boolean operations)
Binary operators: and , or
Boolean negation (unary operator): ! , not
----------------------------------------
Comparisons Equality :(comparison)
Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , ! = ( eq , ne )
---------------------------------------
Conditional Operators: Conditional operators
If ‐ then: (if) ? (then)
If ‐ then ‐ else: (if) ? (then) : (else)
Default: (value) ? : (defaultvalue)
Special Tokens
No ‐ Operation: _
Copy the code
The syntax of Thymeleaf is not completely covered here, but those who are interested should refer to the official documentation: Thymeleaf Use Reference
4. Use of Thymeleaf
Thymeleaf template engine use:
① Introduce thymeleaf dependency in pom. XML file;
② Refer to the grammar template page of Thymeleaf;
(1) Import dependencies in POM. XML. Import dependencies without configuration. SpringBoot will automatically configure them
<! Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Copy the code
In SpringBoot2.3.4.RELEASE, the integrated Thymeleaf version is 3.0.11.RELEASE is the latest version on the official website
② Write the template page success.html
<! DOCTYPEhtml>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>success</title>
</head>
<body>
<h1>Success!!!</h1>
<div th:utext="${hello}">21313</div>
<div>
<h3>my name is</h3>
<h3 th:text="${name}"></h3>
<hr/>
<! -- th:each iteration generates the current tag: 3 h4 -->
<h4 th:text="${user}" th:each="user:${users}"></h4>
<hr/>
<h4>
<a th:each="user:${users}"> [[${user}]] </a>
</h4>
</div>
</body>
</html>
Copy the code
③ Write the method success that calls the template page
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(a) {
return "hello";
}
@RequestMapping("/success")
public String success(Map<String,Object> map){
map.put("name"."zhangsan");
map.put("hello"."< h3 > hello < / h3 >");
map.put("users", Arrays.asList("zhangsan"."lisi"."wangwu"));
return "success"; }}Copy the code
④ Start the project and access it in the browser
(4) SpringMVC automatic configuration
1. SpringMVC Auto-Configuration
Note in the official SpringBoot documentation:
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
The auto-configuration adds the following features on top of Spring’s defaults:
- Inclusion of
ContentNegotiatingViewResolver
andBeanNameViewResolver
beans.- Support for serving static resources, including support for WebJars (covered later in this document)).
- Automatic registration of
Converter
.GenericConverter
, andFormatter
beans.- Support for
HttpMessageConverters
(covered later in this document).- Automatic registration of
MessageCodesResolver
(covered later in this document).- Static
index.html
support.- Custom
Favicon
support (covered later in this document).- Automatic use of a
ConfigurableWebBindingInitializer
bean (covered later in this document).If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own
@Configuration
class of typeWebMvcConfigurer
but without@EnableWebMvc
.If you want to provide custom instances of
RequestMappingHandlerMapping
,RequestMappingHandlerAdapter
, orExceptionHandlerExceptionResolver
, and still keep the Spring Boot MVC customizations, you can declare a bean of typeWebMvcRegistrations
and use it to provide custom instances of those components.If you want to take complete control of Spring MVC, you can add your own
@Configuration
annotated with@EnableWebMvc
, or alternatively add your own@Configuration
-annotatedDelegatingWebMvcConfiguration
as described in the Javadoc of@EnableWebMvc
.The original translation is as follows:
Spring Boot automatically configures SpringMVC to be used with other applications
Spring Boot Automatic Configuration In addition to the default configuration, the following features are configured:
- contains
ContentNegotiatingViewResolver
和BeanNameViewResolver
Components;- Support for static resources, including support for Webjars;
- Automatic registration
Converter
.GenericConverter
, andFormatter
Components;- support
HttpMessageConverters
;- Automatic registration
MessageCodesResolver
;- Static supported
index.html
Page;- user-enabled
Favicon
;- Automatically using
ConfigurableWebBindingInitializer
Components;If you want to preserve Spring Boot custom configurations and extend MVC custom configurations (interceptors, formatters, view parsers, and other features), you can add your own WebMvcConfigurer Configuration class annotated with @Configuration. And don’t take over SpringMVC with the @enableWebMVC annotation.
If you want to use a custom instance RequestMappingHandlerMapping, RequestMappingHandlerAdapter, Or ExceptionHandlerExceptionResolver and still use the Spring Boot MVC configuration, you can declare a WebMvcRegistrations type of bean, and use it to provide custom configuration to replace the existing configuration.
If you want to completely control the Spring MVC, you can add your own comments with @ EnableWebMvc Configuration class, or add your own comments with @ Configuration DelegatingWebMvcConfiguration, such as: As described in the Javadoc for @enableWebMVC.
Let’s take a look at some of the configurations mentioned:
1) ContentNegotiatingViewResolver: all view combined parser
@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));
// ContentNegotiatingViewResolver uses all the other view resolvers to locate
// a view so it should have a high precedence
resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
return resolver;
}
Copy the code
Based on the method’s return value to the View object, the View object decides how to render (forward? Redirect?) , SpringBoot automates the configuration of the view parser
public interface ViewResolver {
/**
* Resolve the given view by name.
* <p>Note: To allow for ViewResolver chaining, a ViewResolver should
* return {@code null} if a view with the given name is not defined in it.
* However, this is not required: Some ViewResolvers will always attempt
* to build View objects with the given name, unable to return {@code null}
* (rather throwing an exception when View creation failed).
* @param viewName name of the view to resolve
* @param locale the Locale in which to resolve the view.
* ViewResolvers that support internationalization should respect this.
* @return the View object, or {@code null} if not found
* (optional, to allow for ViewResolver chaining)
* @throws Exception if the view cannot be resolved
* (typically in case of problems creating an actual View object)
*/
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
Copy the code
③ Converter; Converters are used when converting between browsers and beans, and there are many converters configured for converting between types
For example, format 2020-11-11 as Date type data
@Bean
@Override
public FormattingConversionService mvcConversionService(a) {
Format format = this.mvcProperties.getFormat();
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters()
.dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime()));
addFormatters(conversionService);
return conversionService;
}
Copy the code
We can add custom formatters and converters just by putting them in containers.
⑤ HttpMessageConverter: SpringMVC is used to convert Http requests and responses, for example: converting entity classes into JSON arrays
HttpMessageConverters, determined from the container, gets all HttpMessageConverters
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider
> converters)
> {
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
}
Copy the code
So we can also add HttpMessageConverter to the container by registering our own components (@bean,@Component)
SpringBoot Web application Development official document: SpringMVC Configuration
2. The extension for SpringMVC
Configuration information required to use SpringMVC when SpringBoot is not used previously
<mvc:view-controller path="/hello" view-name="success"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean></bean>
</mvc:interceptor>
</mvc:interceptors>
<mvc:default-servlet-handler/>
Copy the code
Use configuration files to extend the SpringMVC functionality
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
/** * super.addViewControllers(registry); * The browser sends the /atguigu request to Success *@param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/Bruce").setViewName("ok"); }}Copy the code
Some blogs may refer to inheriting the WebMvcConfigurerAdapter class, but the WebMvcConfigurerAdapter was abandoned after Spring5.0 and replaced with the WebMvcConfigurer interface.
With SpringBoot we can write a Configuration class of type WebMvcConfigurer (annotated with @Configuration) without @enableWebMVC Annotations (annotating this means that our configuration takes over SpringBoot configuration) so that we can write configuration classes that both retain all of SpringBoot’s automatic configuration and use our extended configuration;
Both automatic and custom configurations can be retained for the following reasons:
WebMvcAutoConfigurationAdapter import EnableWebMvcConfiguration classes used to load the custom configuration information;
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {... }Copy the code
EnableWebMvcConfiguration class inheritance DelegatingWebMvcConfiguration class in order to realize the load custom MVC configuration;
@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {... }Copy the code
DelegatingWebMvcConfiguration class contains setConfigurers method, can put all the custom configuration and SpringBoot automatically configure load at the same time, in order to realize the automatic configuration and custom configurations to take effect at the same time;
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if(! CollectionUtils.isEmpty(configurers)) {this.configurers.addWebMvcConfigurers(configurers); }}}Copy the code
Summary of loading configuration:
① WebMvcAutoConfiguration is an automatic configuration class for SpringMVC
(2) in the automatic configuration, will Import @ Import (EnableWebMvcConfiguration. Class)
③ All WebMvcConfigurer configurations in the container are loaded during configuration
④ Our self-written configuration classes are therefore loaded
Result: Automatic configuration of SpringMVC in SpringBoot and our custom configuration information will work
Automatic configuration and custom configuration inheritance diagrams
3. Take over SpringMVC
Instead of using SpringBoot’s automatic configuration of SpringMVC at all, we can use our own configuration content for SpringMVC.
We can add the @enableWebMVC annotation to our own configuration class, at which point the SpringBoot configuration for SpringMVC is completely invalidated, and only our own SpringMVC configuration will take effect.
@EnableWebMVC
Note why SpringBoot autoconfiguration is disabled:
1) EnableWebMVC annotations in the imported DelegatingWebMvcConfiguration class
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
Copy the code
(2) and DelegatingWebMvcConfiguration class inherited WebMvcConfigurationSupport, WebMvcConfigurationSupport contains only the basic configuration for SpringMVC
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {... }Copy the code
Conditions, (3) and WebMvcAutoConfiguration configuration class contains annotations @ ConditionalOnMissingBean (WebMvcConfigurationSupport. Class)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {... }Copy the code
Conclusion:
@Enable
Annotations imported directly from theDelegatingWebMvcConfiguration
Class inheritsWebMvcConfigurationSupport
Class;- while
WebMvcAutoConfiguration
Configure conditional annotations in a class@ConditionalOnMissingBean
Requirement not to includeWebMvcConfigurationSupport
Type bean;- So mark
@Enable
The annotation’s custom configuration class makesWebMvcAutoConfiguration
Automatic configuration class failure, that is, SpringBoot to SpringMVC automatic configuration failure;
4. Modify the default SpringBoot configuration
How SpringBoot loads components:
When SpringBoot automatically configits components, it checks whether there are any user-configured components in the container, i.e. configuration classes with @bean and @Component annotations.
An extended annotation implementation that depends on the @conditition annotation to load components;
SpringBoot also supports the combination of automatic and user configuration for components such as the ViewResovler component;
Basic idea:
XxxAutoConfiguration: SpringBoot automatic configuration class, configuration of related components, configuration class annotation can help us understand the role and requirements of the configuration class;
XxxProperties: is the property class of the automatic configuration class in SpringBoot. The configuration items in the property class are things that we can configure in external configuration files.
XxxConfiguration: Extended configuration class in SpringBoot for extended configuration of automatic configuration. We can look at the composition of these extension configuration classes and write our own configuration classes to extend the SpringBoot configuration classes;
XxxCustomizer: a customizer class in SpringBoot that can be used to help us customize certain configurations;
(5) RestfulCRUD sample project
1. Set the default home page
We can inject a custom WebMvc configuration class into the container to extend the existing WebMvc configuration, and SpringBoot loads both automatic configuration and custom configuration. For example, write a custom configuration class to configure view mapping and modify the default home page access template information. The principle used is the principle we mentioned above for modifying the default configuration.
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
/** * All WebMVCConfiguration components are loaded together *@return* /
@Bean
public WebMvcConfigurer webMvcConfigurer(a) {
/** * Add view mapping */
WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// Redirect the default access to the login template
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard"); }};returnwebMvcConfigurer; }}Copy the code
2. Internationalization configuration
① Write internationalization configuration files;
(2) use ResourceBundleMessageSource management internationalized resource file;
(3) Use FMT :message to fetch internationalized content;
④ Click the link to switch internationalization
Main steps:
(1) Compile the internationalization configuration file and extract the configuration information to be displayed on the page
(2) SpringBoot automatic configuration management internationalized resource file MessageSourceAutoConfiguration configuration the configuration of internationalization content of components
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {...@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) {
The default loading location of internationalization files is set using the basebame attribute
messageSource.setBasenames(StringUtils
.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
}
if(properties.getEncoding() ! =null) {
// Set the base name of the internationalized resource file (remove the language country code)
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());
returnmessageSource; }... }Copy the code
In the MessageSourceProperties property configuration file
public class MessageSourceProperties {
/** * 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. */
// This property is the configuration information that configures the location property of the internationalization profile
private String basename = "messages"; . }Copy the code
So we can configure the path of the internationalization language in the configuration file
server.port=9080
server.servlet.context-path=/crud
spring.thymeleaf.cache=false
Configure the default SpringBoot internationalization language switch path
spring.messages.basename=i18n.login
Copy the code
③ Modify the display of the login page and replace the display with the internationalization configuration attribute.
<! DOCTYPEhtml>
<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 th:href="@ {/ webjars/bootstrap / 4.0.0 / CSS/bootstrap CSS}" rel="stylesheet"/>
<! -- Custom styles for this template -->
<link th:href="@{/asserts/css/signin.css}" rel="stylesheet"/>
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html">
<img class="mb-4" th:src="@{/asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
<! Thymeleaf (Thymeleaf, Thymeleaf);
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<! -- Error message -->
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" name="username" class="form-control" placeholder="Username"
th:placeholder="#{login.username}" required="" utofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" name="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>
<! -- Configure click Chinese and English to switch display information, and configure display content using the information in the sent request header -->
<a class="btn btn-sm" th:href="@{/login.html(l='zh_CN')}">Chinese</a>
<a class="btn btn-sm" th:href="@{/login.html(l='en_US')}">English</a>
</form>
</body>
</html>
Copy the code
4. Customize LocateResolver to switch international information by clicking the link
public class MyLocaleRrsovler implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
// huu'o'qu
String l = request.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 request, HttpServletResponse response, Locale locale) {}}Copy the code
Load our custom LocateResolver component into the container in the custom configuration class MyMvcConfig
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
/** * All WebMVCConfiguration components are loaded together *@return* /
@Bean
public WebMvcConfigurer webMvcConfigurer(a) {
/** * Add view mapping */
WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard"); }};return webMvcConfigurer;
}
/** * Load our custom LocateResolver component into the container *@return* /
@Bean
public LocaleResolver localeResolver(a) {
return newMyLocaleRrsovler(); }}Copy the code
⑤ Final effect: click Chinese and English and the interface will change the display effect according to the language
Principle of international switching:
The AutoWebMvcConfiguration configures internationalization Locate and LocateResolver
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver(a) {
if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
}
// By default, Locale is obtained based on the information in the request header
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
Copy the code
Inheritance relationship of LocateResolver
3. Log in and configure
Configuration mode:
1 Modify the configuration information on the page
② Write the controller related to login
③ Configure a login interceptor
(1) Modify the configuration information on the page. Add Action, that is, the request interface, and set the request mode to POST
<! DOCTYPEhtml>
<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 th:href="@ {/ webjars/bootstrap / 4.0.0 / CSS/bootstrap CSS}" rel="stylesheet"/>
<! -- Custom styles for this template -->
<link th:href="@{/asserts/css/signin.css}" rel="stylesheet"/>
</head>
<body class="text-center">
<! -- Configure the submit interface action to send post requests
<form class="form-signin" action="dashboard.html" th:action="@{/user/login}" method="post">
<img class="mb-4" th:src="@{/asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
<! Thymeleaf (Thymeleaf, Thymeleaf);
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<! -- Error message -->
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" name="username" class="form-control" placeholder="Username"
th:placeholder="#{login.username}" required="" utofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" name="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>
<! -- Configure click Chinese and English to switch display information, and configure display content using the information in the sent request header -->
<a class="btn btn-sm" th:href="@{/login.html(l='zh_CN')}">Chinese</a>
<a class="btn btn-sm" th:href="@{/login.html(l='en_US')}">English</a>
</form>
</body>
</html>
Copy the code
② Configure LoginController. Set the login request rule
@Controller
public class LoginController {
//@RequestMapping(value = "/user/login",method = RequestMethod.POST)
@PostMapping(value = "/user/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Map<String,Object> map, HttpSession session){
if(! StringUtils.isEmpty(username) &&"123456".equals(password)){
// If the login succeeds, the form can be redirected to the home page
session.setAttribute("loginUser",username);
return "redirect:/main.html";
}else{
// Login failed
map.put("msg"."Username and password error");
return "login"; }}}Copy the code
③ Configure the LoginHandlerInterceptor to intercept requests from users who are not logged in
public class LoginHandlerInterceptor implements HandlerInterceptor {
/** * Perform the operation before executing the target method */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("loginUser");
if(user == null) {// No login, return to login page
request.setAttribute("msg"."No permission, please log in first.");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}else{
// Logged-in, release request
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 {}}Copy the code
(4) Register the interceptor in the container in the custom configuration WebMvcConfig
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
/** * All WebMVCConfiguration components are loaded together *@return* /
@Bean
public WebMvcConfigurer webMvcConfigurer(a) {
/** * Add view mapping */
WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard");
}
/** * Register interceptor *@param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// Block all page requests except the login page. Only after login can you access all pages
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/ * *")
.excludePathPatterns("/index.html"."/"."/user/login"); }};return webMvcConfigurer;
}
/** * Load our custom LocateResolver component into the container *@return* /
@Bean
public LocaleResolver localeResolver(a) {
return newMyLocaleRrsovler(); }}Copy the code
4. Restful requests for access
4.1 LIST of CRUD employees
URI: / Resource name/resource ID. CRUD operations are performed on resources using HTTP requests. Resource operations: Perform operations on resources by POST, DELETE, PUT, and GET. Corresponding to add, delete, modify, query.
Plain CRUD (discriminating operations by URI) | RestfulCRUD | |
---|---|---|
The query | getEmployees | employee—GET |
add | addEmployee? xxx | employee—POST |
Modify the | updateEmployee? id=xxx&xxx=xxxx | empoyee/{id}—PUT |
delete | deleteEmployee? id=1 | employee/{id}—DELETE |
Blog about Restful style introduction: Restful style
Employee CRUD request design
Request the functionality of the interface | The request URI | Request way |
---|---|---|
Query all employees | emps | GET |
Query an employee (displayed on the modify page) | emp/1 | GET |
Request to add page | emp | GET |
Adding employee Information | emp | POST |
Enter the modify page (query and display employee information at the same time) | emp/1 | GET |
Modifying employee Information | emp | PUT |
Delete an employee | emp/1 | DELETE |
Thymeleaf public page extraction
1. Extract common fragments<div th:fragment="copy">
© 2020 The Good Thymes Virtual Grocery
</div>2. Introduce public fragments<div th:insert="~{footer :: copy}"></div>~ {templatename: : the selector} : template name: : selector ~ {templatename: : fragmentname} : template name: : fragments of 3, the default effect: Insert: [[~{}]]; [[~{}]]; [[~{}]]; [[~{}]]; [(~ {})];Copy the code
Three th attributes introduced into public fragments:
Th: INSERT: Inserts the entire public fragment into the element introduced by the declaration
Th :replace: Replaces the element introduced by the declaration with a public fragment
Th :include: Includes the content of the introduced fragment in this tag
Code examples:
<footer th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
</footer>
<! -- Introduction mode -->
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
<! - effect - >
<div>
<footer>
© 2011 The Good Thymes Virtual Grocery
</footer>
</div>
<footer>
© 2011 The Good Thymes Virtual Grocery
</footer>
<div>
© 2011 The Good Thymes Virtual Grocery
</div>
Copy the code
The introduction of fragments can also pass parameters
<div th:replace="commons/bar::#sidebar(activeUri='emps')"></div>
Copy the code
4.2 Page and interface design
Specific page and interface design information, more content, please see the specific code: Restful CRUD, staff basic CRUD