嗯,加油生活,依旧,摘几句子. 我十有八九的欲言又止,在日后想来都庆幸。而绝大多数的敞开心扉在事后都追悔。 -------德卡先生的信箱
2019.10.3
Spring1.x 时代
在Spring1.x时代,都是通过xml文件配置bean,随着项目的不断扩大,需要将xml配置分放到不同的配置文件中,需要频繁的在java类和xml配置文件中切换。
Spring2.x时代
随着JDK 1.5带来的注解支持,Spring2.x可以使用注解对Bean进行申明和注入,大大的减少了xml配置文件,同时也大大简化了项目的开发。
那么,问题来了,究竟是应该使用xml还是注解呢?
最佳实践:
Spring3.x到Spring4.x
从Spring3.x开始提供了Java配置方式,使用Java配置方式可以更好的理解你配置的Bean,现在我们就处于这个时代,并且Spring4.x和Spring boot都推荐使用java配置的方式。
Java配置是Spring4.x推荐的配置方式,可以完全替代xml配置。
Spring的Java配置方式是通过 @Configuration 和 @Bean 这两个注解实现的:
1、@Configuration 作用于类上,相当于一个xml配置文件; 类似与springboot的@SpringBootConfiguration
2、@Bean 作用于方法上,相当于xml配置中的
实例:
@Configuration //通过该注解来表明该类是一个Spring的配置,相当于一个xml文件
@ComponentScan(basePackages = "cn.itcast.springboot.javaconfig") //配置扫描包
public class SpringConfig {
@Bean // 通过该注解来表明是一个Bean对象,相当于xml中的
public UserDAO getUserDAO(){
return new UserDAO(); // 直接new对象做演示
}
}
public class Main {
public static void main(String[] args) {
// 通过Java配置来实例化Spring容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
// 在Spring容器中获取Bean对象
UserService userService = context.getBean(UserService.class);
// 调用对象中的方法
List list = userService.queryUserList();
for (User user : list) {
System.out.println(user.getUsername() + ", " + user.getPassword() + ", " + user.getPassword());
}
// 销毁该容器
context.destroy();
}
}
读取外部资源:
@Configuration //通过该注解来表明该类是一个Spring的配置,相当于一个xml文件
@ComponentScan(basePackages = "cn.itcast.springboot.javaconfig") //配置扫描包
@PropertySource(value= {"classpath:jdbc.properties"})//多个时逗号双引号隔开
public class SpringConfig {
@Value("${jdbc.url}")
private String jdbcUrl;
@Bean // 通过该注解来表明是一个Bean对象,相当于xml中的
public UserDAO getUserDAO(){
return new UserDAO(); // 直接new对象做演示
}
}
简化Spring应用的创建、运行、调试、部署等。使用Spring Boot可以做到专注于Spring应用的开发,而无需过多关注XML的配置。Spring Boot使用“习惯优于配置”的理念,简单来说,它提供了一堆依赖打包,并已经按照使用习惯解决了依赖问题。使用Spring Boot可以不用或者只需要很少的Spring配置就可以让企业项目快速运行起来。
springboot的优点:
使用Java或Groovy开发基于Spring的应用程序非常容易。
它减少了大量的开发时间并提高了生产力。
它避免了编写大量的样板代码,注释和XML配置。
Spring Boot应用程序与其Spring生态系统(如Spring JDBC,Spring ORM,Spring Data,Spring Security等)集成非常容易。
它遵循“自用默认配置”方法,以减少开发工作量。
它提供嵌入式HTTP服务器,如Tomcat,Jetty等,以开发和测试Web应用程序非常容易。
它提供CLI(命令行界面)工具从命令提示符,非常容易和快速地开发和测试Spring Boot(Java或Groovy)应用程序。
它提供了许多插件来开发和测试Spring启动应用程序非常容易使用构建工具,如Maven和Gradle。
它提供了许多插件,以便与嵌入式和内存数据库工作非常容易。
Spring Boot的核心功能
(1)独立运行的Spring项目
Spring Boot可以以jar包的形式进行独立的运行,使用:java -jar xx.jar
就可以成功的运行项目,或者在应用项目的主程序中运行main函数即可;
(2)内嵌的Servlet容器
内嵌容器,使得我们可以执行运行项目的主程序main函数,是想项目的快速运行;
(3)提供starter简化Manen配置
Spring Boot提供了一系列的starter pom用来简化我们的Maven依赖,下边是创建一个web项目中自动包含的依赖,使用的starter pom以来为:spring-boot-starter-web
spring-bootstatus-parent简介:
1,包含了常用的版本属性,
修改java的编译版本,
包含常用的依赖
1,springboot -starter-xxx:Springboot自带的starter包
2,xxx-spring-boot-starter;第三方和springBoot集成的starter
3,druid-spring-boot-starter (druid数据源的原始依赖)自动装配的依赖
spring-boot-starter-web:支持全栈web开发,里面包括了Tomcat和Spring-webmvc。
spring-boot-starter-mail:提供对javax.mail的支持.
spring-boot-starter-ws: 提供对Spring Web Services的支持
spring-boot-starter-test:提供对常用测试框架的支持,包括JUnit,Hamcrest以及Mockito等。
spring-boot-starter-actuator:支持产品环境下的一些功能,比如指标度量及监控等。
spring-boot-starter-jetty:支持jetty容器。
spring-boot-starter-log4j:引入默认的log框架(logback)
Spring Boot官网还提供了很多的starter pom,请参考:
http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-starter
springboot的parent的设置:
spring-boot-dependencies
,这个里边定义了依赖的版本,也正是因为继承了这个依赖,所以我们在写依赖时才不需要写版本号。不用 parent:使用公司的parent。自己定义节点。
org.springframework.boot
spring-boot-dependencies
2.1.4.RELEASE
pom
import
package com.example.demo.helloDemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/1 11:26
*/
@Controller
@RequestMapping("test")
public class HelloController {
@Autowired
private ApplicationArguments applicationArguments;
@RequestMapping("hello")
@ResponseBody
public String helloPage(){
System.out.println(applicationArguments.getNonOptionArgs());
return "hello springboot";
}
}
package com.example.demo.helloDemo;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import java.util.Arrays;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
System.out.println(Arrays.toString(args));
// 启动配置类方法1
SpringApplication.run(DemoApplication.class, args);
// 启动一个配置类方法2.设置banner
SpringApplication application = new SpringApplication(DemoApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
// 启动一个配置类3
new SpringApplicationBuilder(DemoApplication.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
}
}
java -jar xx.jar
tomcat配置:
# 修改端口号
server.port=8080
# 修改上下文路径
server.servlet.context-path=/liruilong
# 配置编码
server.tomcat.uri-encoding=utf-8
由于application.properties和application.yml文件接受Spring样式占位符 ${...}
,因此 Maven 过滤更改为使用 @..@
占位符,当然开发者可以通过设置名为 resource.delimiter 的Maven 属性来覆盖 @..@
占位符。
* 在应用程序启动过程中,可以通过启动参数给应用传递一些额外的参数来控制应用的运行.
* 1,在main方法中可以直接使用传入的参数.
* 2,可以任何类中直接通过@Autowired注入一个ApplicationArgument对象.
* sptingboot参数的主要来源及优先级:
post 生产(application-dev.yml):dev 开发(application-port.yml): text 测试
spring:
profiles:
active: dev
package com.example.demo.parentDi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/5 18:38
*/
@Controller
public class bookController {
@Autowired
private Book book;
@ResponseBody
@RequestMapping("book")
public String shuwBook(){
return book.toString();
}
}
package com.example.demo.parentDi;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/5 18:20
*/
@PropertySource("classpath:books.properties")
@Setter@Getter@ToString
@Component
public class Book {
@Value("${name}")
private String name;
@Value("${pri}")
private double pri;
@Value("${sum}")
private int sum;
}
package com.example.demo.datasourceDemocontroller;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
// SpringApplication.run(DemoApplication.class, args);
// 取消banner
SpringApplicationBuilder builder = new SpringApplicationBuilder(DemoApplication.class);
SpringApplication build = builder.build();
build.setBannerMode(Banner.Mode.OFF);
build.run(args);
}
}
将图片加工后放到resource下面就可以啦.
server.port=8080
#数据源配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=mysql
package com.example.demo.configureationPropertise;
import com.example.demo.configureationPropertise.MyDruidSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/2 12:44
*/
@Controller
public class DateSource {
@Autowired
private MyDruidSource myDruidSource;
@RequestMapping("dataSource")
@ResponseBody
public String dataSource(){
// System.out.println(myDruidSource.toString());
System.out.println(myDruidSource.toString());
return "dataSourct";
}
}
package com.example.demo.configureationPropertise;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/2 12:31
*/
@Setter
@Getter
@ToString
@Component
@ConfigurationProperties("db")
public class MyDruidSource {
private String username;
private String password;
private String url;
private String driverClassName;
}
package com.example.demo.configureationPropertise;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/2 12:47
*/
@SpringBootApplication
public class Appconfig {
@Bean
@ConfigurationProperties("db")
public MyDruidSource dataSource(){
return new MyDruidSource();
}
public static void main(String[] args) {
SpringApplication.run(Appconfig.class, args);
}
}
Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。
例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。
Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。
org.projectlombok
lombok
1.16.20
provided
yaml配置和properties区别:
# YAML 配置 (*.yml || *.yaml)
server:
port: 8081
redis:
port: 6397
hosts:
- 192.168.66.128
- 192.168.66.128
- 192.168.66.128
- 192.168.66.128
redisList:
- port: 6397
hosts: 192.168.22.128
- port: 6833
hosts: 192.168.22.128
package com.example.demo.yamlDemo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/5 19:18
*/
@Getter@Setter@ToString
@Component
@ConfigurationProperties(prefix = "redis")
public class Redis {
private String port;
private List hosts;
private List redisList;
}
package com.example.demo.yamlDemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/5 19:25
*/
@Controller
public class ymlDemoController {
@Autowired
private Redis r;
@ResponseBody
@RequestMapping("yml")
public String showReids(){
System.out.println(r.toString());
return r.toString();
}
}
默认的加载顺序
${basedir}/src/main/resources
true
**/application*.yml
**/application*.yaml
**/application*.properties
server.port=8080
#数据源配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=mysql
# 打印sql语句
logging.level.com.example.demo.mybatisDemo.Mapper=debug
# 加载mybatis配置文件 可以不写
# mybatis.config-location=classpath:mybatis-config.xml
# 指定别名 可以不写
# mybatis.type-aliases-package=com.example.demo.mybatisDemo.POJO.user
# 指定映射文件的位置 可以不写
# mybatis.mapper-locations=classpath:com/example/demo/mybatisDemo/Mapper/*Mapper.xml
package com.example.demo.mybatisDemo.controller;
import com.example.demo.mybatisDemo.POJO.user;
import com.example.demo.mybatisDemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/3 9:47
*/
@Controller
public class UserController {
@Autowired
private UserService userServiceimpl;
@ResponseBody
@RequestMapping("select")
public List select(){
return userServiceimpl.select();
}
@RequestMapping("reig")
void insert(user user){
userServiceimpl.insert(user);
}
}
package com.example.demo.mybatisDemo.Mapper;
import com.example.demo.mybatisDemo.POJO.user;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/2 20:49
*/
@Repository
public interface UserMapper {
List select();
void insert(user user);
}
insert into user values (1,"李四","10000")
package com.example.demo.mybatisDemo.POJO;
import lombok.Getter;
import lombok.Setter;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/2 20:42
*/
@Setter@Getter
public class user {
private Long id;
private String name;
private String resource;
}
package com.example.demo.mybatisDemo.service;
import com.example.demo.mybatisDemo.POJO.user;
import java.util.List;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/3 9:43
*/
public interface UserService {
List select();
void insert(user user);
}
package com.example.demo.mybatisDemo.service;
import com.example.demo.mybatisDemo.Mapper.UserMapper;
import com.example.demo.mybatisDemo.POJO.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/3 9:43
*/
@Service
public class UserServiceimpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public List select() {
return userMapper.select();
}
@Override
public void insert(user user) {
userMapper.insert(user);
}
}
package com.example.demo.mybatisDemo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/3 9:38
*/
@SpringBootApplication
@MapperScan("com.example.demo.mybatisDemo.Mapper") // 数据源配置
// 扫描mapper
public class Appconfig {
public static void main(String[] args) {
SpringApplication.run(Appconfig.class, args);
}
}
springboot-mybatis多数据源配置:
package com.example.demo.mybatisDemo.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import javax.sql.DataSource;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/11/25 8:44
*/
@Configuration
@MapperScan(basePackages = "com.example.demo.mybatisDemo.Mapper1", sqlSessionFactoryRef ="sqlSessionFactory1", sqlSessionTemplateRef = "sqlSessionTemplate1")
public class DataSourceConfig {
@Resource(name = "dsOne")
DataSource dsOne;
@Bean
SqlSessionFactory sqlSessionFactory1() {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
try{
bean.setDataSource(dsOne);
return bean.getObject();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
@Bean
SqlSessionTemplate sqlSessionTemplate1(){
return new SqlSessionTemplate(sqlSessionFactory1());
}
}
springboot整合jdbctemplate
package com.example.demo.jdbctemplate;
import org.apache.catalina.LifecycleState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/11/24 19:45
*/
@Service
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
public Integer addUser(User user){
return jdbcTemplate.update("INSERT INTO users(username,password) VALUES (?, ? )",user.getUsername(), user.getPassword());
}
public List getAllUser(){
// 属性名不同的
return jdbcTemplate.query("SELECT * FROM users ", new RowMapper() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
//属性名相同
return jdbcTemplate.query("", new BeanPropertyRowMapper<>(User.class));
}
}
springboot----jdbctemplate多数据源的配置
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.one.url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=UTF-8
spring.datasource.one.username=root
spring.datasource.one.password=mysql
spring.datasourceoe.tow.type=com.alibaba.druid.pool.DruidDataSource
spring.datasourceoe.tow.url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=UTF-8
spring.datasourceoe.tow.username=root
spring.datasourceoe.tow.password=mysql
package com.example.demo.jdbctemplate;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/11/25 7:51
*/
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.one")
DataSource dsOne(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.tow")
DataSource dsTow(){
return DruidDataSourceBuilder.create().build();
}
}
package com.example.demo.jdbctemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/11/25 7:56
*/
@Configuration
public class jdbcTemplateConfig {
@Bean // @Qualifier 指定前缀
JdbcTemplate jdbcTemplateOne(@Qualifier("dsOne")DataSource dsOne){
return new JdbcTemplate(dsOne);
}
@Bean // @Qualifier 指定前缀
JdbcTemplate jdbcTemplateTow(@Qualifier("dsTow")DataSource dsOne){
return new JdbcTemplate(dsOne);
}
}
package com.example.demo.jdbctemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/11/24 19:51
*/
@Component
public class test {
@Autowired
@Qualifier("jdbcTemplateOne")
JdbcTemplate jdbcTemplateOne;
@Resource(name = "jdbcTemplateTow")
JdbcTemplate jdbcTemplateTow;
public static void main(String[] args) {
}
public Integer addUserOne(User user){
return jdbcTemplateOne.update("INSERT INTO users(username,password) VALUES (?, ? )",user.getUsername(), user.getPassword());
}
public Integer addUserTow(User user){
return jdbcTemplateTow.update("INSERT INTO users(username,password) VALUES (?, ? )",user.getUsername(), user.getPassword());
}
}
package com.example.demo.mybatisDemo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/3 9:38
*/
@EnableTransactionManagement //等价于xml的
@SpringBootApplication
@MapperScan("com.example.demo.mybatisDemo.Mapper")// 扫描mapper
// 读取配置文件
//@ImportResource("classpath:applicationContext.xml")
public class Appconfig {
@Bean
public PlatformTransactionManager txManager(DataSource dataSource){
DataSourceTransactionManager txManager = new DataSourceTransactionManager();
txManager.setDataSource(dataSource);
return txManager;
}
public static void main(String[] args) {
SpringApplication.run(Appconfig.class, args);
}
}
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
先静态,静态没有到动态下寻找.直接在页面下写Index文件即可.
spring.resources.static-locations=classpath:/static,/public,/resources,/META-INF/resource,/mydir
org.springframework.boot
spring-boot-devtools
2.0.2
true
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-freemarker
对于模板引擎,默认的加载路径为:calsspath下的/templates.
Thymeleaf是一种用于Web和独立环境的现代服务器端的Java模板引擎。
Thymeleaf的主要目标是将优雅的自然模板带到开发工作流程中,并将HTML在浏览器中正确显示,并且可以作为静态原型,让开发团队能更容易地协作。Thymeleaf能够处理HTML,XML,JavaScript,CSS甚至纯文本。
Title
id
姓名
地址
性别
使用Thymeleaf属性需要注意点以下五点:
xmlns:th="http://www.thymeleaf.org"
html有的属性,Thymeleaf基本都有,而常用的属性大概有七八个。其中th属性执行的优先级从1~8,数字越低优先级越高。
FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
org.springframework.boot
spring-boot-starter-freemarker
freemarker
hello ${name}
package com.example.demo.freemarker;
import org.jcp.xml.dsig.internal.MacOutputStream;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/3 21:12
*/
@Controller
public class FreemarkerController {
@RequestMapping("name")
public String helloPage(Model model){
model.addAttribute("name","springboot");
return "hello";
}
}
#freemarker 获取session域
spring.freemarker.expose-session-attributes=true
freemarker学习博客:https://www.cnblogs.com/itdragon/p/7750903.html
freemarker
编号
用户名
用户地址
性别
<#list users as u>
<#if u.id=4>
<#break >
${u.id}
${u.name}
${u.addres}
<#if u.fix==0>
男
<#elseif u.fix=1>
女
<#elseif u.fix=2>
未知
字符串输出:
${"Hello ${name} !"} / ${"Hello " + name + " !"}
<#assign cname=r"特殊字符完成输出(http:\www.baidu.com)">
${cname}
字符串截取 :
通过下标直接获取下标对应的字母: ${name[2]}
起点下标..结尾下标截取字符串:${name[0..2]}
算数运算:
<#-- 支持"+"、"-"、"*"、"/"、"%"运算符 -->
<#assign number1 = 10>
<#assign number2 = 5>
"+" : ${number1 + number2}
"-" : ${number1 - number2}
"*" : ${number1 * number2}
"/" : ${number1 / number2}
"%" : ${number1 % number2}
比较运算符:
<#if number1 + number2 gte 12 || number1 - number2 lt 6>
"*" : ${number1 * number2}
<#else>
"/" : ${number1 / number2}
内建函数:
<#assign data = "abcd1234">:${data}
第一个字母大写:${data?cap_first}
所有字母小写:${data?lower_case}
所有字母大写:${data?upper_case}
<#assign floatData = 12.34>:${floatData}
数值取整数:${floatData?int}
获取集合的长度:${users?size}
时间格式化:${dateTime?string("yyyy-MM-dd")}
空判断和对象集合:
<#if users??>
<#list users as user >
${user.id} - ${user.name}
<#else>
${user!"变量为空则给一个默认值"}
Map集合:
<#assign mapData={"name":"程序员", "salary":15000}>
直接通过Key获取 Value值:${mapData["name"]}
通过Key遍历Map:
<#list mapData?keys as key>
Key: ${key} - Value: ${mapData[key]}
通过Value遍历Map:
<#list mapData?values as value>
Value: ${value}
List集合:
<#assign listData=["ITDragon", "blog", "is", "cool"]>
<#list listData as value>${value}
include指令:
引入其他文件:<#include "otherFreeMarker.ftl" />
macro宏指令:
<#macro mo>
定义无参数的宏macro--${name}
使用宏macro: <@mo />
<#macro moArgs a b c>
定义带参数的宏macro-- ${a+b+c}
使用带参数的宏macro: <@moArgs a=1 b=2 c=3 />
命名空间:
<#import "otherFreeMarker.ftl" as otherFtl>
${otherFtl.otherName}
<@otherFtl.addMethod a=10 b=20 />
<#assign otherName="修改otherFreeMarker.ftl中的otherName变量值"/>
${otherFtl.otherName}
<#assign otherName="修改otherFreeMarker.ftl中的otherName变量值" in otherFtl />
${otherFtl.otherName}
Title
其他FreeMarker文件
<#macro addMethod a b >
result : ${a + b}
<#assign otherName="另外一个FreeMarker的变量">
package com.example.demo.freemarker;
import com.example.demo.freemarker.bena.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.*;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/3 21:12
*/
@Controller
public class FreemarkerController {
@RequestMapping("name")
public String helloPage(Model model){
model.addAttribute("name","springboot");
return "hello";
}
@GetMapping("user")
public String user(Model model){
List users = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 15; i++) {
User user = new User();
user.setId(i);
user.setName("java"+ ">>"+i);
user.setAddres("liruiong"+ ">>" + i);
user.setFix(random.nextInt(3));
users.add(user);
}
Map dataMap = new HashMap();
model.addAttribute("name", "itdragon博客");
model.addAttribute("dateTime", new Date());
model.addAttribute("dataMap",dataMap);
model.addAttribute("name", "李瑞龙");
model.addAttribute("users",users);
return "userftl";
}
}
数据类型:
和java不同,FreeMarker不需要定义变量的类型,直接赋值即可。
字符串: value = "xxxx" 。如果有特殊字符 string = r"xxxx" 。单引号和双引号是一样的。
数值:value = 1.2。数值可以直接等于,但是不能用科学计数法。
布尔值:true or false。
List集合:list = [1,2,3] ; list=[1..100] 表示 1 到 100 的集合,反之亦然。
Map集合:map = {"key" : "value" , "key2" : "value2"},key 必须是字符串哦!
实体类:和EL表达式差不多,直接点出来。
字符串操作
字符串连接:可以直接嵌套${"hello , ${name}"} ; 也可以用加号${"hello , " + name}
字符串截取:string[index]。index 可以是一个值,也可以是形如 0..2 表示下标从0开始,到下标为2结束。一共是三个数。
比较运算符
== (等于),!= (不等于),gt(大于),gte(大于或者等于),lt(小于),lte(小于或者等于)。不建议用 >,< 可能会报错!
一般和 if 配合使用
内建函数
FreeMarker 提供了一些内建函数来转换输出,其结构:变量?内建函数,这样就可以通过内建函数来转换输出变量。
1. html: 对字符串进行HTML编码;
2. cap_first: 使字符串第一个字母大写;
3. lower_case: 将字符串转成小写;
4. upper_case: 将字符串转成大写;
5. size: 获得集合中元素的个数;
6. int: 取得数字的整数部分。
变量空判断
! 指定缺失变量的默认值;一般配置变量输出使用
?? 判断变量是否存在。一般配合if使用 <#if value??>
宏指令
可以理解为java的封装方法,供其他地方使用。宏指令也称为自定义指令,macro指令
语法很简单:<#macro val > 声明macro ; 使用macro <@val />
命名空间
可以理解为java的import语句,为避免变量重复。一个重要的规则就是:路径不应该包含大写字母,使用下划线_分隔词语,myName --> my_name
语法很简单:<#import "xxx.ftl" as val>
一,处理全局异常
package com.example.demo.freemarker;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Description :
* @Date: 2019/10/3 21:37
* @Author: Liruilong
*/
@ControllerAdvice //controller的增强
public class ErrorController {
// 可以指定异常类型,当触发时指定所在的异常.不指定时默认所有异常处理器
@ExceptionHandler
public void handlerError(Exception ex, HandlerMethod handlerMethod, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.write("统一的异常处理");
out.write("异常描述:" + ex.getMessage());
out.write("发生异常的类:"+handlerMethod.getBean().getClass().getName());
out.write("发生异常的方法:"+handlerMethod.getMethod().getName());
}
@ExceptionHandler(ArithmeticException.class)
public void myEscrption(ArithmeticException ex, HttpServletResponse response ) throws IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.write("算数异常处理");
System.out.println("异常描述:" + ex.getMessage());
}
@ExceptionHandler(ArithmeticException.class)
public ModelAndView myException(ArithmeticException ex,HttpServletResponse response){
ModelAndView modelAndView = new ModelAndView("erroe");
modelAndView.addObject("error", "异常页面");
return modelAndView;
}
}
二,预设全局数据
定义一个controller增强
package com.example.demo.controlleradvice;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
import java.util.HashMap;
import java.util.Map;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/8 23:48
*/
@ControllerAdvice
public class DemoDate {
@ModelAttribute(value = "info")
public Map mydata(){
Map map= new HashMap<>();
map.put("name","javaboy");
map.put("address", "www.javaboy.org");
return map;
} ;
}
定义一个contrlooerl
package com.example.demo.controlleradvice;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/8 23:52
*/
@RestController
public class Controller {
@GetMapping("/hellos")
public String hello(Model model){
// 转换为Map
Map map = model.asMap();
map.forEach((o1, o2) ->{
System.out.println(o1 + o2);
});
return "hello";
}
}
请求参数预处理:
当前端传来的相同键的不同值得时候,会将相同的键的值合并到一起.可以指定前缀,然后通过前缀来区分不同的值.
@GetMapping("/book")
public void addBook(@ModelAttribute("a")Book book, @ModelAttribute("b") User user){
System.out.println(book.toString());
System.out.println(user.toString());
}
package com.example.demo.controlleradvice;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import java.util.HashMap;
import java.util.Map;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/8 23:48
*/
@InitBinder("a")
public void initA(WebDataBinder binder){
binder.setFieldDefaultPrefix("a");
}
@InitBinder("b")
public void initB(WebDataBinder binder){
binder.setFieldDefaultPrefix("b");
}
}
spring自定义异常数据,当不对异常信息进行处理的时候,spring会对异常信息进行处理,并替换为指定的错误页面
可以使用默认的异常处理的参数,
可一个使用自定义的参数处理.
@ResponseBody
@GetMapping("errorDemo")
public String errorDemo(){
int i = 1/0;
return "异常测试";
}
// 500.html
Title
path
timestamp
message
att
spring自定义异常处理页面.
package com.example.demo.freemarker;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.DefaultErrorViewResolver;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/9 10:55
*/
@Component
public class MyErrorviewResolver extends DefaultErrorViewResolver {
/**
* Create a new {@link DefaultErrorViewResolver} instance.
*
* @param applicationContext the source application context
* @param resourceProperties resource properties
*/
public MyErrorviewResolver(ApplicationContext applicationContext, ResourceProperties resourceProperties) {
super(applicationContext, resourceProperties);
}
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map model) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("error");
modelAndView.addAllObjects(model);
return modelAndView;
}
}
package com.example.demo.servlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/4 10:33
*/
@SpringBootApplication
@ServletComponentScan //扫描Servlet
public class Appconfigs {
public static void main(String[] args) {
SpringApplication.run(Appconfigs.class, args);
}
}
package com.example.demo.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Description : servlet
* @Author: Liruilong
* @Date: 2019/10/4 10:30
*/
@WebServlet(urlPatterns = "/testServlet")
public class TestServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("testServlet");
super.service(req, resp);
}
}
package com.example.demo.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @Description : 拦截请求
* @Author: Liruilong
* @Date: 2019/10/4 10:37
*/
@WebFilter(urlPatterns = "/*")
public class TestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("test Filter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
package com.example.demo.servlet;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* @Description : 监听启动
* @Author: Liruilong
* @Date: 2019/10/4 10:59
*/
@WebListener
public class TestListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("启动了^^^^^^");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("关闭了^^^^^^^^");
}
}
package com.example.demo.servlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/4 10:33
*/
@SpringBootApplication
@ServletComponentScan //扫描Servlet
public class Appconfigs {
@Bean
public ServletRegistrationBean testServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean();
bean.setServlet(new TestServlet());
bean.addUrlMappings("/testServlet");
return bean;
}
@Bean
public FilterRegistrationBean testFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new TestFilter());
bean.addUrlPatterns("/*");
return bean;
}
@Bean
public ServletListenerRegistrationBean testListener(){
ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean<>();
bean.setListener(new TestListener());
return bean;
}
public static void main(String[] args) {
SpringApplication.run(Appconfigs.class, args);
}
}
#文件大小
spring.servlet.multipart.max-file-size=4KB
# 文件写入路径
spring.servlet.multipart.location=
package com.example.demo.fileup;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/4 12:12
*/
@Controller
public class fileupController {
@Value("${file.path}")
private String filePath;
@ResponseBody
@RequestMapping("/upfile")
public String upfile(MultipartFile multipartFile) throws IOException {
if (multipartFile.isEmpty()){
System.out.println("没有传入数据");
}
String filenamefix = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf("."));
String newFile = UUID.randomUUID().toString() + filenamefix;
FileCopyUtils.copy(multipartFile.getInputStream(),new FileOutputStream(new File(filePath+newFile)));
return "文件已经上传啦!!!";
}
// 分文件夹存取
SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
@ResponseBody
@PostMapping("/upload")
public String upload(MultipartFile multipartFile, HttpServletRequest request) throws IOException {
// 将文件存入指定的文件夹
String format = sdf.format(new Date());
String realPath = request.getServletContext().getRealPath("/img") + format;
// 创建文件存放路径
File folder = new File(realPath);
folder.mkdir();
if (!folder.exists()){
folder.mkdirs();
}
String oldName = multipartFile.getOriginalFilename();
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
// 将文件移动到指定的文件夹.
File file = new File(folder,newName);
System.out.println(file.getName());
multipartFile.transferTo(new File(folder, newName));
return newName;
}
// 多文件上传
@ResponseBody
@PostMapping("/uploads")
public String uploads(MultipartFile[] multipartFiles,HttpServletRequest request){
// 创建文件路径
String fommad = sdf.format(new Date());
String filepath = request.getServletContext().getRealPath("/img") + fommad;
File file = new File(filepath);
if (!file.exists()){
file.mkdirs();
}
Arrays.stream(multipartFiles).forEach(
(MultipartFile multipart) ->{
String filename = multipart.getOriginalFilename();
String newName = UUID.randomUUID().toString() + filename.substring(filename.lastIndexOf("."));
try {
multipart.transferTo(new File(file, newName));
} catch (IOException e) {
e.printStackTrace();
}
}
);
return "上传成功";
}
}
//UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法。UUID(Universally Unique Identifier)全局唯一标识符,
// 是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,是由一个十六位的数字组成,表现出来的形式。
// 由以下几部分的组合:当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同),
// 时钟序列,全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得),UUID的唯一缺陷在于生成的结果串会比较长。
文件上传页面
文件上传
基于AJAX的文件上传
package com.example.demo.Binterceptor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/4 15:24
*/@SpringBootApplication
public class Appconfgi extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(Appconfgi.class,args);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册一个拦截器
registry.addInterceptor(myInterceptor()).addPathPatterns("/*");
super.addInterceptors(registry);
}
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
}
package com.example.demo.Binterceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/4 15:28
*/
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截没有哎 $_$");
//return super.preHandle(request, response, handler);
return true;
}
}
package com.example.demo.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/17 16:00
*/
public class MyInterceptors implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("请求进入拦截");
// 只有该方法返回ture才会执行之后的.
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("请求中拦截");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("请求后拦截");
}
}
package com.example.demo.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Description : 拦截器注册
* @Author: Liruilong
* @Date: 2019/10/18 14:53
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
MyInterceptors myInterceptors(){
return new MyInterceptors();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptors()).addPathPatterns("/**");
}
}
package com.example.demo.interceptor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/18 15:01
*/
@SpringBootApplication
public class config {
public static void main(String[] args) {
SpringApplication.run(config.class);
}
}
HttpMessageConverter,:将服务返回的对象序列化为JSON字符串.将前端的JSON数据转化为Java对象
所以的JSON都离不开HttpMassageConverter.Spring MVC 自动配置了Jackson和GSON.
当需要对JSON数据进行相应的格式设置时,可以通过注解或者其他的方式设置.
方法一:
package com.example.demo.jsonDemo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.SecondaryTable;
import java.util.Date;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/7 21:46
*/
@Getter@Setter@ToString
public class User {
private int id ;
private String name;
private String sex;
private String addres;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birdei;
}
方法二:自己注入ObjectMapper
package com.example.demo.jsonDemo.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Controller;
import java.text.SimpleDateFormat;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/7 22:13
*/
@Configuration
public class WebMvcConfig {
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
MappingJackson2HttpMessageConverter cborHttpMessageConverter =
new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd"));
cborHttpMessageConverter.setObjectMapper(objectMapper);
return cborHttpMessageConverter;
}
@Bean
public ObjectMapper objectMapper(){
return new ObjectMapper().setDateFormat(new SimpleDateFormat("yyyy/MM/dd"));
}
}
同源策略:安全策略,是浏览器最核心最基本的安全功能,现在所有支持JavaScript的浏览器都会使用这个策略,它是浏览器最核心的功能,所谓同源就是指协议,域名已及端口号都要相同,同源策略是出于安全方面的考虑.在实际开发开发中,需要实现跨域的请求,
对于跨域的解决方案有基于前端的JSONP,但JSONP有局限性,即只支持GET请求,不支持其他类型的请求,
CORS(跨域资源共享):是一个W3C标准,他是浏览器技术规范,提供了web服务器重不同的网域传来沙盒脚本的方法.避开浏览器的同源策略.spring框架中对CORS提供了相应的解决办法,
建立两个springboot项目实现前后端分离.
package com.example.demo.xmlDemo;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
* @Description : 基于xml装配bean
* @Author: Liruilong
* @Date: 2019/10/18 13:42
*/
@Configuration
@ImportResource(locations = "classpath:beans.xml")
public class webMvcConfig {
}
系统启动任务只执行一次,可以获取系统参数,多个时按照优先级执行
package com.example.demo.applicationrunerApplication;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/20 0:44
*/
@Component
@Order(5)
public class MycommandLineRunner2 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner2" + Arrays.toString(args));
}
}
package com.example.demo.applicationrunerApplication;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/20 0:42
*/
@Component
@Order(7)// 默认的优先级最低,
public class MycommandLineRunnerl implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner1" + Arrays.toString(args));
}
}
package com.example.demo.applicationrunerApplication;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/18 16:59
*/
@Component
@Order(99)
public class MyApplicationRunner01 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 获取启动的所有参数
String[] sourceArgs = args.getSourceArgs();
System.out.println(Arrays.toString(sourceArgs));
// 获取所有的值
args.getNonOptionArgs().stream().forEach(System.out::print);
args.getOptionNames();
args.getOptionValues("");
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>");
// 获取键值对
args.getOptionNames().stream().forEach((option)->{
System.out.println(option + ":" + args.getOptionValues(option));
});
}
}
//系统启动任务,在系统启动时执行的任务,
package com.example.demo.urlMaping;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/10/20 21:31
*/
@Configuration
public class WebMvcConfgi implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 不经过Controller处理直接到视图
registry.addViewController("/Demos").setViewName("urlMaping");
}
}
package com.example.demo.AOP;
import org.springframework.stereotype.Service;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/11/24 14:42
*/
@Service
public class Userservice {
public String getUserNameById( Integer id){
return "嗯,执行方法";
}
public String deleteUserById(Integer id){
return "deleteUserById";
}
}
package com.example.demo.AOP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/11/24 14:42
*/
@RestController
public class UserController {
@Autowired
Userservice userservice;
@GetMapping("/test1")
public String getUserNameById(Integer id){
return userservice.getUserNameById(id);
}
@GetMapping("/test2")
public String deleteUserById(Integer id){
return userservice.deleteUserById(id);
}
}
package com.example.demo.AOP;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @Description :
* @Author: Liruilong
* @Date: 2019/11/24 14:54
*/
@Component
@Aspect
public class LogComponent {
@Pointcut("execution( * com.example.demo.AOP.*.*(..))")
public void pe1(){
}
// 前置通知
@Before(value = "pe1()")
public void before(JoinPoint jp){
String name = jp.getSignature().getName();
System.out.println("前置通知" + name);
}
// 后置通知
@After(value = "pe1()")
public void after(JoinPoint jp){
String name = jp.getSignature().getName();
System.out.println( "后置通知" + name);
}
// 后置返回通知
@AfterReturning(value = "pe1()", returning = "result")
public void afterReturning(JoinPoint jp, Object result){
String name = jp.getSignature().getName();
System.out.println("后置返回通知:" + name );
}
@AfterThrowing(value = "pe1()", throwing = "e")
public void afterThrow(JoinPoint jp, Exception e){
String name = jp.getSignature().getName();
System.out.println("异常通知:" + name +":"+ e.getMessage());
}
// 环绕通知
@Around("pe1()" )
public Object around(ProceedingJoinPoint pjp) throws Throwable{
//前置
System.out.println("环绕前---------------");
Object proved = pjp.proceed();
//后置
System.out.println("环绕后----------------");
return "liruilong";
}
}
https://tool.lu/favicon/
项目实战:
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法
romise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
let p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成Promise');
resolve('要返回的数据可以任何数据例如接口返回数据');
}, 2000);
});
resolve是对promise成功时候的回调,它把promise的状态修改为fullfiled,
reject就是失败的时候的回调,他把promise的状态修改为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。
function promiseClick(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
}
promiseClick().then(
function(data){
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
},
function(reason, data){
console.log('rejected失败回调');
console.log('失败执行回调抛出失败原因:',reason);
}
);
以上代码:调用promiseClick方法执行,2秒后获取到一个随机数,如果小于10,我们算成功,调用resolve修改Promise的状态为fullfiled。否则我们认为是“失败”了,调用reject并传递一个参数,作为失败的原因。并将状态改成rejected
运行promiseClick并且在then中传了两个参数,这两个参数分别是两个函数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。(也就是说then方法中接受两个回调,一个成功的回调函数,一个失败的回调函数,并且能在回调函数中拿到成功的数据和失败的原因),所以我们能够分别拿到成功和失败传过来的数据就有以上的运行结果
nodejs:
同样nodejs的作用和jvm的一样一样的,也是js的运行环境,不管是你是什么操作系统,
只要安装对应版本的nodejs,那你就可以用js来开发后台程序。
axios 简介:
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
axios({
methods: 'post',
url: 'http://jsonplaceholder.typicode.com/users',
data: {
name: 'qiurx'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
function getUserAccount() {
return axios.get('/user/12345'); //请求1
}
function getUserPermissions() {
return axios.get('/user/12345/permissions'); //请求2
}
axios.all([getUserAccount(), getUserPermissions()]) //两个请求放到数组中传递给all()
.then(axios.spread(function (acct, perms) { //多个请求都发送完毕,拿到返回的数据
// 两个请求现在都执行完成
}));