package com.cooler.config;
import com.cooler.vo.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author CoolEr
* @create 2022/3/21
*/
@Configuration
public class SpringConfig {
/**
* 创建方法,方法的返回值是对象。
* 方法的返回值对象就注入到容器中
*/
@Bean
// @Bean(name = "zsStudent")
public Student createStudent(){
Student s1 = new Student();
s1.setName("张三");
s1.setAge(20);
s1.setSex("男");
return s1;
}
}
测试:
import com.cooler.config.SpringConfig;
import com.cooler.vo.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author CoolEr
* @create 2022/3/21
*/
public class MyTest {
@Test
public void test01(){
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
Student student = (Student) ctx.getBean("createStudent");
System.out.println(student);
}
}
@Configuration
@ImportResource(value ={ "classpath:applicationContext.xml","classpath:beans.xml"})
public class SpringConfig {
}
@Configuration
@ImportResource(value ={ "classpath:applicationContext.xml","classpath:beans.xml"})
@PropertySource(value = "classpath:config.properties")
@ComponentScan(basePackages = "com.cooler.vo")
public class SpringConfig {
}
以上两个注解使用具体代码
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="myCat" class="com.cooler.vo.Cat">
<property name="name" value="tom猫"/>
<property name="age" value="2" />
<property name="cardId" value="uw532423422"/>
bean>
beans>
@Configuration
@ImportResource(value ={ "classpath:applicationContext.xml","classpath:beans.xml"})
@PropertySource(value = "classpath:config.properties")
@ComponentScan(basePackages = "com.cooler.vo")
public class SpringConfig {
/**
* 创建方法,方法的返回值是对象。 在方法的上面加入@Bean
* 方法的返回值对象就注入到容器中。
*
* @Bean: 把对象注入到spring容器中。 作用相当于
*
* 位置:方法的上面
*
* 说明:@Bean,不指定对象的名称,默认是方法名是 id
*
*/
@Bean
public Student createStudent(){
Student s1 = new Student();
s1.setName("张三");
s1.setAge(26);
s1.setSex("男");
return s1;
}
/***
* 指定对象在容器中的名称(指定的id属性)
* @Bean的name属性,指定对象的名称(id)
*/
@Bean(name = "lisiStudent")
public Student makeStudent(){
Student s2 = new Student();
s2.setName("李四");
s2.setAge(22);
s2.setSex("男");
return s2;
}
tiger.name=\u4E1C\u5317\u8001\u864E
tiger.age=3
@Component("tiger")
public class Tiger {
@Value("${tiger.name}")
private String name;
@Value("${tiger.age}")
private Integer age;
@Override
public String toString() {
return "Tiger{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
SpringBoot是Spring中的一个成员, 可以简化Spring,SpringMVC的使用。 他的核心还是IOC容器。
特点:
Create stand-alone Spring applications——创建spring应用
Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)——内嵌的tomcat, jetty , Undertow
Provide opinionated ‘starter’ dependencies to simplify your build configuration——提供了starter起步依赖,简化应用的配置。
Automatically configure Spring and 3rd party libraries whenever possible——尽可能去配置spring和第三方库。叫做自动配置(就是把spring中的,第三方库中的对象都创建好,放到容器中, 开发人员可以直接使用)
Provide production-ready features such as metrics, health checks, and externalized configuration——提供了健康检查, 统计,外部化配置
Absolutely no code generation and no requirement for XML configuration——不用生成代码, 不用使用xml做配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>005-springboot-mvcartifactId>
<version>1.0.0version>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
@Controller
public class HelloSpringBoot {
@RequestMapping("/hello")
@ResponseBody
public String helloSpringBoot(){
return "欢迎使用SpringBoot框架";
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
有两种格式的配置文件的情况下,默认使用properties
例1:application.properties设置 端口和上下文
#设置端口号
server.port=8082
#设置访问应用上下文路径, contextpath
server.servlet.context-path=/myboot
server:
port: 8083
servlet:
context-path: /myboot2
#在主application.yml中激活使用的test环境
spring:
profiles:
active: test
@Controller
public class HelloController {
@Value("${server.port}")
private Integer port;
@Value("${server.servlet.context-path}")
private String contextPath;
@Value("${school.name}")
private String name;
@Value("${site}")
private String site;
@Resource
private SchoolInfo info;
@RequestMapping("/data")
@ResponseBody
public String queryData(){
return name+",site="+site+", 项目的访问地址="+contextPath+",使用的端口="+port;
}
@RequestMapping("/info")
@ResponseBody
public String queryInfo(){
return "SchoolInfo对象=="+info.toString();
}
}
#port
server.port=8082
#context-path
server.servlet.context-path=/myboot
school.name=Cooler
school.website=www.cooler.com
school.address=江西省
site=www.cooler.com
@Component
@ConfigurationProperties(prefix = "school")
public class SchoolInfo {
private String name;
private String website;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "SchoolInfo{" +
"name='" + name + '\'' +
", website='" + website + '\'' +
", address='" + address + '\'' +
'}';
}
}
SpringBoot不推荐使用jsp ,而是使用模板技术代替jsp
步骤:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>009-springboot-jspartifactId>
<version>0.0.1-SNAPSHOTversion>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-jasperartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<resources>
<resource>
<directory>src/main/webappdirectory>
<targetPath>META-INF/resourcestargetPath>
<includes>
<include>**/*.*include>
includes>
resource>
resources>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
创建一个存放jsp的目录,一般叫做webapp—— index.jsp
需要在pom.xml指定jsp文件编译后的存放目录。
创建Controller, 访问jsp
@Controller
public class JspController {
/*public String doJsp(HttpServletRequest request){
request.setAttribute("data","SpringBoot使用Jsp");
//视图的逻辑名称
return "index";
}*/
@RequestMapping("/myjsp")
public String doJsp(Model model){
//把数据放入到request作用域
model.addAttribute("data","SpringBoot使用Jsp");
//request.setAttribute("data","SpringBoot使用Jsp");
//视图的逻辑名称
return "index";
}
}
#配置端口号
server.port=9090
server.servlet.context-path=/myboot
#配置视图解析器
#/ = src/main/webapp
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp
@SpringBootApplication
public class Application {
public static void main(String[] args) {
//获取容器对象
//ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
ApplicationContext ctx = SpringApplication.run(Application.class, args);
//从容器者获取对象
UserService userService = (UserService) ctx.getBean("userService");
userService.sayHello("李四");
}
}
@SpringBootApplication
public class Application implements CommandLineRunner {
@Resource
private HelloService helloService;
public static void main(String[] args) {
System.out.println("准备创建容器对象");
//创建容器对象
SpringApplication.run(Application.class, args);
System.out.println("容器对象创建之后");
}
@Override
public void run(String... args) throws Exception {
String str = helloService.sayHello("lisi");
System.out.println("调用容器中的对象="+str);
//可做自定义的操作,比如读取文件, 数据库等等
System.out.println("在容器对象创建好,执行的方法");
}
}
拦截器是SpringMVC中一种对象,能拦截对Controller的请求。
框架中有系统的拦截器, 还可以自定义拦截器,实现对请求预先处理。
实现自定义拦截器步骤:
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
<mvc:interceptors>
<mvc:interceptor>
<bean class="拦截器类全限定名称"/>
mvc:interceptor>
mvc:interceptors>
/**
* 自定义拦截器
*/
public class LoginInterceptor implements HandlerInterceptor {
/**
*
* @param request
* @param response
* @param handler 被拦截器的控制器对象
* @return boolean
* true: 请求能被Controller处理
* false: 请求被截断
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println("执行了LoginInterceptor的preHandle");
return true;
}
}
@Configuration
public class MyAppConfig implements WebMvcConfigurer {
//添加拦截器对象, 注入到容器中
@Override
public void addInterceptors(InterceptorRegistry registry) {
//创建拦截器对象
HandlerInterceptor interceptor = new LoginInterceptor();
//指定拦截的请求uri地址
String path []= {"/user/**"};
//指定不拦截的地址
String excludePath [] = {"/user/login"};
registry.addInterceptor(interceptor)
.addPathPatterns(path)
.excludePathPatterns(excludePath);
}
}
使用步骤:
//创建Servlet类
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//使用HttpServletResponse输出数据,应答结果
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("===执行的是Servlet==");
out.flush();
out.close();
}
}
@Configuration
public class WebApplictionConfig {
//定义方法, 注册Servlet对象
@Bean
public ServletRegistrationBean servletRegistrationBean(){
//public ServletRegistrationBean(T servlet, String... urlMappings)
//第一个参数是 Servlet对象, 第二个是url地址
//这里是有参构造
//ServletRegistrationBean bean =
//new ServletRegistrationBean( new MyServlet(),"/myservlet");
//这里是无参构造
ServletRegistrationBean bean = new ServletRegistrationBean();
bean.setServlet( new MyServlet());
bean.addUrlMappings("/login","/test"); //
return bean;
}
}
Filter是Servlet规范中的过滤器,可以处理请求, 对请求的参数, 属性进行调整。 常常在过滤器中处理字符编码
在框架中使用过滤器:
// 自定义过滤器
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("执行了MyFilter,doFilter ");
filterChain.doFilter(servletRequest,servletResponse);
}
}
@Configuration
public class WebApplicationConfig {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter( new MyFilter());
bean.addUrlPatterns("/user/*");
return bean;
}
}
CharacterEncodingFilter : 解决post请求中乱码的问题
在SpringMVC框架, 在web.xml 注册过滤器,配置属性。
第一种方式:
使用步骤:
@Configuration
public class WebSystemConfig {
//注册Servlet
@Bean
public ServletRegistrationBean servletRegistrationBean(){
MyServlet myServlet = new MyServlet();
ServletRegistrationBean reg = new ServletRegistrationBean(myServlet,"/myservlet");
return reg;
}
//注册Filter
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean reg = new FilterRegistrationBean();
//使用框架中的过滤器类
CharacterEncodingFilter filter = new CharacterEncodingFilter();
//指定使用的编码方式
filter.setEncoding("utf-8");
//指定request , response都使用encoding的值
filter.setForceEncoding(true);
reg.setFilter(filter);
//指定 过滤的url地址
reg.addUrlPatterns("/*");
return reg;
}
}
#SpringBoot中默认已经配置了CharacterEncodingFilter。 编码默认ISO-8859-1
#设置enabled=false 作用是关闭系统中配置好的过滤器, 使用自定义的CharacterEncodingFilter
server.servlet.encoding.enabled=false
第二种方式
server.port=9001
server.servlet.context-path=/myboot
#让系统的CharacterEncdoingFilter生效
server.servlet.encoding.enabled=true
#指定使用的编码方式
server.servlet.encoding.charset=utf-8
#强制request,response都使用charset属性的值
server.servlet.encoding.force=true
@Mapper:放在dao接口的上面, 每个接口都需要使用这个注解。
使用步骤:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>017-springboot-mapperartifactId>
<version>0.0.1-SNAPSHOTversion>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.4version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
includes>
resource>
resources>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
public class Student {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
/**
* @Mapper:告诉MyBatis这是dao接口,创建此接口的代理对象。
* 位置:在类的上面
*/
@Mapper
public interface StudentDao {
Student selectById(@Param("stuId") Integer id);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cooler.dao.StudentDao">
<select id="selectById" resultType="com.cooler.model.Student">
select id,name,age from student where id=#{stuId}
select>
mapper>
public interface StudentService {
Student queryStudent(Integer id);
}
@Service
public class StudentServiceImpl implements StudentService {
@Resource
private StudentDao studentDao;
@Override
public Student queryStudent(Integer id) {
Student student = studentDao.selectById(id);
return student;
}
}
@Controller
public class StudentController {
@Resource
private StudentService studentService;
@RequestMapping("/student/query")
@ResponseBody
public String queryStudent(Integer id){
Student student = studentService.queryStudent(id);
return student.toString();
}
}
server.port=9001
server.servlet.context-path=/orm
#连接数据库:mysql驱动新版的驱动类
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
}
}
/**
* @MapperScan: 找到Dao接口和Mapper文件
* basePackages:Dao接口所在的包名
*/
@SpringBootApplication
@MapperScan(basePackages = {"com.cooler.dao","com.cooler.mapper"})
public class Application {
}
mapper 文件放在 resources 目录下, java 代码放在 src/main/java。
#指定mapper文件的位置
mybatis.mapper-locations=classpath:mapper/*.xml
#指定mybatis的日志
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.*include>
includes>
resource>
resources>
Spring框架中的事务:
声明式事务: 在xml配置文件或者使用注解说明事务控制的内容
事务处理方式:
SpringBoot中使用事务: 上面的两种方式都可以。
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>019-springboot-transactionalartifactId>
<version>0.0.1-SNAPSHOTversion>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.4version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.*include>
includes>
resource>
resources>
<plugins>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.3.6version>
<configuration>
<configurationFile>GeneratorMapper.xmlconfigurationFile>
<verbose>trueverbose>
<overwrite>trueoverwrite>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<classPathEntry location="D:\tools\mysql-connector-java-8.0.22.jar"/>
<context id="tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="true" />
commentGenerator>
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/springdb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"
userId="root"
password="123">
jdbcConnection>
<javaModelGenerator targetPackage="com.cooler.model"
targetProject="D:\course\25-SpringBoot\springboot-prj\019-springboot-transactional\src\main\java">
<property name="enableSubPackages" value="false" />
<property name="trimStrings" value="false" />
javaModelGenerator>
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<property name="enableSubPackages" value="false" />
sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.cooler.dao" targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
javaClientGenerator>
<table tableName="student" domainObjectName="Student"
enableCountByExample="false"
enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
selectByExampleQueryId="false"/>
context>
generatorConfiguration>
#设置端口
server.port=9002
#context-path
server.servlet.context-path=/mytrans
#配置数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123
#配置mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
#配置日志
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
@Service
public class StudentServiceImpl implements StudentService {
@Resource
private StudentMapper studentDao;
/**
* @Transactional: 表示方法的有事务支持
* 默认:使用库的隔离级别, REQUIRED 传播行为; 超时时间 -1
* 抛出运行时异常,回滚事务
*/
@Transactional
@Override
public int addStudent(Student student) {
System.out.println("业务方法addStudent");
int rows = studentDao.insert(student);
System.out.println("执行sql语句");
//抛出一个运行时异常, 目的是回滚事务
//int m = 10 / 0 ;
return rows;
}
}
@Controller
public class StudentController {
@Resource
private StudentService service;
@RequestMapping("/addStudent")
@ResponseBody
public String addStudent(String name,Integer age){
Student s1 = new Student();
s1.setName(name);
s1.setAge(age);
int rows = service.addStudent(s1);
return "添加学生:"+rows;
}
}
/**
* @EnableTransactionManagement: 启用事务管理器
*/
@SpringBootApplication
@EnableTransactionManagement
@MapperScan(basePackages = "com.cooler.dao")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
RESTful架构风格
表现层状态转移:
URL加上请求方式必须唯一
用REST表示资源和对资源的操作。
比如我们要访问一个 http 接口:http://localhost:8080/boot/order?id=1021&status=1
采用 RESTFul 风格则 http 地址为:http://localhost:8080/boot/order/1021/1
对资源:
使用http中的动作(请求方式), 表示对资源的操作(CURD)
处理单个资源: 用他的单数方式
http://localhost:8080/myboot/student/1001
http://localhost:8080/myboot/student/1001/1
处理多个资源:使用复数形式
http://localhost:8080/myboot/students/1001/1002
http://localhost:8080/myboot/student
在post请求中传递数据
删除1的数据
需要的分页, 排序等参数,依然放在 url的后面, 例如
http://localhost:8080/myboot/students?page=1&pageSize=20
@RestController
public class MyRestController {
// 学习注解的使用
//查询id=1001的学生
/**
* @PathVariable(路径变量) : 获取url中的数据
* 属性: value : 路径变量名
* 位置: 放在控制器方法的形参前面
*
*
* {stuId}:定义路径变量, stuId自定义名称
*/
@GetMapping("/student/{stuId}")
public String queryStudent(@PathVariable("stuId") Integer studentId){
return "查询学生studentId="+studentId;
}
/***
* 创建资源 Post请求方式
* http://localhost:8080/myboot/student/zhangsan/20
*/
@PostMapping("/student/{name}/{age}")
public String createStudent(@PathVariable("name") String name,
@PathVariable("age") Integer age){
return "创建资源 student: name="+name+"#age="+age;
}
/**
* 更新资源
*
* 当路径变量名称和 形参名一样, @PathVariable中的value可以省略
*/
@PutMapping("/student/{id}/{age}")
public String modifyStudent(@PathVariable Integer id,
@PathVariable Integer age){
return "更新资源, 执行put请求方式: id="+id+"#age="+age;
}
/**
* 删除资源
*/
@DeleteMapping("/student/{id}")
public String removeStudentById(@PathVariable Integer id){
return "删除资源,执行delete, id="+id;
}
}
在SpringMVC中 有一个过滤器, 支持post请求转为put ,delete
过滤器:org.springframework.web.filter.HiddenHttpMethodFilter
作用:把请求中的post请求转为 put , delete
实现步骤:
server.port=9001
server.servlet.context-path=/myredis
#启用支持put,delete
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=123
<form action="student/test" method="post">
<input type="hidden" name="_method" value="put">
<input type="submit" value="测试请求方式">
form>
需求:完善根据学生 id 查询学生的功能,先从 redis 缓存中查找,如果找不到,再从数据库中查找,然后放到 redis 缓存中
步骤:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>021-springboot-redisartifactId>
<version>0.0.1-SNAPSHOTversion>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
server.port=9001
server.servlet.context-path=/myredis
#指定Redis
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=123
@RestController
public class RedisController {
/**
* 注入RedisTemplate
*
* RedisTemplate 泛型
* RedisTemplate
* RedisTemplate
@Resource
private RedisTemplate redisTemplate;
@Resource
private StringRedisTemplate stringRedisTemplate;
// 添加数据到redis
@PostMapping("/redis/addstring")
public String addToRedis(String name, String value){
// 操作Redis中string类型的数据, 先获取ValueOperations对象
ValueOperations valueOperations = redisTemplate.opsForValue();
//添加数据到redis
valueOperations.set("myname","lisi");
return "向redis添加string类型的数据";
}
// 从redis获取数据
@GetMapping("/redis/getk")
public String getData(String k){
ValueOperations valueOperations = redisTemplate.opsForValue();
Object v = valueOperations.get(k);
return "key是"+k+",他的值是:"+v;
}
@PostMapping("/redis/{k}/{v}")
public String addStringKV(@PathVariable String k,
@PathVariable String v){
// 使用StringRedisTemplate对象
stringRedisTemplate.opsForValue().set(k,v);
return "使用StringRedisTemplate对象";
}
@GetMapping("/redis/getstr/{k}")
public String getStringValue(@PathVariable String k){
String v = stringRedisTemplate.opsForValue().get(k);
return "k的value:"+v;
}
/** 设置 RedisTemplate 序列化
* 可以设置 key 的序列化, 可以设置value的序列化
* 可以同时设置 key 和 value的序列化
*/
@PostMapping("/redis/addstr")
public String addString(String k,String v){
// 使用RedisTemplate
// 设置 key 使用String的序列化
redisTemplate.setKeySerializer( new StringRedisSerializer());
// 设置 value 的序列化
redisTemplate.setValueSerializer( new StringRedisSerializer());
redisTemplate.opsForValue().set(k,v);
return "定义RedisTemplate对象的key,value的序列化";
}
/**
* 使用json 序列化, 把java对象转为json存储
*/
@PostMapping("/redis/addjson")
public String addJson(){
Student student = new Student();
student.setId(1001);
student.setName("zhangsan");
student.setAge(20);
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 把值作为json序列化
redisTemplate.setValueSerializer( new Jackson2JsonRedisSerializer(Student.class) );
redisTemplate.opsForValue().set("mystudent", student);
return "json序列化";
}
@PostMapping("/redis/getjson")
public String getJson(){
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 把值作为json序列化
redisTemplate.setValueSerializer( new Jackson2JsonRedisSerializer(Student.class) );
Object obj = redisTemplate.opsForValue().get("mystudent");
return "json反序列化="+ obj;
}
}
java的序列化: 把java对象转为byte[], 二进制数据
json序列化:json序列化功能将对象转换为 JSON 格式或从 JSON 格式转换对象。
例如把一个Student对象转换为JSON字符串{"name":"李四", "age":29} )
反序列化(将JSON字符串 {"name":"李四", "age":29} 转换为Student对象)
public class Student implements Serializable {
private static final long serialVersionUID = 1901229007746699151L;
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
public interface StudentService {
Student queryStudent(Integer id);
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>023-service-providerartifactId>
<version>1.0.0version>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>com.coolergroupId>
<artifactId>022-interface-apiartifactId>
<version>1.0.0version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>2.7.8version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-dependencies-zookeeperartifactId>
<version>2.7.8version>
<type>pomtype>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12artifactId>
<groupId>org.slf4jgroupId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
/**
* 使用dubbo中的注解暴露服务
*/
//@Component 可以不用加
@DubboService(interfaceClass = StudentService.class,version = "1.0",timeout = 5000)
public class StudentServiceImpl implements StudentService {
@Override
public Student queryStudent(Integer id) {
Student student = new Student();
if( 1001 == id){
student.setId(1001);
student.setName("------1001-张三");
student.setAge(20);
} else if(1002 == id){
student.setId(1002);
student.setName("#######1002-李四");
student.setAge(22);
}
return student;
}
}
#配置服务名称 dubbo:application name="名称"
spring.application.name=studentservice-provider
#配置扫描的包
dubbo.scan.base-packages=com.cooler.service
#dubbo的协议和端口号
#dubbo.protocol.name=dubbo
#dubbo.protocol.port=20881
#注册中心
dubbo.registry.address=zookeeper://localhost:2181
/**
* @EnableDubbo 启用Dubbo 包含以下两个内容
* @EnableDubboConfig
* @DubboComponentScan
*/
@SpringBootApplication
//@EnableDubboConfig
@EnableDubbo
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>024-consumerartifactId>
<version>0.0.1-SNAPSHOTversion>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.coolergroupId>
<artifactId>022-interface-apiartifactId>
<version>1.0.0version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>2.7.8version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-dependencies-zookeeperartifactId>
<version>2.7.8version>
<type>pomtype>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12artifactId>
<groupId>org.slf4jgroupId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
@RestController
public class DubboController {
/**
* 引用远程服务, 把创建好的代理对象,注入给studentService
*/
//@DubboReference(interfaceClass = StudentService.class,version = "1.0")
/**
* 没有使用interfaceClass,默认的就是 引用类型的 数据类型
*/
@DubboReference(version = "1.0")
private StudentService studentService;
@GetMapping("/query")
public String queryStudent(Integer id){
Student student = studentService.queryStudent(id);
return "调用远程接口,获取对象:"+student;
}
}
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
#指定服务名称
spring.application.name=consumer-application
#指定注册中心
dubbo.registry.address=zookeeper://localhost:2181
#指定扫描的包
dubbo.scan.base-packages=com.cooler.controller
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>025-springboot-warartifactId>
<version>1.0.0version>
<packaging>warpackaging>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-jasperartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<finalName>mybootfinalName>
<resources>
<resource>
<directory>src/main/webappdirectory>
<targetPath>META-INF/resourcestargetPath>
<includes>
<include>**/*.*include>
includes>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
includes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.*include>
includes>
resource>
resources>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
server.port=9001
server.servlet.context-path=/myjsp
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp
/**
* SpringBootServletInitializer: 继承这个类, 才能使用独立tomcat服务器
*/
@SpringBootApplication
public class JspApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(JspApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(JspApplication.class);
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>026-springboot-jarartifactId>
<version>0.0.1-SNAPSHOTversion>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-jasperartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<finalName>mybootfinalName>
<resources>
<resource>
<directory>src/main/webappdirectory>
<targetPath>META-INF/resourcestargetPath>
<includes>
<include>**/*.*include>
includes>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
includes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.*include>
includes>
resource>
resources>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>1.4.2.RELEASEversion>
plugin>
plugins>
build>
project>
//之前使用的是@RestController,是因为本次操作有视图,不单单只有数据
@Controller
public class HelloController {
@RequestMapping("/hello")
public ModelAndView hello(){
ModelAndView mv = new ModelAndView();
mv.addObject("data","SpringBoot打包为jar");
mv.setViewName("main");
return mv;
}
}
可以在该jar包所在的目录下cmd,使用java -jar 该文件的名字.jar可以独立启动。(使用的是springboot内嵌的Tomcat)
部署到Linux中
#!/bin/sh
java -jar xxx.jar
//如果不在同一目录,需写成java -jar /usr/xxx/xxx/xx.jar
@Controller
public class HelloThymeleafController {
@GetMapping("/hello")
public String helloThymeleaf(Model model,HttpServletRequest request){
//添加数据到request作用域, 模板引擎可以从request中获取数据
request.setAttribute("data","欢迎使用Thymeleaf模板引擎");
//使用model存放对象
model.addAttribute("mydata","model中的数据");
//指定视图(模板引用使用的页面(html))
//逻辑名称 classpath:/templates/hello.html
return "hello";
}
}
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>hello.htmltitle>
head>
<body>
<h3>使用Thymeleaf的例子h3>
<p th:text="${data}">
显示数据:
p>
<p th:text="${mydata}">
显示数据:
p>
body>
html>
#在开发阶段,关闭模板引擎,让修改立即生效
spring.thymeleaf.cache=false
#编码格式
spring.thymeleaf.encoding=utf-8
#模板类型(默认是HTML)
spring.thymeleaf.mode=HTML
#模板的前缀
spring.thymeleaf.prefix=classpath:/templates/
#模板后缀
spring.thymeleaf.suffix=.html
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<groupId>com.coolergroupId>
<artifactId>028-thymeleaf-courseartifactId>
<version>0.0.1-SNAPSHOTversion>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
<div style="margin-left: 400px">
<h3>标准变量表达式: ${key}h3>
<p th:text="${site}">key不存在p>
<br/>
<p>获取SysUser对象 属性值p>
<p th:text="${myuser.id}">idp>
<p th:text="${myuser.name}">姓名p>
<p th:text="${myuser.sex}">性别:m男p>
<p th:text="${myuser.age}">年龄p>
<p th:text="${myuser.getName()}">获取姓名使用getXXXp>
div>
<p>使用 *{} 获取SysUser的属性值p>
<div th:object="${myuser}">
<p th:text="*{id}">p>
<p th:text="*{name}">p>
<p th:text="*{sex}">p>
<p th:text="*{age}">p>
div>
<p>使用*{}完成的表示 对象的属性值p>
<p th:text="*{myuser.name}" >p>
语法: @{url}
作用: 表示链接, 可以如下
<script src="..."> ,
<link href="...">
<a href=".."> ,
<form action="...">
<img src="...">
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>链接表达式title>
head>
<body>
<h3>链接绝对路径h3>
<a th:href="@{http://www.baidu.com}">链接到百度a>
<h3>链接的是相对地址h3>
<a th:href="@{/tpl/queryAccount}">相对地址,没有参数a>
<h3>链接的相对地址,使用字符串链接传递参数h3>
<a th:href="@{'/tpl/queryAccount?id='+ ${userId} }">获取model中数据a>
<h3>推荐使用的传参数的方式h3>
<a th:href="@{/tpl/queryAccount(id=${userId})}">传参数a>
<h3>传递多个参数h3>
<a th:href="@{/tpl/queryUser(name='lisi',age=20)}">传多个参数a>
body>
html>
<form action="/loginServlet" method="post">form>
<form th:action="/loginServlet" th:method="${methodAttr}">form>
<form id="login" th:action="@{/login}" th:method="post">......form>
<form id="login" th:action="@{/login}" th:method="post">......form>
<a th:href="@{/query/student}">相对地址没有传参数a>
<script type="text/javascript" th:src="@{/js/jquery-3.4.1.js}">script>
<input type="text" id="realName" name="reaName" th:text="${realName}">
<a th:onclick="'fun1('+${user.id}+')'" th:style="'color:red'">点击我a>
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>属性title>
<script th:src="@{/js/jquery-3.4.1.js}" type="text/javascript">script>
head>
<body>
<div style="margin-left: 400px">
<h3>属性使用, 在html元素的属性上加入thh3>
<form th:action="@{/loginServlet}" th:method="${methodAttr}">
<input th:type="text" th:name="${paramname}" th:value="${uservalue}"> <br/>
<input type="button" id="btn" th:onclick="btnClick()" value="按钮">
form>
<p th:style="${textcolor}">这是模板的例子p>
div>
body>
<script type="text/javascript">
function btnClick(){
alert("按钮单击了");
}
$(function(){
$("#btn").click(function(){
alert("click===jquery")
})
})
script>
html>
<div th:each="集合循环成员,循环的状态变量:${key}">
<p th:text="${集合循环成员}" >p>
div>
集合循环成员,循环的状态变量:两个名称都是自定义的。
“循环的状态变量”这个名称可以不定义,默认是"集合循环成员Stat"
th:each="user, iterStat : ${userlist}"中:
◼ iterStat
${userList} 循环体的信息,通过该变量可以获取如下信息:
index: 当前迭代对象的 index(从 0 开始计算)
count: 当前迭代对象的个数(从 1 开始计算)这两个用的较多
size: 被迭代对象的大小
current: 当前迭代变量
even/odd: 布尔值,当前循环是否是偶数/奇数(从 0 开始计算)
first: 布尔值,当前循环是否是第一个
last: 布尔值,当前循环是否是最后一个
注意:循环体信息 iterStat 也可以不定义,则默认采用迭代变量加上 Stat 后缀,即userStat
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>each循环title>
head>
<body>
<div style="margin-left: 400px">
<br/>
<br/>
<table border="1" cellpadding="0" cellspacing="0">
<thead>
<tr>
<td> 编号td>
<td> id 序号 td>
<td> name td>
<td> sex td>
<td> age td>
<td>姓名td>
<td>是否是第一行td>
tr>
thead>
<tbody>
<tr th:each="user:${myusers}">
<td th:text="${userStat.count}+'/'+${userStat.size}">td>
<td th:text="${user.id}">td>
<td th:text="${user.name}">td>
<td th:text="${user.sex}">td>
<td th:text="${user.age}">td>
<td th:text="${userStat.current.name}">td>
<td th:text="${userStat.first}"/>
tr>
tbody>
table>
div>
body>
html>
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>each循环title>
head>
<body>
<div style="margin-left: 400px">
<div th:each="user:${userarray}">
<p th:text="${user.id}">p>
<p th:text="${user.name}">p>
<p th:text="${user.sex}">p>
<p th:text="${user.age}">p>
<br/>
<hr/>
div>
div>
body>
html>
和循环List一样
<div th:each="集合循环成员,循环的状态变量:${key}">
<p th:text="${集合循环成员.key}" >p>
<p th:text="${集合循环成员.value}" >p>
div>
集合循环成员,循环的状态变量:两个名称都是自定义的。 “循环的状态变量”这个名称可以不定义,默认是"集合循环成员Stat"
key:map集合中的key
value:map集合key对应的value值
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>循环Maptitle>
head>
<body>
<div style="margin-left: 400px">
<div th:each="map,userStat:${mymap}">
<p th:text="${map.key}">p>
<p th:text="${map.value}" >p>
<p th:text="${map.value.id}">p>
<p th:text="${map.value.name}">p>
<p th:text="${userStat.index}">p>
<br/>
<hr/>
div>
<br/>
<br/>
div>
body>
html>
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>循环Maptitle>
head>
<body>
<div style="margin-left: 400px">
<h3>循环List《Map》 Map<String,SysUser> lm: listmap.get(0)h3>
<div th:each="lm:${listmap}">
<div th:each="m:${lm}">
<p th:text="${m.key}">p>
<p th:text="${m.value.id}">p>
<p th:text="${m.value.name}">p>
<p th:text="${m.value.age}">p>
<br/>
<hr/>
div>
<br>
<hr>
div>
div>
body>
html>
语法:
<div th:if=" 10 > 0 "> 显示文本内容 div>
<div style="margin-left: 400px">
<h3> if 使用h3>
<p th:if="${sex=='m'}">性别是男p>
<p th:if="${isLogin}">已经登录系统p>
<p th:if="${age > 20}">年龄大于20p>
<p th:if="${name}">name是“”p>
<p th:if="${isOld}"> isOld是nullp>
div>
语法:
<div th:unless=" 10 < 0 "> 当条件为false显示标签体内容 div>
<div style="margin-left: 400px">
<h3>unless: 判断条件为false,显示标签体内容h3>
<p th:unless="${sex=='f'}">性别是男的p>
<p th:unless="${isLogin}">登录系统p>
<p th:unless="${isOld}"> isOld是null p>
div>
语法:
<div th:switch="要比对的值">
<p th:case="值1">
结果1
p>
<p th:case="值2">
结果2
p>
<p th:case="*">
默认结果
p>
以上的case只有一个语句执行
div>
<p>显示姓名是:[[${key}]]p>
<div style="margin-left: 400px">
<h3>内联 text, 使用内联表达式显示变量的值h3>
<div th:inline="text">
<p>我是[[${name}]],年龄是[[${age}]]p>
我是<span th:text="${name}">span>,年龄是<span th:text="${age}">span>
div>
<div>
<p>使用内联textp>
<p>我是[[${name}]],性别是[[${sex}]]p>
div>
div>
例子:
<script type="text/javascript" th:inline="javascript">
var myname = [[${name}]];
var myage = [[${age}]];
//alert("获取的模板中数据 "+ myname + ","+myage)
function fun(){
alert("单击事件,获取数据 "+ myname + ","+ [[${sex}]])
}
script>
<div style="margin-left: 400px">
<h3>文本字面量: 使用单引号括起来的字符串h3>
<p th:text="'我是'+${name}+',我所在的城市'+${city}">数据显示p>
<h3>数字字面量h3>
<p th:if="${20>5}"> 20大于 5p>
<h3>boolean字面量h3>
<p th:if="${isLogin == true}">用户已经登录系统p>
<h3>null字面量h3>
<p th:if="${myuser != null}">有myuser数据p>
div>
<p th:text="'我是'+${name}+',我所在的城市'+${city}">数据显示p>
<p th:text="|我是${name},我所在城市${city|">
显示数据
p>
<div style="margin-left: 400px">
<h3>字符串连接方式1:使用单引号括起来的字符串h3>
<p th:text="'我是'+${name}+',我所在的城市'+${city}">数据显示p>
<br/>
<br/>
<h3>字符串连接方式2:|字符串和表达式|h3>
<p th:text="|我是${name},所在城市${city},其他人${myuser.name}|">p>
div>
算术运算: + , - - , * , / , %
关系比较: > , < , >= , <= ( gt , lt , ge , le )
相等判断: == , != ( eq , ne )
三元运算符:(三元运算符可以嵌套)
表达式 ? true的结果 : false的结果
<div style="margin-left: 400px">
<h3>使用运算符h3>
<p th:text="${age > 10}">年龄大于 10 p>
<p th:text="${ 20 + 30 }">显示运算结果p>
<p th:if="${myuser == null}">myuser是nullp>
<p th:if="${myuser eq null}">myuser是nullp>
<p th:if="${myuser ne null}">myuser不是nullp>
<p th:text="${isLogin == true ? '用户已经登录' : '用户需要登录'}">p>
<p th:text="${isLogin == true ? ( age > 10 ? '用户是大于10的' : '用户年龄比较小') : '用户需要登录'}">p>
div>
#request 表示HttpServletRequest
#session表示HttpSession对象
session对象:表示Map对象的, 是#session的简单表示方式, 用来获取session中指定的key的值
//模板内置对象
@GetMapping("/baseObject")
public String baseObject(Model model, HttpServletRequest request,
HttpSession session){
//添加数据
model.addAttribute("myname","李思");
request.setAttribute("requestData","request作用域中的数据");
request.getSession().setAttribute("sessionData","session作用域中的数据");
//直接使用session
session.setAttribute("loginname","zhangsan");
return "baseObject";
}
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>模板内置对象,方便使用request,sessiontitle>
head>
<body>
<div style="margin-left: 350px">
<h3>内置对象#request,#session,session的使用h3>
<p>获取作用域中的数据p>
<p th:text="${#request.getAttribute('requestData')}">p>
<p th:text="${#session.getAttribute('sessionData')}">p>
<p th:text="${session.loginname}">p>
<br/>
<br/>
<h3>使用内置对象的方法h3>
getRequestURL=<span th:text="${#request.getRequestURL()}">span><br/>
getRequestURI=<span th:text="${#request.getRequestURI()}">span><br/>
getQueryString=<span th:text="${#request.getQueryString()}">span><br/>
getContextPath=<span th:text="${#request.getContextPath()}">span><br/>
getServerName=<span th:text="${#request.getServerName()}">span><br/>
getServerPort=<span th:text="${#request.getServerPort()}">span><br/>
sessionId,getId=<span th:text="${#session.getId()}">span>
<h3>param对象:表示请求的参数集合h3>
name参数的值:<span th:text="${param.name}">span><br/>
参数的数量:<span th:text="${param.size()}">span><br/>
div>
body>
html>
//内置的工具类对象
@GetMapping("/utilobject")
public String utilObject(Model model){
model.addAttribute("mydate",new Date());
model.addAttribute("mynum",26.695);
model.addAttribute("mystr","cooler");
List<String> list = Arrays.asList("a","b","c");
model.addAttribute("mylist",list);
//创建Zoo对象
Zoo zoo = new Zoo();
Cat cat = new Cat();
cat.setName("短腿");
Dog dog = new Dog();
dog.setName("二哈");
zoo.setCat(cat);
//zoo.setDog(dog); zoo.dog = null
model.addAttribute("zoo",zoo);
return "utilObject";
}
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>内置工具类对象title>
head>
<body>
<div style="margin-left: 350px">
<h3>日期类对象 #datesh3>
<p th:text="${#dates.format(mydate )}">p>
<p th:text="${#dates.format(mydate,'yyyy-MM-dd')}">p>
<p th:text="${#dates.format(mydate,'yyyy-MM-dd HH:mm:ss')}">p>
<p th:text="${#dates.year(mydate)}">p>
<p th:text="${#dates.month(mydate)}">p>
<p th:text="${#dates.monthName(mydate)}">p>
<p th:text="${#dates.createNow()}">p>
<br/>
<h3>内置工具类#numbers,操作数字的h3>
<p th:text="${#numbers.formatCurrency(mynum)}">p>
<p th:text="${#numbers.formatDecimal(mynum,5,2)}">p>
<br/>
<h3>内置工具类#strings,操作字符串h3>
<p th:text="${#strings.toUpperCase(mystr)}">p>
<p th:text="${#strings.indexOf(mystr,'cool')}">p>
<p th:text="${#strings.substring(mystr,2,5)}">p>
<p th:text="${#strings.substring(mystr,2)}">p>
<p th:text="${#strings.concat(mystr,'---A cool man---')}">p>
<p th:text="${#strings.length(mystr)}">p>
<p th:text="${#strings.length('hello')}">p>
<p th:unless="${#strings.isEmpty(mystr)}"> mystring 不是 空字符串 p>
<br/>
<h3>内置工具类#lists,操作list集合h3>
<p th:text="${#lists.size(mylist)}">p>
<p th:if="${#lists.contains(mylist,'a')}">有成员ap>
<p th:if="!${#lists.isEmpty(mylist)}"> list 集合有多个成员p>
<br/>
<h3>处理nullh3>
<p th:text="${zoo?.dog?.name}">p>
div>
body>
html>
模板是内容复用, 定义一次,在其他的模板文件中多次使用。
模板使用:
th:fragment="模板自定义名称"
例如:
<div th:fragment="head">
<p>
CoolEr学习Java
p>
<p>
www.cooler.com
p>
div>
1) ~{templatename :: selector}
templatename: 文件名称
selector: 自定义模板名称
2)templatename :: selector
templatename: 文件名称
selector: 自定义模板名称
对于使用模板:
有包含模板(th:include)
插入模板(th:insert)
例子:
head.html
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
<div th:fragment="top">
<p>CoolErp>
<p>网站 www.cooler.comp>
div>
<div th:fragment="menu">
<p>文档|下载|blogp>
div>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div>
footer.html
@copy; CoolEr2022
div>
body>
html>
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>使用模板title>
head>
<body>
<div style="margin-left: 350px">
<h3>使用其他目录中的模板文件h3>
<div th:insert="common/left :: html">div>
<br/>
<br/>
<div th:include="common/left">div>
<div th:insert="head :: menu">div>
<h3>插入模板 th:inserth3>
<div th:insert="~{ head :: top }">
div>
<br/>
<br/>
<h3>插入模板 第二种格式h3>
<p th:insert="head :: top">p>
<br/>
<br/>
<h3>包含模板,第一种语法h3>
<div th:include="~{ head :: top}">
div>
<br/>
<br/>
<h3>包含模板,第二种语法h3>
<div th:include="head :: top">
div>
<br/>
<br/>
<h3>使用整个文件作为复用的内容(整个文件作为模板使用)h3>
<div th:include="footer :: html">div>
<br/>
<div th:include="footer" >div>
<br/>
<div th:insert="footer">div>
div>
body>
html>
注解 | 解释 |
---|---|
@Controller | 组合注解(组合了@Component注解),应用在MVC层(控制层),DispatcherServlet会自动扫描注解了此注解的类,然后将web请求映射到注解了@RequestMapping的方法上。 |
@Service | 组合注解(组合了@Component注解),应用在service层(业务逻辑层) |
@Reponsitory | 组合注解(组合了@Component注解),应用在dao层(数据访问层) |
@Component | 表示一个带注释的类是一个“组件”,成为Spring管理的Bean。当使用基于注解的配置和类路径扫描时,这些类被视为自动检测的候选对象。同时@Component还是一个元注解。 |
@Autowired | Spring提供的工具(由Spring的依赖注入工具(BeanPostProcessor、BeanFactoryPostProcessor)自动注入。) |
@Resource | JSR-250提供的注解 |
@Inject | JSR-330提供的注解 |
@Configuration | 声明当前类是一个配置类(相当于一个Spring配置的xml文件) |
@ComponentScan | 自动扫描指定包下所有使用@Service,@Component,@Controller,@Repository的类并注册 |
@Bean | 注解在方法上,声明当前方法的返回值为一个Bean。返回的Bean对应的类中可以定义init()方法和destroy()方法,然后在@Bean(initMethod=”init”,destroyMethod=”destroy”)定义,在构造之后执行init,在销毁之前执行destroy。 |
@Aspect | 声明一个切面(就是说这是一个额外功能) |
@After | 后置建言(advice),在原方法前执行。 |
@Before | 前置建言(advice),在原方法后执行。 |
@Around | 环绕建言(advice),在原方法执行前执行,在原方法执行后再执行(@Around可以实现其他两种advice) |
@PointCut | 声明切点,即定义拦截规则,确定有哪些方***被切入 |
@Transactional | 声明事务(一般默认配置即可满足要求,当然也可以自定义) |
@Cacheable | 声明数据缓存 |
@EnableAspectJ*** | 开启Spring对AspectJ的支持 |
@Value | 值得注入。经常与Sping EL表达式语言一起使用,注入普通字符,系统属性,表达式运算结果,其他Bean的属性,文件内容,网址请求内容,配置文件属性值等等 |
@PropertySource | 指定文件地址。提供了一种方便的、声明性的机制,用于向Spring的环境添加PropertySource。与@configuration类一起使用。 |
@PostConstruct | 标注在方法上,该方法在构造函数执行完成之后执行。 |
@PreDestroy | 标注在方法上,该方法在对象销毁之前执行。 |
@Profile | 表示当一个或多个指定的文件是活动的时,一个组件是有资格注册的。使用@Profile注解类或者方法,达到在不同情况下选择实例化不同的Bean。@Profile(“dev”)表示为dev时实例化。 |
@EnableAsync | 开启异步任务支持。注解在配置类上。 |
@Async | 注解在方法上标示这是一个异步方法,在类上标示这个类所有的方法都是异步方法。 |
@EnableScheduling | 注解在配置类上,开启对计划任务的支持。 |
@Scheduled | 注解在方法上,声明该方法是计划任务。支持多种类型的计划任务:cron,fixDelay,fixRate |
@Conditional | 根据满足某一特定条件创建特定的Bean |
@Enable* | 通过简单的@Enable来开启一项功能的支持。所有@Enable注解都有一个@Import注解,@Import是用来导入配置类的,这也就意味着这些自动开启的实现其实是导入了一些自动配置的Bean(1.直接导入配置类2.依据条件选择配置类3.动态注册配置类) |
@RunWith | 这个是Junit的注解,springboot集成了junit。一般在测试类里使用:@RunWith(SpringJUnit4ClassRunner.class) — SpringJUnit4ClassRunner在JUnit环境下提供Sprng TestContext Framework的功能 |
@ContextConfiguration | 用来加载配置ApplicationContext,其中classes属性用来加载配置类:@ContextConfiguration(classes = {TestConfig.class(自定义的一个配置类)}) |
@ActiveProfiles | 用来声明活动的profile–@ActiveProfiles(“prod”(这个prod定义在配置类中)) |
@EnableWebMvc | 用在配置类上,开启SpringMvc的Mvc的一些默认配置:如ViewResolver,MessageConverter等。同时在自己定制SpringMvc的相关配置时需要做到两点:1.配置类继承WebMvcConfigurerAdapter类2.就是必须使用这个@EnableWebMvc注解。 |
@RequestMapping | 用来映射web请求(访问路径和参数),处理类和方法的。可以注解在类和方法上,注解在方法上的@RequestMapping路径会继承注解在类上的路径。同时支持Serlvet的request和response作为参数,也支持对request和response的媒体类型进行配置。其中有value(路径),produces(定义返回的媒体类型和字符集),method(指定请求方式)等属性。 |
@ResponseBody | 将返回值放在response体内。返回的是数据而不是页面 |
@RequestBody | 允许request的参数在request体中,而不是在直接链接在地址的后面。此注解放置在参数前。 |
@PathVariable | 放置在参数前,用来接受路径参数。 |
@RestController | 组合注解,组合了@Controller和@ResponseBody,当我们只开发一个和页面交互数据的控制层的时候可以使用此注解。 |
@ControllerAdvice | 用在类上,声明一个控制器建言,它也组合了@Component注解,会自动注册为Spring的Bean。 |
@ExceptionHandler | 用在方法上定义全局处理,通过他的value属性可以过滤拦截的条件:@ExceptionHandler(value=Exception.class)–表示拦截所有的Exception。 |
@ModelAttribute | 将键值对添加到全局,所有注解了@RequestMapping的方法可获得次键值对(就是在请求到达之前,往model里addAttribute一对name-value而已)。 |
@InitBinder | 通过@InitBinder注解定制WebDataBinder(用在方法上,方法有一个WebDataBinder作为参数,用WebDataBinder在方法内定制数据绑定,例如可以忽略request传过来的参数Id等)。 |
@WebAppConfiguration | 一般用在测试上,注解在类上,用来声明加载的ApplicationContext是一个WebApplicationContext。他的属性指定的是Web资源的位置,默认为src/main/webapp,我们可以修改为:@WebAppConfiguration(“src/main/resources”)。 |
@EnableAutoConfiguration | 此注释自动载入应用程序所需的所有Bean——这依赖于Spring Boot在类路径中的查找。该注解组合了@Import注解,@Import注解导入了EnableAutoCofigurationImportSelector类,它使用SpringFactoriesLoader.loaderFactoryNames方法来扫描具有META-INF/spring.factories文件的jar包。而spring.factories里声明了有哪些自动配置。 |
@SpingBootApplication | SpringBoot的核心注解,主要目的是开启自动配置。它也是一个组合注解,主要组合了@Configurer,@EnableAutoConfiguration(核心)和@ComponentScan。可以通过@SpringBootApplication(exclude={想要关闭的自动配置的类名.class})来关闭特定的自动配置。 |
@ImportResource | 虽然Spring提倡零配置,但是还是提供了对xml文件的支持,这个注解就是用来加载xml配置的。例:@ImportResource({“classpath |
@ConfigurationProperties | 将properties属性与一个Bean及其属性相关联,从而实现类型安全的配置。例:@ConfigurationProperties(prefix=”authot”,locations={“classpath |
@ConditionalOnBean | 条件注解。当容器里有指定Bean的条件下。 |
@ConditionalOnClass | 条件注解。当类路径下有指定的类的条件下。 |
@ConditionalOnExpression | 条件注解。基于SpEL表达式作为判断条件。 |
@ConditionalOnJava | 条件注解。基于JVM版本作为判断条件。 |
@ConditionalOnJndi | 条件注解。在JNDI存在的条件下查找指定的位置。 |
@ConditionalOnMissingBean | 条件注解。当容器里没有指定Bean的情况下。 |
@ConditionalOnMissingClass | 条件注解。当类路径下没有指定的类的情况下。 |
@ConditionalOnNotWebApplication | 条件注解。当前项目不是web项目的条件下。 |
@ConditionalOnResource | 条件注解。类路径是否有指定的值。 |
@ConditionalOnSingleCandidate | 条件注解。当指定Bean在容器中只有一个,后者虽然有多个但是指定首选的Bean。 |
@ConditionalOnWebApplication | 条件注解。当前项目是web项目的情况下。 |
@EnableConfigurationProperties | 注解在类上,声明开启属性注入,使用@Autowired注入。例:@EnableConfigurationProperties(HttpEncodingProperties.class)。 |
@AutoConfigureAfter | 在指定的自动配置类之后再配置。例:@AutoConfigureAfter(WebMvcAutoConfiguration.class) |