SpringBoot
2022-01-24 20:16:39 77 举报
AI智能生成
SpringBoot学习的大致流程
作者其他创作
大纲/内容
框架入门
前言
Spring优点:<br>1、使用Spring的IOC容器,将对象之间的依赖关系交给Spring,降低组件之间的耦合性,让我们更专注于应用逻辑。<br>2、提供众多服务、事务管理、WS等。<br>3、AOP的很好支持,方便面向切面编程。<br>4、对主流框架提供了很好的集成支持:如Hibernate、Struts2、JPA等<br>5、Spring DI机制降低了业务对象替换的复杂性。<br>6、Spring属于低侵入,代码污染极低。<br>7、Spring的高度可开放性,并不强制依赖于Spring,开发者可自由选择部分或全部。
Spring缺点:<br> 虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。一开始,Spring用XML配置,而且是很多XML配置。Spring 2.5引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式XML配置。Spring 3.0引入了基于Java的配置,这是一种类型安全的可重构配置方式,可以代替XML。(配置代表开发时损耗)<br> 除此之外,项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。
概述
SpringBoot便是对上述Spring缺点进行的改善和优化,简化Spring应用程序的创建和开发过程,也可以说简化SSM框架进行开发的过程,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换。<br> 在以往采用SSM框架进行开发时,搭建和整合三大框架,要配置web.xml、Spring、MyBatis还有整合等。现在SpringBoot框架对此开发过程进行了革命性颠覆,完全抛弃了繁琐的xml配置过程,采用大量默认配置简化开发过程。<br> 所以采用SpringBoot可以容易和快速地创建基于Spring框架的应用程序,他让编码、配置、部署、监控变得简单。<br>
特性
1、能快速创建基于Spring的应用程序。<br>
2、能直接使用java main方法启动内嵌的Tomcat服务器运行SpringBoot程序,不需要部署war包文件。<br>
3、提供约定的starter POM来简化Maven配置,让Maven配置变得简单。<br>
4、自动化配置,根据项目的Maven依赖配置,SpringBoot自动配置Spring、SpringMVC等。<br>
5、提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。<br>
6、开箱即用,基本可以完全不使用XML配置文件,采用注解配置。同时也可以修改默认值来满足特定的需求。<br>
四大核心功能<br>
1、自动配置<br>Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个。该过程是Spring自动完成的。<br>
2、起步依赖<br>起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。<br>
3、Actuator(#)<br>
4、命令行界面(#)<br>
核心注解
@SpringBootApplication启动入口类<br>
@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。<br>
@ComponentScan:Spring组件扫描。<br>
当前工程GAV
<groupId>com.kx</groupId><br> <artifactId>springboot002</artifactId><br> <version>0.0.1-SNAPSHOT</version>
当前工程的父工程GAV<br>
<parent><br> <groupId>org.springframework.boot</groupId><br> <artifactId>spring-boot-starter-parent</artifactId><br> <version>2.5.6</version><br> <relativePath/> <!-- lookup parent from repository --><br> </parent>
starter-parent的父工程
<groupId>org.springframework.boot</groupId><br> <artifactId>spring-boot-dependencies</artifactId><br> <version>2.5.6</version>
spring-boot-starter-parent分类<br>
1. Spring Boot应用类启动器<br>spring-boot-starter————包含自动配置、日志、YAML的支持。<br>spring-boot-starter-web———使用SpringMVC构建web工程,包含restful,默认使用Tomcat容器。。。
2. Spring Boot生产启动器
3. Spring Boot技术类启动器<br>spring-boot-starter-json————提供对JSON读写支持<br>spring-boot-starter-logging————默认的日志启动器Logback
4. 其他第三方启动器
入门案例
一、创建SpringBoot框架web项目
spring-boot-starter-web
SpringBoot-web项目起步依赖
<!--SpringBoot项目打包编译的插件--><br> <plugins><br> <plugin><br> <groupId>org.springframework.boot</groupId><br> <artifactId>spring-boot-maven-plugin</artifactId><br> </plugin><br> </plugins>
二、集成SpringMVC
常用注解
@Controller
@ResponseBody
@RestController=@Controller+@ResponseBody
@RequestMapping(method=get/post/delete/put/patch)
@Controller<br>public class IndexController {<br> @RequestMapping("/springboot/say")<br> @ResponseBody<br> public String say(){<br> return "hello,springboot!";<br> }<br>}
三、核心配置文件
application-properties
#设置内嵌Tomcat端口号<br>server.port=9090<br>#设置上下文根<br>server.servlet.context-path=/springboot003
application.yml
server:<br> port: 8081<br> servlet:<br> context-path: /springboot004
application.yaml
若application.properties和application.yml或application.yaml同时存在,优先前者
多环境配置文件<br>后缀properties和yml配置大致相同
application.properties<br>
#SpringBoot主核心配置文件<br>#激活使用的配置文件<br>spring.profiles.active=dev
application-dev.properties<br>
#开发环境的配置文件<br>server.port=8080<br>server.servlet.context-path=/dev
application-product.properties<br>
#生产环境的配置文件<br>server.port=8083<br>server.servlet.context-path=/product<br>
application-ready.properties<br>
#准生产环境的配置文件<br>server.port=8082<br>server.servlet.context-path=/ready<br>
application-test.properties<br>
#测试环境的配置文件<br>server.port=8081<br>server.servlet.context-path=/test<br>
获取配置文件中自定义的值
${ property : default_value }<br>
例:<br>#配置自定义属性<br>student.name=zkx<br>websit=www.kx25.com<br>—————————————<br>@Value("${student.name}")<br>private String stuName;<br>
#{ obj.property? :default_value }
将配置文件中的自定义值映射到对象<br>(注:得有前缀)
school.name=kxSchool<br>school.website=www.kx25.com<br>————————————————————<br>@Component<br>@ConfigurationProperties(prefix = "school")<br>public class School {<br> private String name;<br> private String website;<br>}<br>
<!--解决使用@ConfigurationProperties注解出现警告--><br> <dependency><br> <groupId>org.springframework.boot</groupId><br> <artifactId>spring-boot-configuration-processor</artifactId><br> <optional>true</optional><br> </dependency>
注:如果在SpringBoot核心配置文件中有中文信息,会出现乱码。一般在<br>配置文件中,不建议出现中文(注释除外)。如果有,可以先转化为ASCII码。<br>Idea操作:setting——editor——file encodings——UTF-8√<br>(注:拷贝配置是注意空格删干净)
四、集成jsp
依赖:<br><!--web项目起步依赖--><br>spring-boot-starter-web<br><!--引入SpringBoot内嵌Tomcat对jsp的解析依赖,不添加解析不了jsp--><br><dependency><br> <groupId>org.apache.tomcat.embed</groupId><br> <artifactId>tomcat-embed-jasper</artifactId><br></dependency><br>
<!--<br> SpringBoot项目默认推荐使用Thymeleaf<br> 现在要使用SpringBoot集成JSP,手动指定JSP最后编译的路径<br> 而且SpringBoot集成JSP编译JSP的路径是SpringBoot规定好的位置<br> META-INF/resources<br> --><br><resources><br> <resource><br> <!--源文件夹--><br> <directory>src/main/webapp</directory><br> <!--指定编译到META-INF/resources--><br> <targetPath>META-INF/resources</targetPath><br> <!--指定源文件中的那个资源要编译进行--><br> <includes><br> <include>*.*</include><br> </includes><br> </resource><br></resources><br>
#配置视图解析器<br>spring.mvc.view.prefix=/<br>spring.mvc.view.suffix=.jsp
五、logo的关闭和修改
关闭logo
//获取入口类<br>// SpringApplication springApplication = new SpringApplication(LogoApplication.class);<br> //设置它的属性<br>// springApplication.setBannerMode(Banner.Mode.OFF);<br>// springApplication.run(args);
修改logo
//修改logo只需添加banner.txt<br>SpringApplication.run(LogoApplication.class, args);<br>
例:<br>${AnsiColor.RED}<br> .::::.<br> .::::::::.<br> :::::::::::<br> ..:::::::::::'<br> '::::::::::::'<br> .::::::::::<br> '::::::::::::::..<br> ..::::::::::::.<br> ``::::::::::::::::<br> ::::``:::::::::' .:::.<br> ::::' ':::::' .::::::::.<br> .::::' :::: .:::::::'::::.<br> .:::' ::::: .:::::::::' ':::::.<br> .::' :::::.:::::::::' ':::::.<br> .::' ::::::::::::::' ``::::.<br> ...::: ::::::::::::' ``::.<br> ```` ':. ':::::::::' ::::..<br> '.:::::' ':'````..<br>:: Spring Boot :: (v2.6.2.RELEASE)<br>
集成MyBatis
依赖:<br>mybatis-spring-boot-starter、mysql-connector-java
mybatis逆向工程
个人习惯在cmd中使用generator.xml自动生成(不会让项目看起来变的复杂)
springboot中mybatis-generator<br>配置完后双击maven中plugin中mybatis-generator<br>
<plugin><br> <groupId>org.mybatis.generator</groupId><br> <artifactId>mybatis-generator-maven-plugin</artifactId><br> <version>1.3.2</version><br> <configuration><br> <overwrite>true</overwrite><br> <configurationFile>GeneratorMapper.xml</configurationFile><br> </configuration><br></plugin><br>
<!DOCTYPE generatorConfiguration<br> PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"<br> "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><br><generatorConfiguration><br> <!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包--><br> <classPathEntry location="D:\generator/mysql-connector-java-8.0.16.jar"/><br> <context id="DB2Tables" targetRuntime="MyBatis3"><br> <!-- JavaBean 实现 序列化 接口 --><br> <!-- <plugin type="org.mybatis.generator.plugins.SerializablePlugin" />--><br> <!-- 生成toString --><br> <!-- <plugin type="org.mybatis.generator.plugins.ToStringPlugin" />--><br> <!-- optional,旨在创建class时,对注释进行控制 --><br> <commentGenerator><br> <!-- <property name="suppressDate" value="true"/>--><br> <property name="suppressAllComments" value="true"/><br> </commentGenerator><br> <!--数据库链接URL,用户名、密码 --><br> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"<br> connectionURL="jdbc:mysql://127.0.0.1:3306/springboot?serverTimezone=UTC"<br> userId="root"<br> password="123456"><br> </jdbcConnection><br> <!-- 类型转换 --><br> <javaTypeResolver><br> <!-- 是否使用bigDecimal,<br> false: 把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer(默认)<br> true: 把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal<br> --><br> <property name="forceBigDecimals" value="false"/><br> </javaTypeResolver><br> <!-- 生成模型的包名和位置--><br> <javaModelGenerator targetPackage="com.kx.springboot.pojo" targetProject="src/main/java"><br> <!-- 默认false 是否允许子包 --><br> <property name="enableSubPackages" value="true"/><br> <!-- 默认false 是否对model添加 构造函数 --><br> <property name="constructorBased" value="false"/><br> <!-- 默认false 建立的Model对象是否 不可改变 即生成的Model对象不会有 setter方法,只有构造方法 --><br> <property name="immutable" value="false"/><br> <!-- 默认false 是否对类CHAR类型的列的数据进行trim操作 --><br> <property name="trimStrings" value="true"/><br> </javaModelGenerator><br> <!-- 生成映射文件的包名和位置--><br> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"><br> <property name="enableSubPackages" value="true"/><br> </sqlMapGenerator><br> <!-- 生成DAO的包名和位置--><br> <javaClientGenerator type="XMLMAPPER" targetPackage="com.kx.springboot.dao" targetProject="src/main/java"><br> <property name="enableSubPackages" value="true"/><br> </javaClientGenerator><br> <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名--><br> <!-- <table tableName="risk_model_order" domainObjectName="DSRiskModelOrder" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table><br> <table tableName="tel_bill_record" domainObjectName="DSTelBillRecord" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>--><br> <table tableName="student1"<br> enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false"<br> enableSelectByExample="false" selectByExampleQueryId="false"><br> </table><br> </context><br></generatorConfiguration><br>
注解<br>
@Mapper
需要在每个Mapper接口类上添加,作用扫描dao接口。(每个加麻烦,用下方@MapperScan)
@MapperScan
在SpringBoot启动入口类上添加的,basePackage="选择扫描的包"。
Mapper映射文件存放的位置
a)将Mapper接口和Mapper映射文件存放到src/main/java同一目录下,<br> 还需要在pom文件中手动指定资源文件夹路径resources。<br>
<resources><br> <resource><br> <directory>src/main/java</directory><br> <includes><br> <include>**/*.xml</include><br> </includes><br> <filtering>false</filtering><br> </resource><br> <resource><br> <directory>src/main/resources</directory><br> <includes><br> <include>**/*.properties</include><br> </includes><br> <filtering>false</filtering><br> </resource><br> </resources>
b)将Mapper接口和Mapper映射文件分开存放,Mapper接口类存放到src/main/java目录下,Mapper映射文件存放到resource(类路径下)<br> 还需要在配置文件中指定mapper映射文件<br>
#指定MyBatis映射文件的路径<br>mybatis.mapper-locations=classpath:mapper/*.xml
使用事务
事务只跟什么SQL语句有关?事务只跟DML语句有关系:增删改<br>SQL语言:DML、DQL、DDL、TCL、DCL
操作
在ServiceImpl类上添加@Transactional
例:<br>@Transactional<br> @Override<br> public int updateStudentById(Student student) {<br> int i = studentMapper.updateByPrimaryKeySelective(student);<br> int a = 10 / 0;<br> return i;<br> }<br>
集成RESTFul
风格
传统风格
http://localhost:8080/boot/order?id=1&status=1
RestFul风格<br>
http://localhost:8080/boot/order/1/1<br>
路径
在RESTful架构中,每个网址代表一种资源(resource),所以网址中只能有名词(与数据库的表格名对应)。<br>
@PathVariable:获取url中的数据
Restful API
简单的说即可联网设备利用HTTP协议通过get\post\delete\put\patch来操作具有URL标识的服务器资源,<br>返回统一格式的资源信息,包括JSON、XML、CSV、ProtoBuf等。<br>
HTTP常用的5个动词
GET(SELECT):从服务器取出资源
POST(CREATE):在服务器新建一个资源<br>
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)(整体更新)<br>
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)(局部更新)<br>
DELETE(DALETE):在服务器删除资源
状态码:建议使用HTTP状态码<br>错误处理:返回指定错误
解决请求路径模糊
1、通常在RESTful风格中方法的请求方式会按增删改查的请求方式来区分。<br>
2、修改请求路径。<br>
3、RESTful请求风格要求路径中使用单词为名词。<br>
4、分页、排序等操作,不需要使用斜杠<br>例:/book/orders?page=1&sort=desc一般传的参数不是数据库表的字段<br>
解决请求路径冲突
1、分配不同的请求方式@GetMapping和@PostMappering<br>
2、改变路径位置<br>
原路径:/stu/detail/{id}/{age}<br>
改动后:/stu/{id}/detail/{status}
集成Redis
a)添加操作redis数据类型的依赖<br>
spring-boot-starter-data-redis
b)配置文件中添加redis的配置
#设置redis配置信息<br>spring.redis.host=localhost<br>spring.redis.port=6379
注入RedisTemplate对象
@Autowired<br> private RedisTemplate<Object,Object> redisTemplate;<br><br> @Override<br> public void put(String key, String value) {<br> redisTemplate.opsForValue().set(key,value);<br> }<br><br> @Override<br> public void put1(String key, String value) {<br> RedisSerializer redisSerializer=new StringRedisSerializer();<br> redisTemplate.setKeySerializer(redisSerializer);<br> redisTemplate.setValueSerializer(redisSerializer);<br> redisTemplate.opsForValue().set(key,value);<br> }<br><br> @Override<br> public String get(String key) {<br> return (String) redisTemplate.opsForValue().get(key);<br> }<br>
SpringBoot下使用拦截器Intercept
a)定义一个拦截器
实现HandlerInterceptor接口,重写preHandler方法
public class UserInterceptor implements HandlerInterceptor {<br> @Override<br> public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {<br> System.out.println("———————————进入用户登录拦截器——————————");<br> //编写拦截用户信息<br> //从session中获取用户信息<br> User user = (User) request.getSession().getAttribute("user");<br> //判断用户是否登录<br> if (null == user){<br> //未登录<br> response.sendRedirect(request.getContextPath()+"/user/error");<br> return false;<br> }<br> return true;<br> }<br>}
b)创建一个配置类
类似于在SpringMVC配置文件中使用mvc:interceptors标签<br>
@Configuration //定义此类为配置文件(相当于之前的xml文件)<br>public class InterceptorConfig implements WebMvcConfigurer {<br> //mvc:interceptors<br> @Override<br> public void addInterceptors(InterceptorRegistry registry) {<br> String[] addPathPatterns = {<br> "/user/**"<br> };<br> String[] excludePathPatterns = {<br> "/user/login","/user/out","/user/error"<br> };<br> //mvc:interceptor bean class=""<br> registry.addInterceptor(new UserInterceptor()).addPathPatterns(addPathPatterns).excludePathPatterns(excludePathPatterns);<br>// WebMvcConfigurer.super.addInterceptors(registry);<br> }<br>}<br>
SpringBoot下使用Servlet(了解)
以前的配置
1、创建一个Servlet继承HTTPServlet
2、在web.xml配置文件中使用servlet servlet-mapping<br>
方式
第一种方式:注解方式<br>
@WebServlet、@ServletComponentScan
@WebServlet(urlPatterns = "/myservlet")<br>public class MyServlet extends HttpServlet {<br> @Override<br> protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> resp.getWriter().println("MyServlet One");<br> resp.getWriter().flush();<br> resp.getWriter().close();<br> }<br><br> @Override<br> protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> doGet(req,resp);<br> }<br>}<br>
@SpringBootApplication<br>@ServletComponentScan("com.kx.springboot.servlet")<br>public class Springboot031ServletApplication {<br> public static void main(String[] args) {<br> SpringApplication.run(Springboot031ServletApplication.class, args);<br> }<br>}
第二种方式:通过配置类注册组件<br>
和以前配置一样(创建一个Servlet继承HTTPServlet:)<br>public class MyServlet extends HttpServlet {<br> @Override<br> protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> resp.getWriter().println("MyServlet Two");<br> resp.getWriter().flush();<br> resp.getWriter().close();<br> }<br><br> @Override<br> protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> doGet(req,resp);<br> }<br>}
@Configuration<br>public class ServletConfig {<br> /**<br> * @Bean是个方法级别的注解,主要用在配置类<br> * 相当于<beans><bean id="" class=""></bean></beans><br> * @return<br> */<br> @Bean<br> public ServletRegistrationBean myServletRegistrationBean(){<br> ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new MyServlet(),"/myservlet2");<br> return servletRegistrationBean;<br> }<br>}
SpringBoo下使用过滤器Filter(了解)
第一种方式:注解方式<br>
@WebFilter、@ServletComponentScan
@WebFilter(urlPatterns = "/myfilter")<br>public class MyFilter implements Filter {<br> @Override<br> public void init(FilterConfig filterConfig) throws ServletException {<br> Filter.super.init(filterConfig);<br> }<br><br> @Override<br> public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {<br> System.out.println("————————过滤器————————");<br> filterChain.doFilter(servletRequest,servletResponse);<br> }<br><br> @Override<br> public void destroy() {<br> Filter.super.destroy();<br> }<br>}
@SpringBootApplication<br>@ServletComponentScan(basePackages = "com.kx.springboot.filter")<br>public class Springboot033FilterApplication {<br> public static void main(String[] args) {<br> SpringApplication.run(Springboot033FilterApplication.class, args);<br> }<br>}
第二种方式:注册组件
public class MyFilter implements Filter {<br> @Override<br> public void init(FilterConfig filterConfig) throws ServletException {<br> Filter.super.init(filterConfig);<br> }<br> @Override<br> public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {<br> System.out.println("————————过滤器————————");<br> filterChain.doFilter(servletRequest,servletResponse);<br> }<br> @Override<br> public void destroy() {<br> Filter.super.destroy();<br> }<br>}
@Configuration<br>public class FilterConfig {<br> @Bean<br> public FilterRegistrationBean myFilterRegistrationBean(){<br> //注册过滤器<br> FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean(new MyFilter());<br> //添加过滤路径<br> filterRegistrationBean.addUrlPatterns("/user/*");<br> return filterRegistrationBean;<br> }<br>}
SpringBoot配置字符编码
第一种方式
@WebServlet("/myservlet")<br>public class MyServlet extends HttpServlet {<br> @Override<br> protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> resp.getWriter().println("世界您好 Hello World!");<br> //统一设置浏览器编码格式<br> resp.setContentType("text/html;character=utf-8");<br> resp.getWriter().flush();<br> resp.getWriter().close();<br> }<br> @Override<br> protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> doGet(req,resp);<br> }<br>}
@Configuration<br>public class SystemConfig {<br> @Bean<br> public FilterRegistrationBean myFilterRegistrationBean(){<br> //创建字符编码过滤器<br> CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();<br> //强制设置使用指定字符编码<br> characterEncodingFilter.setForceEncoding(true);<br> //并设置指定字符编码<br> characterEncodingFilter.setEncoding("utf-8");<br> FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean();<br> //设置字符编码过滤器<br> filterRegistrationBean.setFilter(characterEncodingFilter);<br> //设置字符编码过滤器路径<br> filterRegistrationBean.addUrlPatterns("/*");<br> return filterRegistrationBean;<br> }<br>}<br>
@SpringBootApplication<br>@ServletComponentScan("com.kx.springboot.servlet")<br>public class Springboot035EncodingApplication {<br><br> public static void main(String[] args) {<br> SpringApplication.run(Springboot035EncodingApplication.class, args);<br> }<br><br>}
#关闭SpringBoot的http字符编码支持<br>server.servlet.encoding.enabled=false<br>
第二种方式
@WebServlet("/myservlet")<br>public class MyServlet extends HttpServlet {<br> @Override<br> protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> resp.getWriter().println("世界你好 hello");<br> resp.setContentType("text/html;character=utf-8");<br> resp.getWriter().flush();<br> resp.getWriter().close();<br> }<br><br> @Override<br> protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> doGet(req,resp);<br> }<br>}<br>
@SpringBootApplication<br>@ServletComponentScan("com.kx.springboot.servlet")<br>public class Springboot035Encoding2Application {<br><br> public static void main(String[] args) {<br> SpringApplication.run(Springboot035Encoding2Application.class, args);<br> }<br><br>}<br>
#设置请求字符编码<br>server.http.encoding.enabled=true<br>server.servlet.encoding.force=true<br>server.servlet.encoding.charset=utf-8
打包与部署
打war包部署
<!--pom文件中修改打包方式--><br><packaging>war</packaging><br><!--pom文件中build下指定打包的war名称--><br><finalName>SpringBootWar</finalName><br>
启动类变动:<br>@SpringBootApplication<br>public class Springboot037WarApplication extends SpringBootServletInitializer {<br> public static void main(String[] args) {<br> SpringApplication.run(Springboot037WarApplication.class, args);<br> }<br> @Override<br> protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {<br> //构造新资源<br> return builder.sources(Springboot037WarApplication.class);<br>// return super.configure(builder);<br> }<br>}
在Tomcat的webapps目录下放上war包
启动Tomcat的bin目录下startup.bat
注:1、SpringBoot打war包,部署到tomcat中,之前在application.properties设置的端口号和上下文失效。<br> 2、如果前端为jsp页面需要配置spring.mvc.view.prefix=/和spring.mvc.view.suffix=.jsp
打jar包
<finalName>SpringBootJar</finalName><br> <resources><br> <resource><br> <directory>src/main/webapp</directory><br> <targetPath>META-INF/resources</targetPath><br> <includes><br> <include>*.*</include><br> </includes><br> </resource><br> <resource><br> <directory>src/main/resources</directory><br> <includes><br> <include>**/*.*</include><br> </includes><br> </resource><br> </resources>
pom文件build下plugins中打包插件加<version>1.4.2.RELEASE</version>
application.properties设置的端口号和上下文有效
java -jar xxx.jar
集成logback
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?><br><!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 --><br><!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true --><br><!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 --><br><!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --><br><configuration scan="true" scanPeriod="10 seconds"><br> <contextName>logback</contextName><br><br> <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 --><br><!-- <property name="log.path" value="/var/log/myapp"/>--><br> <property name="log.path" value="D:/IdeaProject/log"/><br><br> <!--0. 日志格式和颜色渲染 --><br> <!-- 彩色日志依赖的渲染类 --><br> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /><br> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /><br> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /><br> <!-- 彩色日志格式 --><br> <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/><br><br> <!--1. 输出到控制台--><br> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><br> <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--><br> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"><br> <level>debug</level><br> </filter><br> <encoder><br> <Pattern>${CONSOLE_LOG_PATTERN}</Pattern><br> <!-- 设置字符集 --><br> <charset>UTF-8</charset><br> </encoder><br> </appender><br><br> <!--2. 输出到文档--><br> <!-- 2.1 level为 DEBUG 日志,时间滚动输出 --><br> <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><br> <!-- 正在记录的日志文档的路径及文档名 --><br> <file>${log.path}/debug.log</file><br> <!--日志文档输出格式--><br> <encoder><br> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><br> <charset>UTF-8</charset> <!-- 设置字符集 --><br> </encoder><br> <!-- 日志记录器的滚动策略,按日期,按大小记录 --><br> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><br> <!-- 日志归档 --><br> <fileNamePattern>${log.path}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern><br> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><br> <maxFileSize>100MB</maxFileSize><br> </timeBasedFileNamingAndTriggeringPolicy><br> <!--日志文档保留天数--><br> <maxHistory>15</maxHistory><br> </rollingPolicy><br> <!-- 此日志文档只记录debug级别的 --><br> <filter class="ch.qos.logback.classic.filter.LevelFilter"><br> <level>debug</level><br> <onMatch>ACCEPT</onMatch><br> <onMismatch>DENY</onMismatch><br> </filter><br> </appender><br><br> <!-- 2.2 level为 INFO 日志,时间滚动输出 --><br> <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><br> <!-- 正在记录的日志文档的路径及文档名 --><br> <file>${log.path}/info.log</file><br> <!--日志文档输出格式--><br> <encoder><br> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><br> <charset>UTF-8</charset><br> </encoder><br> <!-- 日志记录器的滚动策略,按日期,按大小记录 --><br> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><br> <!-- 每天日志归档路径以及格式 --><br> <fileNamePattern>${log.path}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern><br> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><br> <maxFileSize>100MB</maxFileSize><br> </timeBasedFileNamingAndTriggeringPolicy><br> <!--日志文档保留天数--><br> <maxHistory>15</maxHistory><br> </rollingPolicy><br> <!-- 此日志文档只记录info级别的 --><br> <filter class="ch.qos.logback.classic.filter.LevelFilter"><br> <level>info</level><br> <onMatch>ACCEPT</onMatch><br> <onMismatch>DENY</onMismatch><br> </filter><br> </appender><br><br> <!-- 2.3 level为 WARN 日志,时间滚动输出 --><br> <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><br> <!-- 正在记录的日志文档的路径及文档名 --><br> <file>${log.path}/warn.log</file><br> <!--日志文档输出格式--><br> <encoder><br> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><br> <charset>UTF-8</charset> <!-- 此处设置字符集 --><br> </encoder><br> <!-- 日志记录器的滚动策略,按日期,按大小记录 --><br> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><br> <fileNamePattern>${log.path}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern><br> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><br> <maxFileSize>100MB</maxFileSize><br> </timeBasedFileNamingAndTriggeringPolicy><br> <!--日志文档保留天数--><br> <maxHistory>15</maxHistory><br> </rollingPolicy><br> <!-- 此日志文档只记录warn级别的 --><br> <filter class="ch.qos.logback.classic.filter.LevelFilter"><br> <level>warn</level><br> <onMatch>ACCEPT</onMatch><br> <onMismatch>DENY</onMismatch><br> </filter><br> </appender><br><br> <!-- 2.4 level为 ERROR 日志,时间滚动输出 --><br> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><br> <!-- 正在记录的日志文档的路径及文档名 --><br> <file>${log.path}/error.log</file><br> <!--日志文档输出格式--><br> <encoder><br> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><br> <charset>UTF-8</charset> <!-- 此处设置字符集 --><br> </encoder><br> <!-- 日志记录器的滚动策略,按日期,按大小记录 --><br> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><br> <fileNamePattern>${log.path}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern><br> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><br> <maxFileSize>100MB</maxFileSize><br> </timeBasedFileNamingAndTriggeringPolicy><br> <!--日志文档保留天数--><br> <maxHistory>15</maxHistory><br> </rollingPolicy><br> <!-- 此日志文档只记录ERROR级别的 --><br> <filter class="ch.qos.logback.classic.filter.LevelFilter"><br> <level>ERROR</level><br> <onMatch>ACCEPT</onMatch><br> <onMismatch>DENY</onMismatch><br> </filter><br> </appender><br><br> <!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件 --><br> <appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><br> <!-- 正在记录的日志文档的路径及文档名 --><br> <file>${log.path}/all.log</file><br> <!--日志文档输出格式--><br> <encoder><br> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><br> <charset>UTF-8</charset> <!-- 此处设置字符集 --><br> </encoder><br> <!-- 日志记录器的滚动策略,按日期,按大小记录 --><br> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><br> <fileNamePattern>${log.path}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern><br> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><br> <maxFileSize>100MB</maxFileSize><br> </timeBasedFileNamingAndTriggeringPolicy><br> <!--日志文档保留天数--><br> <maxHistory>15</maxHistory><br> </rollingPolicy><br> <!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 --><br> <filter class="ch.qos.logback.classic.filter.LevelFilter"><br> <level>DEBUG</level><br> <onMatch>DENY</onMatch><br> <onMismatch>ACCEPT</onMismatch><br> </filter><br> </appender><br><br> <!--<br> <logger>用来设置某一个包或者具体的某一个类的日志打印级别、<br> 以及指定<appender>。<logger>仅有一个name属性,<br> 一个可选的level和一个可选的addtivity属性。<br> name:用来指定受此logger约束的某一个包或者具体的某一个类。<br> level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,<br> 还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。<br> 如果未设置此属性,那么当前logger将会继承上级的级别。<br> addtivity:是否向上级logger传递打印信息。默认是true。<br> <logger name="org.springframework.web" level="info"/><br> <logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/><br> --><br><br> <!--<br> 使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:<br> 第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息<br> 第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:<br> 【logging.level.org.mybatis=debug logging.level.dao=debug】<br> --><br><br> <!--<br> root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性<br> level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,<br> 不能设置为INHERITED或者同义词NULL。默认是DEBUG<br> 可以包含零个或多个元素,标识这个appender将会添加到这个logger。<br> --><br><br><br><br> <!-- 4 最终的策略:<br> 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)--><br> <!--多个或全部定义--><br> <root level="info"><br> <appender-ref ref="CONSOLE" /><br><!-- <appender-ref ref="DEBUG_FILE" />--><br> <appender-ref ref="INFO_FILE" /><br><!-- <appender-ref ref="WARN_FILE" />--><br><!-- <appender-ref ref="ERROR_FILE" />--><br><!-- <appender-ref ref="ALL_FILE" />--><br> </root><br> <!--单个定义--><br> <logger name="com.kx.springboot" level="debug"/><br><!-- <springProfile name="dev">--><br><!-- <root level="info">--><br><!-- <appender-ref ref="CONSOLE" />--><br><!-- <appender-ref ref="DEBUG_FILE" />--><br><!-- <appender-ref ref="INFO_FILE" />--><br><!-- <appender-ref ref="WARN_FILE" />--><br><!-- <appender-ref ref="ERROR_FILE" />--><br><!-- <appender-ref ref="ALL_FILE" />--><br><!-- </root>--><br><!-- <logger name="com.kx.springboot" level="debug"/> <!– 开发环境, 指定某包日志为debug级 –>--><br><!-- </springProfile>--><br><br><!-- <springProfile name="test">--><br><!-- <root level="info">--><br><!-- <appender-ref ref="CONSOLE" />--><br><!-- <appender-ref ref="DEBUG_FILE" />--><br><!-- <appender-ref ref="INFO_FILE" />--><br><!-- <appender-ref ref="WARN_FILE" />--><br><!-- <appender-ref ref="ERROR_FILE" />--><br><!-- <appender-ref ref="ALL_FILE" />--><br><!-- </root>--><br><!-- <logger name="com.kx.springboot" level="info"/> <!– 测试环境, 指定某包日志为info级 –>--><br><!-- </springProfile>--><br><br><!-- <springProfile name="pro">--><br><!-- <root level="info">--><br><!-- <!– 生产环境最好不配置console写文件 –>--><br><!-- <appender-ref ref="DEBUG_FILE" />--><br><!-- <appender-ref ref="INFO_FILE" />--><br><!-- <appender-ref ref="WARN_FILE" />--><br><!-- <appender-ref ref="ERROR_FILE" />--><br><!-- <appender-ref ref="ALL_FILE" />--><br><!-- </root>--><br><!-- <logger name="com.kx.springboot" level="warn"/> <!– 生产环境, 指定某包日志为warn级 –>--><br><!-- <logger name="com.kx.springboot.Springboot039LogbackApplication" level="info"/> <!– 特定某个类打印info日志, 比如application启动成功后的提示语 –>--><br><!-- </springProfile>--><br><br></configuration>
添加lombok依赖<br>
@Controller<br>@Slf4j<br>public class StudentController {<br> @Autowired<br> private StudentService studentService;<br><br> @RequestMapping("/student/count")<br> public @ResponseBody String studentCount() {<br> log.info("查询当前学生总人数");<br> Integer stuCount = studentService.queryStudentCount();<br> return "学生总人数为:" + stuCount;<br> }<br>}
集成Thymeleaf
Thymeleaf<br>
简介
Thymeleaf是一个跟Velocity、FreeMarker类似的模板引擎,它可以完全代替JSP。<br>特点:<br>1、Thymeleaf在有无网络的情况下都能运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。<br>2、Thymeleaf开箱即用的特性。他提供标准和Spring标准两种方言,可直接套用模板实现JSTL、OGNL表达式效果,避免每天套模板、改jstl、改标签的困扰。同时也能自己拓展方言。<br>3、Thymeleaf提供Spring标准方言和一个与SpringMVC完美集成的可选模块、可以快速实现表单绑定、属性编辑器、国际化等功能。<br>
表达式<br>
1、标准变量表达式(推荐):${...}<br>
控制器:mo.addAttribute("city","上海");<br>表达式:<h1 th:text="${city}">hello</h1>(使用city变量的内容替换标记文本)<br>
2、选择变量表达式(不推荐):*{...}<br>
意思是首先选择一个对象(通过属性th:object描述),<br>然后在选择(标记)的范围内,处理对象的属性。
例:<br>*{}必须使用th:object属性来绑定此对象,在div子标签中用*来代替绑定的对象${stu}<br>控制器:<br> Student stu=new Student();<br> stu.setStuName("张飞");<br> stu.setStuId("s11");<br> stu.setGrade(67);<br> mo.addAttribute("stu",stu);<br>表达式:<br> <h1 th:object="${stu}"><br> 用户姓名:<span th:text="*{stuName}"></span><br> 用户编号:<span th:text="*{stuId}"></span><br> </h1><br>
3、消息表达式:#{...}<br>
4、URL链接表达式:@{...}<br>
导入文件<br>
传统写法:<script type="text/javascript" src="js/jquery-3.5.1.min.js"></script><br>
路径表达式写法:<script type="text/javascript" th:src="@{/js/jquery-3.5.1.min.js}"></script><br>注:@后面加上斜杠,以表示相对路径
导入图片<br>
控制器:<br> Course cs=new Course();<br> cs.setCourseId("cs12");<br> cs.setCourseName("cpp");<br> mp.addAttribute("course",cs);<br>表达式:<br><img src="1.jpg" th:src="@{images/getImg{courseId=${course.courseId}}}"><br>执行结果:<img src="images/getImg?courseId=cs12">
路径表达式<br>
a、无参数<br>
绝对路径(不推荐,往往实际中不写绝对路径):<br> 传统写法:<a href="http://www.baidu.com">百度一下</a><br> 路径表达式:<a th:href="@{http://www.baidu.com}">百度一下</a><br> 传统写法:<a href="http://localhost:8080/user">跳转至/user</a><br> 路径表达式:<a th:href="http://localhost:8080/user}">跳转至/user</a><br>
相对路径(推荐):<br> <a th :href="@{/user}">跳转至/user</a><br>
b、有参数
绝对路径(不推荐):<br> 传统写法:<a href="http://localhost:8080/user?username='zhangsan'">跳转 至/user</a><br> 路径表达式:<a th:href="@{http://localhost:8080/user?username='zhangsan'}">跳转至/user</a>
相对路径(推荐):<br> <a th :href="@{/user?username='zhangsan'}">带参数跳转至/user</a><br> //后台获取动态参数(推荐)<br> <a th :href="@{'/user?username='+${username}}">动态参数值跳转</a><br> //后台获取多个动态参数(推荐)<br> <a th :href="@{'/user?id=’+${id}+'&username='+${username}}">动态参数值跳转</a><br> //后台获取多个动态参数(极力推荐)<br> <a th :href="@{/user(id=${id},username=${username})}">动态参数值跳转</a><br> //RestFul风格不支持小括号(推荐)<br> <a th :href="@{'/user/'+${id}+'/'+${username}}">RestFul风格动态参数值跳转</a><br>
5、代码段表达式:~{...}
常用属性<br>
th标签的基本含义:替换(th),解析:需要从后台取值需要加上th。
格式:th:需替换的部分="替换的值";
常用th标签<br>
替换id: th:id<br> 替换name:th:name<br> 属性赋值 :th:value<br> 替换文本 :th:text<br> textarea :th:utext<br> 链接地址 :th:href<br> 图片地址 :th:src<br> 代入对象 :th:object<br> 代入集合 :th:each
<!--<br> user:当前循环的对象变量名称(随意)<br> userStat:当前循环对象状态的变量(可省略,默认就是对象变量名称+Stat)<br> ${userList}:当前循环的集合<br>--><br><div th:each="user,userStat:${userList}"><br> <span th:text="${userStat.index}"></span><br> <span th:text="${userStat.count}"></span><br> <span th:text="${user.id}"></span><br> <span th:text="${user.nick}"></span><br> <span th:text="${user.phone}"></span><br> <span th:text="${user.address}"></span><br></div><br> 条件代入 :th:if<br> 条件代入 :th:unless<br><h2>th:if用法(th:unless与之相反)</h2><br><div th:if="${sex eq 1}"><br> 男<br></div><br><div th:if="${sex eq 0}"><br> 女<br></div><br> 选择结构 :th:switch<br> 选择case :th:case<br>//*通配符表示无此产品<br><div th:switch="${productType}"><br> <span th:case="0">产品0</span><br> <span th:case="1">产品1</span><br> <span th:case="*">无此产品</span><br></div><br> 内敛表达式:th:inline(三种取值(text文本、javascript脚本、none))<br><h2>内敛文本:th:inline="text",通常在div标签中写</h2><br><div th:inline="text"><br> 数据:[[${data}]]<br></div><br> //注意:JS中获取后台传过来的值得用th:inline<br><h2>内敛脚本(在js获取后台传过来的值):th:inline="javascript"</h2><br><script type="text/javascript" th:inline="javascript"><br> function showData() {<br> // alter(${data}) //无效<br> alert([[${data}]])<br> }<br></script><br><button type="button" onclick="showData()">showData</button><br> 设置样式 :th:style<br> th:onclick<br>
常量与运算符<br>
常量<br>
一般称之为字面量<br> 文本:'one text,'another one!',...<br> 数值:0,2,2.0<br> 布尔类型:true、false<br> null<br>
运算符
1、算术运算:+,-,*,/,%<br>
控制器:mp.addAttribute("num",50);<br> html:<br> <h1>hello<span th:text="${num}*2">spring</span></h1><br> <h1>hello<span th:text="${num}/2">spring</span></h1><br> <h1>hello<span th:text="${num}%2">spring</span></h1><br>
2、布尔操作:and,or二元操作符<br> !,not非(一元操作符)
3、关系操作符:>,<,>=,<=(gt,it,ge,le),==,!=(eq,ne)
控制器:mp.addAttrbute("grade",80);<br>html:<h1 th:utext="${course.courseGrade}>3?'<u>主课</u>':一般"></h1>
4、条件运算<br>
<span th:text="${grade} ge 90?'good':${grade}">spring</span>
配置:关闭自动缓存spring.thymeleaf.cache=false<br>引入th名称空间:<html xmlns:th="http://www.thymeleaf.org"><br>
循环遍历array、list、map
if、switch条件判断<br>
inline内敛表达式<br>
a、内敛文本:<br><div th:inline="text"><br> 数据:[[${data}]]<br></div><br>b、内敛脚本:<br><script type="text/javascript" th:inline="javascript"><br><br>splice字符拼接,例:<br><span th:text="|共${totalRows}条${totalPage}页,当前第${currentPage}页,首页 上一页 下一页 尾页|"></span>
literal字面量<br>
operatal数学运算<br>
基本表达式对象(内置功能对象前加#)<br>
//获取协议名称<br>let scheme = [[${#request.getScheme()}]];<br>//获取服务器名称<br>let serverName = [[${#request.getServerName()}]];<br>//获取服务器端口号<br>let serverPort = [[${#request.getServerPort()}]];<br>//获取上下文路径<br>let contextPath = [[${#request.getContextPath()}]];<br>let allPath = scheme+"://"+serverName+":"+serverPort+contextPath;<br>// alert(allPath)<br>let requestUrl = [[${#httpServletRequest.requestURL}]];<br>let queryString = [[${#httpServletRequest.queryString}]];<br>let requestAddress = requestUrl + "?" + queryString;<br>alert(requestAddress)
功能表达式对象
#dates<br>#calendars<br>#numbers<br>#strings:contains,startWith,appending等<br>#objects<br>#bools<br>#arrays<br>#lists<br>#maps<br>#aggregates<br>
0 条评论
下一页