SpringBoot-web开发

一.springboot对静态资源的映射规则

1.web jars的映射

  1. webjars:以jar包的方式引入静态资源

所有的/webjars/**,都去classpath:/META-INF/resources/webjars/找资源

2./**

访问当前项目的任何资源(默认静态资源的文件夹)

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public/
  • /:当前项目的根路径

3.欢迎页

静态资源文件夹下的index.html页面,被/**映射
localhost:8080:/ -> 找index.html

4.favicon(网页图标)

所有的**/favicon.ico都在静态资源文件夹下找

5.自定义静态资源路径

在properties或yml配置里面定义(可以定义多个)

spring.resource.static.locations=classpath:/hello/,classpath:/world/

二.模板引擎

JSP、velocity、freeMark、thymeleaf(springboot推荐)

1.thymeleaf引入

  1. 引入thymeleaf
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-themaleaf</artifactId>
</dependency>

2.thymeleaf使用

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
	private static final Charset DEFAULT_ENCODING = Charset.forName("UTF‐8");
	private static final MimeType DEFAULT_CONTENT_TYPE =MimeType.valueOf("text/html");
	public static final String DEFAULT_PREFIX = "classpath:/templates/";
	public static final String DEFAULT_SUFFIX = ".html";
//
}

只要把html文件放入templates目录下,thymeleaf就能自动渲染,直接return:“success”;
不同的是要导入thymeleaf的名称空间,目的是有语法提示,如下

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

3.thymeleaf语法规则

(1)th:*

具体见官网文档usethymeleaf.pdf
在这里插入图片描述

  1. th:text;改变当前元素里面文本内容,th:utext不转义特殊字符
  2. th:任意html属性,来替换原生属性的值
@Controller
public class userController {
    @RequestMapping("/user")
    public String success(Map<String,Object> map){
        map.put ( "hello","你好" );//会把map放入request作用域中去
        return "success";
    }
}

<div id="dic01" th:text="${hello}" th:id="${hello}">success</div>
  1. th:each
    [[]]与th:text对应
    [()]与th:utext对应
<span th:each="user:${list}">[[${user}]]<br></span>

(2)表达式

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: _
  1. ${}
  • 可以获取对象属性,调用方法

  • 可以使用基本内置对象:#ctx,#vars,#locale,#request,#response,#session,#sevletContext1

  • 可以使用内置工具对象:

  1. *{}选择表达式,和${}功能一样,和th:object配合使用
<div ><!--普通使用-->
	<p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>
	<p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
	<p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
</div>
<div th:object="${session.user}"><!--配合th:object使用-->
	<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>
  1. #{}获取国际化内容
  2. @{}定义url
<div href="details.html" th:href="@{/order/process(execId=${execId},execType='FAST')}"></div>
  1. ~{}片段引用表达式
<div th:insert="~{commons :: main}">...</div>

三.mvc自动配置

1.SpringBoot对SpringMVC的默认配置:(WebMvcAutoConfiguration)

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
  • 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 beans.
  • Support for HttpMessageConverters (see below).
  • Automatic registration of MessageCodesResolver (see below).定义错误代码生成规则
  • Automatic use of a ConfigurableWebBindingInitializer bean (see below).

2.扩展Spring MVC

  • springmvc中的配置文件
<mvc:view‐controller path="/hello" view‐name="success"/>
<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/hello"/>
		<bean></bean>
	</mvc:interceptor>
</mvc:interceptors>
  • springboot扩展配置
    编写一个配置类(@Configuration),是WebMvcConfigurerAdapter类型;不能标注@EnableWebMvc;既保留了所有的自动配置,也能用我们扩展的配置;
//使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		// super.addViewControllers(registry);
		//浏览器发送 /atguigu 请求来到 success
		registry.addViewController("/atguigu").setViewName("success");
	}
}

原理:

  1. WebMvcAutoConfiguration是SpringMVC的自动配置类
  2. 在做其他自动配置时会导入;@Import(EnableWebMvcConfiguration.class)
  3. 容器中所有的WebMvcConfigurer都会一起起作用;
  4. 我们的配置类也会被调用;

3.全面接管springMVC

SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己配置;所有的SpringMVC的自动配置都失效了
我们需要在配置类中添加@EnableWebMvc即可;

@EnableWebMvc
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		// super.addViewControllers(registry);
		//浏览器发送 /atguigu 请求来到 success
		registry.addViewController("/atguigu").setViewName("success");
	}
}

四.默认访问首页的修改

@Controller
public class HelloController {
    @RequestMapping("/")
    //方式1
    public String index(){
        return "login";
    }
}

@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
	//springboot2.0中用WebMvcConfigurationSupport代替
    @Override//方式2
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController ( "/liangqiu" ).setViewName ( "login" );
    }
    @Bean//方式3
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter ( ) {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController ( "/index.html" ).setViewName ( "login" );
            }
        };
        return adapter;
    }
}

五.国际化

步骤:
1)、编写国际化配置文件;
2)、使用ResourceBundleMessageSource管理国际化资源文件
3)、在页面使用fmt:message取出国际化内容
4)、点击链接切换国际化

1.编写国际化配置文件

编写国际化配置文件,抽取页面需要显示的国际化消息,并且可以修改国际化文件的默认位置(默认为类路径下的messages文件)

spring.messages.basename=i18n.login

在这里插入图片描述

2.管理国际化资源文件

SpringBoot自动配置好了管理国际化资源文件的组件(以下为源代码)

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

3.去页面获取国际化的值;

以下为我的html代码,主要用#{}获取国际化内容

<!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.3.1/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" th:src="@{asserts/img/bootstrap-solid.svg}" 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" required="" autofocus="" th:placeholder="#{login.username}">
			<label class="sr-only" th:text="#{login.password}">Password</label>
			<input type="password" class="form-control" placeholder="Password" required="" th:placeholder="#{login.password}">
			<div class="checkbox mb-3">
				<label>
          	<input type="checkbox" value="remember-me" >[[#{login.remmember}]]
        </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>

4.点击链接切换国际化

<a class="btn btn-sm" th:href="@{/index.html(l=zh_CN)}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l=en_CS)}">English</a>
public class MyLocaleResolver implements LocaleResolver {

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        String str = request.getParameter ( "l" );
        Locale locale = Locale.getDefault ( );
        if (!StringUtils.isEmpty ( str )){
            String[] split = str.split("_");
            locale = new Locale(split[0],split[1]);
        }
        return locale;
    }

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

    }
}

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

六、拦截器

1.快速生效

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

  1. 禁用模板引擎的缓存
spring.thymeleaf.cache=false
#禁用缓存
  1. 页面修改之后ctrl+f9,重新编译

2.拦截器

(1)编写拦截器

public class MyIntercepter implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Object user = request.getSession ( ).getAttribute ( "user" );
        if (user!=null){
            return true;
        }else{
            request.setAttribute ( "msg","没有权限请先登录" );
            request.getRequestDispatcher ( "/index.html" ).forward ( request,response );
            return false;
        }
    }

    @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 {

    }
}

(2)注册拦截器

@Bean//方式3
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter ( ) {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor ( new MyIntercepter () ).addPathPatterns ( "/**" )
                        .excludePathPatterns ( "/index.html" ,"/liangqiu","/","/user/login","/asserts/**");
            }
			//除了要放行首页外,还要放行访问静态资源,这是有些时候首页样式表不起效的原因
        };
        return adapter;
    }

七.thymeleaf公共页面元素抽取(片段引用)

1.步骤

  1. 抽取公共片段
<div th:fragment="copy">
&copy; 2011 The Good Thymes Virtual Grocery
</div>
  1. 引入公共片段
<div th:insert="~{footer :: copy}"></div>
~{templatename::#selector}:模板名::选择器
~{templatename::fragmentname}:模板名::片段名
  1. 默认效果
    insert的公共片段在div标签中
    如果使用th:insert等属性进行引入,可以不用写~{}:
    行内写法可以加上:[[{}]];[({})];
<div>
	<div th:insert="~{footer :: copy}"></div>
</div>

2.三种引入公共片段的th属性

  • th:insert:将公共片段整个插入到声明引入的元素中
  • th:replace:将声明引入的元素替换为公共片段
  • th:include:将被引入的片段的内容包含进这个标签中
<footer th:fragment="copy">
&copy; 2011 The Good Thymes Virtual Grocery
</footer>
引入方式
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
效果
<div>
<footer>
&copy; 2011 The Good Thymes Virtual Grocery
</footer>
</div>
<footer>
&copy; 2011 The Good Thymes Virtual Grocery
</footer>
<div>
&copy; 2011 The Good Thymes Virtual Grocery
</div>

3.使用id选择器引入

<nav class="col-md-2 d-none d-md-block bg-light sidebar" id="sidebar">
</nav>
<div th:replace="~{dashboard::#sidebar}"></div>

4.引用片段的时候传入参数,以实现动态的html

步骤

  1. 公共片段定义参数
<a class="nav-link active" href="#" th:href="@{/main}"
                    th:class="${activeUri=='main'?'nav-link active':'nav-link'}">
                    ...
<a class="nav-link active" href="/crud/emps" th:href="@{/emps}"
                    th:class="${activeUri=='emps'?'nav-link active':'nav-link'}">
               
  1. 不同场景传入不同参数
<div th:replace="~{commons/bar::#sidebar(activeUri=emps)}"></div>
<div th:replace="~{commons/bar::#sidebar(activeUri=main)}"></div>
  1. 效果图
    在这里插入图片描述
    在这里插入图片描述
    在公共片段部分点中哪个按钮就高亮,就是点击不同的按钮,进入不同的html,然后引入公共片段,根据传入的参数显示不同的地方高亮。

八.springboot下的put/delete请求

1.springmvc中配置HiddenHttpMethodFilter(springboot自动配置好了)
2.页面创建一个post表单
3.创建一个input项,name="_method",值就是我们指定的请求方式

<form th:action="@{/emp}" method="post">
	<input type="hidden" name="_method" value="put">
</form>

九.错误处理机制

1.springboot默认的错误处理机制

原理可参照ErrorMvcAutoConfiguration,错误的自动配置

(1)浏览器访问

返回一个默认错误处理页面
在这里插入图片描述

(2)其他客户端

默认响应一个json数据
在这里插入图片描述

2.如何定制错误响应

(1)如何定制错误的页面

  1. 有模板引擎的情况下;error/状态码; (将错误页面命名为 错误状态码.html 放在模板引擎文件夹里面的error文件夹下),发生此状态码的错误就会来到 对应的页面;我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html如:404.html);
    页面能获取的信息:
    timestamp:时间戳
    status:状态码
    error:错误提示
    exception:异常对象
    message:异常消息
    errors:JSR303数据校验的错误都在这里
  2. 没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找;
  3. 以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;

(2)如何定制错误的json数据

  1. 自定义异常&返回定制json数据
@ControllerAdvice
public class MyExceptionHandler {
	@ResponseBody
	@ExceptionHandler(UserNotExistException.class)
	public Map<String,Object> handleException(Exception e){
		Map<String,Object> map = new HashMap<>();
		map.put("code","user.notexist");
		map.put("message",e.getMessage());
		return map;
	}
}
//没有自适应效果(浏览器和客户端都是json字符串)
  1. 转发到/error进行自适应响应效果处理
@ControllerAdvice
public class MyExceptionHandler {
	@ExceptionHandler(UserNotExistException.class)
	public String handleException(Exception e, HttpServletRequest request){
		Map<String,Object> map = new HashMap<>();
		//传入我们自己的错误状态码 4xx 5xx,否则就不会进入定制错误页面的解析流程
		/**
		* Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
		*/
		request.setAttribute("javax.servlet.error.status_code",500);
		map.put("code","user.notexist");
		map.put("message",e.getMessage());
		request.setAttribute("ext",map);//将定制数据传入request
		return "forward:/error";
		//定制数据没有携带出去
	}
}
  1. 将我们的定制数据携带出去
    出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法);
    第一种办法:完全来编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中;(太麻烦,不推荐)
    第二种办法:页面上能用的数据,或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes得到;容器中DefaultErrorAttributes.getErrorAttributes();默认进行数据处理的;
//给容器中加入我们自己定义的ErrorAttributes
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
	@Override
	public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,
boolean includeStackTrace) {
		Map<String, Object> map = super.getErrorAttributes(requestAttributes,includeStackTrace);
		Map<String,Object> ext=(Map<String,Object>)requestAttribute.getAttribute("ext",0);
		//从异常处理器获取定制数据,0表示从request中获取,1表示session
		map.put("company","atguigu");
		return map;
	}
}

十.配置嵌入式servlet容器

1.如何定制和修改servlet容器的相关配置

(1)修改server相关的配置(ServerProperties)

server.port=8081
server.context‐path=/crud
server.tomcat.uri‐encoding=UTF‐8
//通用的Servlet容器设置
server.xxx
//Tomcat的设置
server.tomcat.xxx

(2)编写一个EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器;来修改Servlet容器的配置

@Bean //一定要将这个定制器加入到容器中
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
	return new EmbeddedServletContainerCustomizer() {
	//定制嵌入式的Servlet容器相关的规则
		@Override
		public void customize(ConfigurableEmbeddedServletContainer container) {
			container.setPort(8083);
		}
	};
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值