目录
1.Web开发
1.1简介
1.2SpringBoot对静态资源的映射规则
1.3模板引擎
1.3.1引入thymeleaf;
1.3.2Thymeleaf语法
1.3.2.1标准表达式语法
1.变量表达式
1.3.2.2表达式支持的语法
1.3.2.3常用的thymeleaf标签
1.4Springboot整合springmvc
1.4.1Springmvc的自动解管理
1.4.1.1中央转发器
1.4.1.2控制器
1.4.1.3视图解析器自动管理
1.4.1.4静态资源访问
1.4.1.5消息转换和格式化
1.4.1.6欢迎页面的自动配置
1.4.2Springboot扩展springmvc
1.4.2.1在容器中注册视图控制器(请求转发)
1.4.2.2注册格式化器
1.4.2.3消息转换器扩展fastjson
1.4.2.4拦截器注册
1.5配置嵌入式服务器
1.5.1如何定制和修改Servlet容器的相关配置;
1.5.2注册Servlet三大组件【Servlet、Filter、Listener】
1.6使用外置的Servlet容器
1.Web开发
1.1简介
使用SpringBoot;
1)、创建SpringBoot应用,选中我们需要的模块;
2)、SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来
3)、自己编写业务代码;
自动配置原理?
这个场景SpringBoot帮我们配置了什么?能不能修改?能修改哪些配置?能不能扩展?xxx
1.2SpringBoot对静态资源的映射规则
@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.icomapping.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/webjars/ 找资源;
webjars:以jar包的方式引入静态资源;WebJars - Web Libraries in Jars
localhost:8080/webjars/jquery/3.3.1/jquery.js
<!‐‐引入jquery‐webjar‐‐>在访问的时候只需要写webjars下面资源的名称即可
<dependency><groupId>org.webjars</groupId><artifactId>jquery</artifactId><version>3.3.1</version>
</dependency>
2)、"/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射
"classpath:/META‐INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":当前项目的根路径
localhost:8080/abc === 去静态资源文件夹里面找abc
3)、欢迎页; 静态资源文件夹下的所有index.html页面;被"/**"映射;
localhost:8080/ 找index页面
1.3模板引擎
JSP、Velocity、Freemarker、Thymeleaf
SpringBoot推荐的Thymeleaf;
语法更简单,功能更强大;
1.3.1引入thymeleaf;
在pom.xml中引入
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
从spring父文件中能看到Springboot2.0.1所使用的thymeleaf版本是3.0.9
springBoot启动的时候会自动配置
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
从ThymeleafAutoConfiguration的源代码中我们可以得知ThymeleafProperties中配置了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";private Charset encoding;private boolean cache;
}
我们使用html作为模板,而且默认的前缀是放在classpath:/templates/下,后缀是.html
当然这些属性我们都可以通过application.properties来修改。我们采用默认即可。
示例:
- 在templates下创建一个success.html
- 在html中引入thymeleaf的命名空间
<html lang="en" xmlns:th="http://www.thymeleaf.org"> - 创建一个Controller提供一个访问的方法
@RequestMapping("/success") public String hello(Model model){model.addAttribute("hello","<h1>zhangsan</h1>");return "success"; }
- 在thymeleaf模板中取值
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head><title>Title</title> </head> <body> <div th:text="${hello}"> </div> </body> </html>
1.3.2Thymeleaf语法
1.3.2.1标准表达式语法
1.变量表达式
变量表达式即OGNL表达式或Spring EL表达式(在Spring术语中也叫model attributes)。如下所示: ${session.user.name}
它们将以HTML标签的一个属性来表示:
<span th:text="${book.author.name}">
2.选择(星号)表达式
选择表达式很像变量表达式,不过它们用一个预先选择的对象来代替上下文变量容器(map)来执行,如下: *{customer.name}
被指定的object由th:object属性定义:
<div th:object="${book}"> ... <span th:text="*{title}">...</span> ...
</div>
3.文字国际化表达式
文字国际化表达式允许我们从一个外部文件获取区域文字信息(.properties),用Key索引Value,还可以提供一组参数(可选).
#{main.title}
4.URL表达式
URL表达式指的是把一个有用的上下文或回话信息添加到URL,这个过程经常被叫做URL重写。不需要指定项目名字
@{/order/list}
URL还可以设置参数:
@{/order/details(id=${orderId})}
让我们看这些表达式:
<form th:action="@{/createOrder}">
<a href="main.html" rel="external nofollow" th:href="@{/main}" rel="external n
1.3.2.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)
示例代码:
'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))
1.3.2.3常用的thymeleaf标签
关键字 | 功能介绍 | 案例 |
th:id | 替换id | <input th:id="'xxx' + ${collect.id}"/> |
th:text | 文本替换 | <p th:text="${collect.description}">description</p> |
th:utext | 支持html的文本替换 | <p th:utext="${htmlcontent}">conten</p> |
th:object | 替换对象 | <div th:object="${session.user}"> |
th:value | 属性赋值 | <input th:value="${user.name}" /> |
th:onclick | 点击事件 | th:οnclick="'getCollect()'" |
th:each | 属性赋值 | tr th:each="user,userStat:${users}"> |
th:if | 判断条件 | <a th:if="${userId == collect.userId}" > |
th:unless | 和th:if判断相反 | <a th:href="@{/login}" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:unless=${session.user != null}>Login</a> |
th:href | 链接地址 | <a th:href="@{/login}" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:unless=${session.user != null}>Login</a> /> |
th:switch | 多路选择 配合th:case 使用 | <div th:switch="${user.role}"> |
th:case | th:switch的一个分支 | <p th:case="'admin'">User is an administrator</p> |
th:fragment | 布局标签,定义一个代码片段,方便其它地方引用 | <div th:fragment="alert"> |
th:include | 布局标签,替换内容到引入的文件 | <head th:include="layout :: htmlhead" th:with="title='xx'"></head> /> |
th:replace | 布局标签,替换整个标签到引入的文件 | <div th:replace="fragments/header :: title"></div> |
th:selected | selected选择框 选中 | th:selected="(${xxx.id} == ${configObj.dd})" |
th:src | 图片类地址引入 | <img class="img-responsive" alt="App Logo" th:src="@{/img/logo.png}" /> |
th:action | 表单提交的地址 | <form action="subscribe.html" th:action="@{/subscribe}"> |
标签测试
模板:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><title>Title</title>
</head>
<body>
<div th:text="${hello}" th:id="${hello.toUpperCase()}">xxxx</div>
<input th:value="${user.getUsername()}">
<hr>
<div th:object="${user}">
<span th:text="*{username}"></span></div><a th:href="" th:if="${user.getAge() == 2}" >年龄</a><a th:class="${user.getAge() > 2}?'class1':'class2'" >年龄</a><p th:if="${user.score >= 60 and user.score < 85}">B</p>
<p th:if="${user.score < 60}">C</p>
<p th:if="${user.score > 85}">优秀</p><span th:switch="${user.gender}"><p th:case="1">男</p><p th:case="2">女</p>
</span><table><tr th:each="a,aState:${uList}"><td th:text="${a.username}"></td><td th:text="${a.password}"></td><td th:text="${aState.index}"></td></tr>
</table></body>
</html>
Controller中给数据
@RequestMapping("/success")
public String hello(HttpServletRequest req, HttpSession httpSession, Model model){model.addAttribute("hello","<h1>renliang</h1>");User user = new User();user.setPassword("111");user.setUsername("renliang");user.setAge(1);user.setScore(78);user.setGender(2);List<User> uList = new ArrayList<>();for (int i = 0; i < 10; i++){User u = new User();u.setUsername("renliang"+i);u.setPassword("111"+i);uList.add(u);}// httpSession.setAttribute("user", user);model.addAttribute("user", user);model.addAttribute("uList", uList);return "success";
}
1.4Springboot整合springmvc
https://docs.spring.io/spring-boot/docs/2.0.2.RELEASE/reference/htmlsingle/#boot-features-spring-mvc
学习springmvc和springboot的自动配置我们必须对springmvc的组件足够了解,起码知道怎么用。Springmvc的组件基本都被springboot来做了自动的配置。
1.4.1Springmvc的自动解管理
- 中央转发器(DispatcherServlet)
- 控制器
- 视图解析器
- 静态资源访问
- 消息转换器
- 格式化
- 静态资源管理
-
1.4.1.1中央转发器
-
Xml无需配置
-
<servlet><servlet-name>chapter2</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup> </servlet> <servlet-mapping><servlet-name>chapter2</servlet-name><url-pattern>/</url-pattern> </servlet-mapping>
中央转发器被springboot自动接管,不再需要我们在web.xml中配置,我们现在的项目也不是web项目,也不存在web.xml,
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
-
-
1.4.1.2控制器
控制器Controller在springboot的注解扫描范围内自动管理。
1.4.1.3视图解析器自动管理
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
ContentNegotiatingViewResolver:组合所有的视图解析器的;
曾经的配置文件无需再配
<bean id="de" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> |
源码:
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));resolver.setOrder(-2147483648);return resolver;
}
当我们做文件上传的时候我们也会发现multipartResolver是自动被配置好的页面
<form action="/upload" method="post" enctype="multipart/form-data"><input name="pic" type="file"><input type="submit">
</form>
Controller
@ResponseBody
@RequestMapping("/upload")
public String upload(@RequestParam("pic")MultipartFile file, HttpServletRequest request){String contentType = file.getContentType();String fileName = file.getOriginalFilename();/*System.out.println("fileName-->" + fileName);System.out.println("getContentType-->" + contentType);*///String filePath = request.getSession().getServletContext().getRealPath("imgupload/");String filePath = "D:/imgup/";try {this.uploadFile(file.getBytes(), filePath, fileName);} catch (Exception e) {// TODO: handle exception}return "success";
}public static void uploadFile(byte[] file, String filePath, String fileName) throws Exception {File targetFile = new File(filePath);if(!targetFile.exists()){targetFile.mkdirs();}FileOutputStream out = new FileOutputStream(filePath+fileName);out.write(file);out.flush();out.close();
}
文件上传大小可以通过配置来修改
打开application.properties, 默认限制是10MB,我们可以任意修改
1.4.1.4静态资源访问
参见4.2
1.4.1.5消息转换和格式化
Springboot自动配置了消息转换器
格式化转换器的自动注册
时间类型我们可以在这里修改
在配置文件中指定好时间的模式我们就可以输入了
1.4.1.6欢迎页面的自动配置
Springboot自动指定resources下的index.html
1.4.2Springboot扩展springmvc
在实际开发中springboot并非完全自动化,很多跟业务相关我们需要自己扩展,springboot给我提供了接口。
我们可以来通过实现WebMvcConfigurer接口来扩展
public interface WebMvcConfigurer {default void configurePathMatch(PathMatchConfigurer configurer) {}default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {}default void configureAsyncSupport(AsyncSupportConfigurer configurer) {}default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {}default void addFormatters(FormatterRegistry registry) {}default void addInterceptors(InterceptorRegistry registry) {}default void addResourceHandlers(ResourceHandlerRegistry registry) {}default void addCorsMappings(CorsRegistry registry) {}default void addViewControllers(ViewControllerRegistry registry) {}default void configureViewResolvers(ViewResolverRegistry registry) {}default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {}default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {}default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {}default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {}default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {}default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {}@Nullabledefault Validator getValidator() {return null;}@Nullabledefault MessageCodesResolver getMessageCodesResolver() {return null;}
}
1.4.2.1在容器中注册视图控制器(请求转发)
创建一个MyMVCCofnig实现WebMvcConfigurer接口,实现一下addViewControllers方法,我们完成通过/tx访问,转发到success.html的工作
@Configuration
public class MyMVCCofnig implements WebMvcConfigurer{@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/tx").setViewName("success");}
}
1.4.2.2注册格式化器
用来可以对请求过来的日期格式化的字符串来做定制化。当然通过application.properties配置也可以办到。
@Override
public void addFormatters(FormatterRegistry registry) {registry.addFormatter(new Formatter<Date>() {@Overridepublic String print(Date date, Locale locale) {return null;}@Overridepublic Date parse(String s, Locale locale) throws ParseException {return new SimpleDateFormat("yyyy-MM-dd").parse(s);}});
}
1.4.2.3消息转换器扩展fastjson
在pom.xml中引入fastjson
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version>
</dependency>
配置消息转换器,添加fastjson
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {FastJsonHttpMessageConverter fc = new FastJsonHttpMessageConverter();FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);fc.setFastJsonConfig(fastJsonConfig);converters.add(fc);
}
在实体类上可以继续控制
public class User
{private String username;private String password;private int age;private int score;private int gender;@JSONField(format = "yyyy-MM-dd")private Date date;}
1.4.2.4拦截器注册
1.创建拦截器
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("前置拦截");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("后置拦截");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("最终拦截");}
}
拦截器注册
@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/hello2");
}
1.5配置嵌入式服务器
1.5.1如何定制和修改Servlet容器的相关配置;
修改和server有关的配置(ServerProperties);
server.port=8081
server.context‐path=/tx
server.tomcat.uri‐encoding=UTF‐8
1.5.2注册Servlet三大组件【Servlet、Filter、Listener】
由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,没有web.xml文件。
1.servlet
//注册三大组件
@Bean
public ServletRegistrationBean myServlet(){ServletRegistrationBean registrationBean = new ServletRegistrationBean(newMyServlet(),"/myServlet");return registrationBean;
}
2. FilterRegistrationBean
@Bean
public FilterRegistrationBean myFilter(){FilterRegistrationBean registrationBean = new FilterRegistrationBean();registrationBean.setFilter(new MyFilter());registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));return registrationBean;
}
3. ServletListenerRegistrationBean
@Bean
public ServletListenerRegistrationBean myListener(){ServletListenerRegistrationBean<MyListener> registrationBean = newServletListenerRegistrationBean<>(new MyListener());return registrationBean;
}
SpringBoot帮我们自动SpringMVC的时候,自动的注册SpringMVC的前端控制器;DispatcherServlet;
DispatcherServletAutoConfiguration中:
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name =
DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public ServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet) {ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet, this.serverProperties.getServletMapping());//默认拦截: / 所有请求;包静态资源,但是不拦截jsp请求; /*会拦截jsp//可以通过server.servletPath来修改SpringMVC前端控制器默认拦截的请求路径registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);registration.setLoadOnStartup(this.webMvcProperties.getServlet().getLoadOnStartup());if (this.multipartConfig != null) {registration.setMultipartConfig(this.multipartConfig);}return registration;
}
1.6使用外置的Servlet容器
嵌入式Servlet容器:应用打成可执行的jar
优点:简单、便携;
缺点:默认不支持JSP、优化定制比较复杂.;
外置的Servlet容器:外面安装Tomcat---应用war包的方式打包;
步骤
1)、必须创建一个war项目;(利用idea创建好目录结构)
2)、将嵌入式的Tomcat指定为provided;
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring‐boot‐starter‐tomcat</artifactId><scope>provided</scope>
</dependency>
3)配置项目的目录结构
4)部署Tomcat
3)、必须编写一个SpringBootServletInitializer的子类,并调用configure方法
public class ServletInitializer extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {//传入SpringBoot应用的主程序return application.sources(SpringBoot04WebJspApplication.class);}
}
4)、启动服务器就可以使用;
原理
jar包:执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的Servlet容器;
war包:启动服务器,服务器启动SpringBoot应用【SpringBootServletInitializer】,启动ioc容器;