Spring Boot(四)——web开发

目录

一、简介

1.1步骤

1.2SpringBoot帮我们配置了什么?

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

2.1 /webjars/**

2.2 /**  如果访问的资源未知,会去以下文件夹里面找

2.3欢迎页 映射配置

2.4图标修改 favicon.ico

三、模板引擎

3.1背景

扫描二维码关注公众号,回复: 9395216 查看本文章

3.2springboot推荐的Thymeleaf

3.3引入Thymeleaf

3.4Thymeleaf使用&语法

      3.4.1源码,原理

 3.4.2使用

3.4.3语法规则

四、Spring MVC auto-configuration

五、如何修改SpringBoot的默认配置

六、扩展SpringMvc

七、全面接管SpringMvc

八、实际使用

8.1引入依赖

8.2页面引用

8.3国际化

8.3.1编写国际化配置文件

8.3.2使用ResourceBundleMessageSource管理国际化资源文件

8.3.3在页面使用国际化内容

8.3.4html代码:

8.3.5效果

九、模板引擎实时生效

9.1禁用缓存

9.2重新编译: Ctrl + F9

9.3登录错误信息提示

9.4拦截器进行登录检查


一、简介

1.1步骤

1)、新建SpringBoot应用,选中需要的模块;

2)、SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行;

3)、自己编写业务代码;

1.2SpringBoot帮我们配置了什么?

******AutoConfiguration: 帮我们给容器中自动配置组件
******Properties:        配置类来封装配置文件的内容

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

可以看WebMvcAutoConfiguration里

 public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
                CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
                if (!registry.hasMappingForPattern("/webjars/**")) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

                String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

            }
        }

2.1 /webjars/**

都去 classpath:/META-INF/resources/webjars/找资源;

其中:webjars:以jar包的方式引入静态资源;官网:https://www.webjars.org/(springboot是通过webjars管理静态资源)

比如访问:Jquery

        1)、添加依赖:

<!--引入jquery的webjar-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.1.1</version>
        </dependency>

     2)、就可以看见:

    3)、访问:http://localhost:8080/webjars/jquery/3.1.1/jquery.js

2.2 /**  如果访问的资源未知,会去以下文件夹里面找

"classpath:/META-INF/resources/"
"classpath:/resources/"
"classpath:/static/"
"classpath:/public/"

2.3欢迎页 映射配置

2.4图标修改 favicon.ico

 (当然可通过 spring.resources.static-location = 来修改资源文件路径)

三、模板引擎

3.1背景

以前开发,我们需要将HTML转换为jsp页面,转jsp的好处就是,我们可以用<c:foreach>等,也能写java代码。

而springboot首先以jar包的方式,不是war包方式,其次,我们使用的是嵌入式的tomcat,默认是不支持jsp。

因此呢,springboot推荐使用模板引擎。

模板引擎的作用就是:页面上的某些值是动态的,我们用一些表达式表示,这些值从哪来呢?我们组装一些数据,然后把页面模板和数据交给模板引擎,模板引擎将数据填充到对应位置,生成一个最终内容,显示出来。

3.2springboot推荐的Thymeleaf

语法简单、功能强大

3.3引入Thymeleaf

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

3.4Thymeleaf使用&语法

      3.4.1源码,原理

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

      官网:https://www.thymeleaf.org/https://www.thymeleaf.org/

 3.4.2使用

  1)导入thymeleaf的名称空间

<html lang="en" xmlns:th="http://www.thymeleaf.org">

2)放数据

3)显示

3.4.3语法规则

表达式:     4 Standard Expression Syntax

Simple expressions:   //表达式语法
        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. ${session.foo}
                //#response : (only in Web Contexts) the HttpServletResponse object.
                //#session : (only in Web Contexts) the HttpSession object.
                //#servletContext : (only in Web Contexts) the ServletContext object.
            //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 使用
        Message Expressions: #{...}     //获取国际化内容
        Link URL Expressions: @{...}     //定义url
        //<!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
        //    <a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
        Fragment Expressions: ~{...}    //片段表达式
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: _

演示:

四、Spring MVC auto-configuration

https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications

五、如何修改SpringBoot的默认配置

模式:

1)、SpringBoot在自动化配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean @Component)如果有就用用户自己配置的,如果没有,才自动配置,如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来

六、扩展SpringMvc

编写一个配置类(@Configuration),是WebMvcConfigurerAdapter类型,不能标注@EnableWebMvc

即保留了自动配置,也可以使用自定义的配置。

原理:

      1)、WebMvcAutoConfiguration是SpringMvc自动配置类;

      2)、在做其他自动配置时会导入:@Import(EnableWebMvcConfiguration.class);

      3)、容器中所有的WebMvcConfiguration会一起起作用;

      4)、我们的配置类也会被调用。

七、全面接管SpringMvc

springboot对springmvc的自动配置就不需要了,所有都是我们自己配,那么在配置类中加@EnableWebMvc即可。

原理:

@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
@Configuration(
    proxyBeanMethods = false
)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class}) //容器中没有这个组件的时候,这个自动配置类才生效
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {

@EnableWebMvc将WebMvcConfigurationSupport组件导入进来;

导入的WebMvcConfigurationSupport只是Springmvc最基本的功能;

八、实际使用

8.1引入依赖

<!--引入BootStarp的webjar-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>4.4.1</version>
        </dependency>

8.2页面引用

<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.4.1/css/bootstrap.css}" rel="stylesheet">
		<!-- Custom styles for thiss template --><!-- 自定义css文件  任意一个方式都行-->
		<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">    
	</head>

好处:会自动修改引用路径!

8.3国际化

8.3.1编写国际化配置文件

结果:

8.3.2使用ResourceBundleMessageSource管理国际化资源文件

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnMissingBean(
    name = {"messageSource"},
    search = SearchStrategy.CURRENT
)
@AutoConfigureOrder(-2147483648)
@Conditional({MessageSourceAutoConfiguration.ResourceBundleCondition.class})
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {
    private static final Resource[] NO_RESOURCES = new Resource[0];

    public MessageSourceAutoConfiguration() {
    }

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

    protected static class ResourceBundleCondition extends SpringBootCondition {
        private static ConcurrentReferenceHashMap<String, ConditionOutcome> cache = new ConcurrentReferenceHashMap();

        protected ResourceBundleCondition() {
        }

        public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
//通过 spring.messages.basename 指定文件
            String basename = context.getEnvironment().getProperty("spring.messages.basename", "messages");
            ConditionOutcome outcome = (ConditionOutcome)cache.get(basename);
            if (outcome == null) {
                outcome = this.getMatchOutcomeForBasename(context, basename);
                cache.put(basename, outcome);
            }

            return outcome;
        }

8.3.3在页面使用国际化内容

看参考3.4.3知:#{}来获取

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

原理:

@Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(
            prefix = "spring.mvc",
            name = {"locale"}
        )
        public LocaleResolver localeResolver() {
            if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
                return new FixedLocaleResolver(this.mvcProperties.getLocale());
            } else {
                AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
                localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
                return localeResolver;
            }
        }

//默认的就是根据request带来的区域信息获取Local进行国际化

定义自己的Locale:

加入到容器:

8.3.4html代码:

<!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 th:href="@{/webjars/bootstrap/4.4.1/css/bootstrap.css}" rel="stylesheet">
		<!-- Custom styles for thiss template -->
		<link th:href="@{/asserts/css/signin.css}" rel="stylesheet">
	</head>
	<body class="text-center">
		<form class="form-signin" action="dashboard.html" method="post">
			<img class="mb-4" 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"  name="username" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
			<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>
			<a class="btn btn-sm" th:href="@{/login.html(l='zh_CN')}" >中文</a>
			<a class="btn btn-sm" th:href="@{/login.html(l='en_US')}">English</a>
		</form>
	</body>

</html>

8.3.5效果

九、模板引擎实时生效

9.1禁用缓存

spring.thymeleaf.cache=false

9.2重新编译: Ctrl + F9

9.3登录错误信息提示

<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

9.4拦截器进行登录检查

/*
*登录检查
 *  */
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;
        }
        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 {

    }
}
@Bean
    public WebMvcConfigurer webMvcConfigurerAdapter(){
        return new WebMvcConfigurer(){
            @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) {
                registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
                        .excludePathPatterns("/","/index.html","/asserts/**","/webjars/**","/user/login");
            }
        };
    }
发布了25 篇原创文章 · 获赞 5 · 访问量 4502

猜你喜欢

转载自blog.csdn.net/qq_41605068/article/details/104065233