一、自定义属性配置
-
通过@Value注解读取(配置项比较少的时候)
developer.name=wangxiangqian
@Controller public class IndexController { @Value("${developer.name}") private String user; @RequestMapping(value = "/say") public @ResponseBody String say(){ return user; } }
-
通过映射类读取(配置项目比较多的时候)
school.name=xiwangxiaoxue school.webist=www.wangxiangqian.com
@Component @ConfigurationProperties(prefix = "school") public class School { private String name; private String webist; public School() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getWebist() { return webist; } public void setWebist(String webist) { this.webist = webist; } }
@Controller public class IndexController { @Autowired private School school; @RequestMapping(value = "/say") public @ResponseBody String say(){ return school.getName()+"----------"+school.getWebist(); } }
-
通过Environment对象读取(spring ioc 直接就给我们创建了该对象)
@Autowired Environment env; @GetMapping("/user") Public String user() { StringBuilder sb = new StringBuilder(); sb.append("从Environment中获取配置:\n"); sb.append(env.getProperty("myconfig.user.name"));//注意这里不加${} return sb.toString(); }
-
通过嵌套静态内部类读取(参考server.前缀的方式)
二、集成JSP
-
添加依赖
<!--引入SpringBoot内嵌Tomcat对jsp的解析依赖,不添加解析不了jsp--> <!--仅仅只是展示jsp页面,只添加以下一个依赖--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency>
-
指定编译路径
<!-- Springboot项目默认推荐使用的前端引擎是thymeleaf 现在我们要使用springboot集成jsp,手动指定jsp最后编译的路径 而且springboot集成jsp编译jsp的路径是springboot规定好的位置 META-INF/resources --> <resources> <resource> <!--源文夹--> <directory>src/main/webapp</directory> <!--指定编译到META-INF/resources--> <targetPath>META-INF/resources</targetPath> <!--指定源文件夹中的哪个资源要编译进行--> <includes> <include>*.*</include> </includes> </resource> </resources>
-
配置视图解析器
spring.mvc.view.prefix=/ spring.mvc.view.suffix=.jsp
三、集成Mybatis
-
添加依赖
<!--MySQL驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <!--<version>5.1.9</version>--> </dependency> <!--MyBatis整合SpringBoot框架的起步依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency>
-
mybatis逆向工程
-
添加插件
<!--mybatis 代码自动生成插件--> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.6</version> <configuration> <!--配置文件的位置--> <configurationFile>GeneratorMapper.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> </plugin>
-
逆向工程文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- 指定连接数据库的 JDBC 驱动包所在位置,指定到你本机的完整路径 --> <classPathEntry location="D:\mysql-connector-java-5.1.38.jar"/> <!-- 配置 table 表信息内容体,targetRuntime 指定采用 MyBatis3 的版本 --> <context id="tables" targetRuntime="MyBatis3"> <!-- 抑制生成注释,由于生成的注释都是英文的,可以不让它生成 --> <commentGenerator> <property name="suppressAllComments" value="true"/> </commentGenerator> <!-- 配置数据库连接信息 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://192.168.154.128:3306/springboot" userId="root" password="123"> </jdbcConnection> <!-- 生成 model 类,targetPackage 指定 model 类的包名, targetProject 指定 生成的 model 放在 eclipse 的哪个工程下面--> <javaModelGenerator targetPackage="com.bjpowernode.springboot.model" targetProject="src/main/java"> <property name="enableSubPackages" value="false"/> <property name="trimStrings" value="false"/> </javaModelGenerator> <!-- 生成 MyBatis 的 Mapper.xml 文件,targetPackage 指定 mapper.xml 文件的 包名, targetProject 指定生成的 mapper.xml 放在 eclipse 的哪个工程下面 --> <sqlMapGenerator targetPackage="com.bjpowernode.springboot.mapper" targetProject="src/main/java"> <property name="enableSubPackages" value="false"/> </sqlMapGenerator> <!-- 生成 MyBatis 的 Mapper 接口类文件,targetPackage 指定 Mapper 接口类的包 名, targetProject 指定生成的 Mapper 接口放在 eclipse 的哪个工程下面 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.bjpowernode.springboot.mapper" targetProject="src/main/java"> <property name="enableSubPackages" value="false"/> </javaClientGenerator> <!-- 数据库表名及对应的 Java 模型类名 --> <table tableName="t_student" domainObjectName="Student" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> </context> </generatorConfiguration>
-
点击编译插件generator
-
-
手动指定资源文件夹
<!--手动指定文件夹为resources--> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources>
-
添加注解,将mapper对象放到容器中(两种方式)
@Mapper //扫描DAO接口到spring容器 public interface StudentMapper { int deleteByPrimaryKey(Integer id); int insert(Student record); int insertSelective(Student record); Student selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(Student record); int updateByPrimaryKey(Student record); }
@SpringBootApplication //开启spring配置 @MapperScan("com.bjpowernode.springboot.mapper") //开启扫描Mapper接口的包以及子目录 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
-
设置连接数据库的信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.154.128:3306/springboot?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=123
-
指定mybatis映射文件的路径(将mapper文件放到resources中)
mybatis.mapper-locations=classpath:mapper/*.xml
四、事务@Transactional
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper studentMapper;
@Transactional
@Override
public int updateStudentById(Student student) {
//修改成功
int i = studentMapper.updateByPrimaryKeySelective(student);
//失败
int a = 10/0;
return i;
}
}
五、集成SpringMVC常用注解
-
@RestController
//该方法请求方式支持:GET和POST请求 @RequestMapping(value = "/queryStudentById",method = {RequestMethod.GET,RequestMethod.POST}) public Object queryStudentById(Integer id) { Student student = new Student(); student.setId(id); return student; } // @RequestMapping(value = "/queryStudentById2",method = RequestMethod.GET) @GetMapping(value = "/queryStudentById2") //相当于上一句话,只接收GET请求,如果请求方式不对会报405错误 //该注解通过在查询数据的时候使用 -> 查询 public Object queryStudentById2() { return "Ony GET Method"; } // @RequestMapping(value = "/insert",method = RequestMethod.POST) @PostMapping(value = "/insert") //相当于一句话 //该注解通常在新增数据的时候使用 -> 新增 public Object insert() { return "Insert success"; } // @RequestMapping(value = "/delete",method = RequestMethod.DELETE) @DeleteMapping(value = "/delete")//相当于上一句话 //该注解通常在删除数据的时候使用 -> 删除 public Object delete() { return "delete Student"; } // @RequestMapping(value = "/update",method = RequestMethod.PUT) @PutMapping(value = "/update") //相当于上一句话 //该注解通常在修改数据的时候使用 -> 更新 public Object update() { return "update student info1"; }
六、RESTful风格
// @RequestMapping(value = "/student/detail/{id}/{age}")
@GetMapping(value = "/student/detail/{id}/{age}")
public Object student1(@PathVariable("id") Integer id,
@PathVariable("age") Integer age) {
Map<String,Object> retMap = new HashMap<>();
retMap.put("id",id);
retMap.put("age",age);
return retMap;
}
// @RequestMapping(value = "/student/detail/{id}/{status}")
@GetMapping(value = "/student/detail/{id}/{status}")
public Object student2(@PathVariable("id") Integer id,
@PathVariable("status") Integer status) {
Map<String,Object> retMap = new HashMap<>();
retMap.put("id",id);
retMap.put("status",status);
return retMap;
}
//以上代码student1和student2会出现请求路径冲突问题(可以通过请求方式区分)
//通常在RESTful风格中方法的请求方式会按增删改查的请求方式来区分
//修改请求路径
//RESUful请求风格要求路径中使用的单词都是名称,最好不要出现动词
@DeleteMapping(value = "/student/{id}/detail/{city}")
public Object student3(@PathVariable("id") Integer id,
@PathVariable("city") Integer city) {
Map<String,Object> retMap = new HashMap<>();
retMap.put("id",id);
retMap.put("city",city);
return retMap;
}
七、集成Redis
-
添加依赖
<!--SpringBoot集成Redis的起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
在核心配置文件添加redis的配置
spring.redis.host=192.168.154.128 spring.redis.port=6379 spring.redis.password=123456
-
依赖提供的redis模板对象
@Service public class StudentServiceImpl implements StudentService { @Autowired private RedisTemplate<Object,Object> redisTemplate; @Override public void put(String key, String value) { redisTemplate.opsForValue().set(key,value); } @Override public String get(String key) { String count = (String) redisTemplate.opsForValue().get(key); return count; } }
八、集成dubbo
-
服务提供者
<!--Dubbo集成SpringBoot起步依赖--> <dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <!--注册中心--> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency> <!--接口工程--> <dependency> <groupId>com.bjpowernode.springboot</groupId> <artifactId>023-springboot-dubbo-ssm-interface</artifactId> <version>1.0.0</version> </dependency>
#内嵌端口号 server.port=8081 #上下文根 server.servlet.context-path=/ #dubbo的配置 spring.application.name=024-springboot-dubbo-ssm-provider #当前工程是一个服务提供者 spring.dubbo.server=true #设置注册中心 spring.dubbo.registry=zookeeper://192.168.154.128:2181
@Component @Service(interfaceName = "com.bjpowernode.springboot.service.StudentService",version = "1.0.0",timeout = 15000) public class StudentServiceImpl implements StudentService {}
-
服务消费者
<!--Dubbo集成SpringBoot起步依赖--> <dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <!--注册中心--> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency> <!--接口工程--> <dependency> <groupId>com.bjpowernode.springboot</groupId> <artifactId>023-springboot-dubbo-ssm-interface</artifactId> <version>1.0.0</version> </dependency>
```yaml #内嵌端口号 server.port=8081 #上下文根 server.servlet.context-path=/ #dubbo的配置 spring.application.name=022-springboot-dubbo-ssm-consumer #设置注册中心 spring.dubbo.registry=zookeeper://192.168.154.128:2181 ```
@Reference(interfaceName = "com.bjpowernode.springboot.service.StudentService",version = "1.0.0",check = false) private StudentService studentService;
-
开启dubbo注解配置
@SpringBootApplication @EnableDubboConfiguration //开启dubbo配置 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
九、springboot java工程
- 直接获取ConfigurableApplication()
@SpringBootApplication public class Application { public static void main(String[] args) { /** * Springboot程序启动后,返回值是ConfigurableApplicationContext,它也是一个Spring容器 * 它其实相当于原来Spring容器中启动容器ClasspathXmlApplicationContext */ SpringApplication.run(Application.class, args); //获取Springboot容器 ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args); //从spring容器中获取指定bean对象 StudentService studentService = (StudentService) applicationContext.getBean("studentServiceImpl"); //调用业务方法 String sayHello = studentService.sayHello(); System.out.println(sayHello); }
- 实现CommandLineRuner,重写run方法
@SpringBootApplication //开启spring配置 public class Application implements CommandLineRunner { @Autowired private StudentService studentService; public static void main(String[] args) { //SpringBoot启动程序,会初始化Spring容器 SpringApplication.run(Application.class, args); } //重写CommandLineRunner类中的run方法 @Override public void run(String... args) throws Exception { //调用业务方法 String sayHello = studentService.sayHello("World"); System.out.println(sayHello); } }
十、关闭和修改LOGO
-
关闭logo
@SpringBootApplication public class Application { public static void main(String[] args) { // SpringApplication.run(Application.class,args); //获取入口SpringBoot类 SpringApplication springApplication = new SpringApplication(Application.class); //设置它的属性 springApplication.setBannerMode(Banner.Mode.OFF); springApplication.run(args); } }
-
修改logo
在 src/main/resources 放入 banner.txt 文件,该文件名字不能随意,文件中的内容就是要输出的 logo ;可以利用网站生成图标:https://www.bootschool.net/ascii 或 者
http://patorjk.com/software/taag/,将生成好的图标文字粘贴到 banner.txt 文件中,然后将关闭 logo 输出的语句注释,启动看效果
十一、拦截器
-
定义拦截器类
public class UserInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("进入拦截器------------------------------"); //编写业务拦截的规则 //从session中获取用户的信息 User user = (User) request.getSession().getAttribute("user"); //判断用户是否登录 if (null == user) { //未登录 response.sendRedirect(request.getContextPath() + "/user/error"); return false; } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
-
定义配置类
@Configuration //定义此类为配置文件(即相当于之前的xml配置文件) public class InterceptorConfig implements WebMvcConfigurer { //mvc:interceptors @Override public void addInterceptors(InterceptorRegistry registry) { //要拦截user下的所有访问请求,必须用户登录后才可访问, // 但是这样拦截的路径中有一些是不需要用户登录也可访问的 String[] addPathPatterns = { "/user/**" }; //要排除的路径,排除的路径说明不需要用户登录也可访问 String[] excludePathPatterns = { "/user/out", "/user/error","/user/login" }; //mvc:interceptor bean class="" registry.addInterceptor(new UserInterceptor()).addPathPatterns(addPathPatterns).excludePathPatterns(excludePathPatterns); } }
十二、使用servlet
-
第一种方式(注解方式)
@WebServlet(urlPatterns = "/myservlet") public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().println("My SpringBoot Servlet-1"); resp.getWriter().flush(); resp.getWriter().close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
@SpringBootApplication //开启spring配置 @ServletComponentScan(basePackages = "com.bjpowernode.springboot.servlet") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
-
第二种方式(通过配置类注册组件)
public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().println("My SpringBoot Servlet-2"); resp.getWriter().flush(); resp.getWriter().close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
@Configuration //该注解将此类定义为配置类(相当一个xml配置文件) public class ServletConfig { //@Bean是一个方法级别上的注解,主要用在配置类里 //相当于一个 // <beans> // <bean id="" class=""> // </beans> @Bean public ServletRegistrationBean myServletRegistrationBean() { ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new MyServlet(),"/myservlet"); return servletRegistrationBean; } }
十三、使用过滤器filter
-
注解方式
@WebFilter(urlPatterns = "/myfilter") public class MyFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("-------------------您已进入过滤器---------------------"); filterChain.doFilter(servletRequest, servletResponse); } }
@SpringBootApplication @ServletComponentScan(basePackages = "com.bjpowernode.springboot.filter") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
-
通过配置类注册组件
public class MyFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("-------------------您已进入过滤器-222-------------------"); filterChain.doFilter(servletRequest, servletResponse); } }
@Configuration //定义此类为配置类 public class FilterConfig { @Bean public FilterRegistrationBean myFilterRegistrationBean() { //注册过滤器 FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter()); //添加过滤路径 filterRegistrationBean.addUrlPatterns("/user/*"); return filterRegistrationBean; } }
十四、设置字符编码
-
配置类注册组件
@Configuration //将此类定义为配置文件 public class SystemConfig { @Bean public FilterRegistrationBean characterEncodingFilterRegistrationBean() { //创建字符编码过滤器 CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); //设置强制使用指定字符编码 characterEncodingFilter.setForceEncoding(true); //设置指定字符编码 characterEncodingFilter.setEncoding("UTF-8"); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); //设置字符编码过滤器 filterRegistrationBean.setFilter(characterEncodingFilter); //设置字符编码过滤器路径 filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } }
#关闭springboot的http字符集编码支持 #只有关闭该选项后,spring字符编码过滤器才生效 spring.http.encoding.enabled=false
-
修改核心配置文件
#设置请求响应字符编码 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.http.encoding.charset=utf-8
十五、SpringBoot打war包
-
pom指定打war包
<build> <!--指定打war包的字符--> <finalName>springboot</finalName> <resources> <resource> <directory>src/main/webapp</directory> <targetPath>META-INF/resources</targetPath> <includes> <include>*.*</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
-
构造新资源
@SpringBootApplication public class Application extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { //参数为当前springboot启动类 //构造新资源 return builder.sources(Application.class); } }
十六、springboot打jar包
-
修改编译插件的版本
<plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.4.2.RELEASE</version> </plugin> </plugins>
十七、集成logback日志
-
添加logback-spring.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <!-- 日志级别从低到高分为 TRACE < DEBUG < INFO < WARN < ERROR < FATAL, 如果设置为 WARN,则低于 WARN 的信息都不会输出 --> <!-- scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为true --> <!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认 单位是毫秒。当 scan 为 true 时,此属性生效。默认的时间间隔为 1 分钟。 --> <!-- debug:当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback 运行状态。默认值为 false。通常不打印 --> <configuration scan="true" scanPeriod="10 seconds"> <!--输出到控制台--> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <!--此日志 appender 是为开发使用,只配置最底级别,控制台输出的日志级别是大 于或等于此级别的日志信息--> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>debug</level> </filter> <encoder> <Pattern>%date [%5p] [%thread] %logger{60} [%file : %line] %msg%n </Pattern> <!-- 设置字符集 --> <charset>UTF-8</charset> </encoder> </appender> <!--单个定义--> <logger name="com.bjpowernode.springboot.mapper" level="trace"/> <!--如果root标签指定的日志级别那么以根日志级别为准,如果没有则已当前追加器日志级别为准--> <!--全部--> <!-- appender trace trace root trace appender trace debug root debug appender trace debug root 空 如果root没有值默认root级别是debug appender debug info root info --> <root level="info"> <appender-ref ref="CONSOLE"/> <!--<appender-ref ref="FILE"/>--> </root> </configuration>
-
添加依赖(使用注解时使用)
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
-
持久层添加注释
@Controller @Slf4j public class StudentController { @Autowired private StudentService studentService; private Logger log1; @RequestMapping(value = "/student/count") public @ResponseBody String studentCount() { log.trace("查询当前学生总人数"); log.debug("查询当前学生总人数"); log.info("查询当前学生总人数"); log.warn("查询当前学生总人数"); log.error("查询当前学生总人数"); Integer studentCount = studentService.queryStudentCount(); return "学生总人数为:" + studentCount; } }
十八、Thymeleaf模板引擎
-
关闭页面缓存
#设置thymeleaf模板引擎的缓存,设置为false关闭,默认为true开启 spring.thymeleaf.cache=false
-
设置thymeleaf前后缀
spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.htm
-
标准变量表达式和选择变量表达式
<h1>标准变量表达式:${} -> (推荐)</h1> 用户编号:<span th:text="${user.id}"></span><br/> 用户姓名:<span th:text="${user.username}"></span><br/> 用户年龄:<span th:text="${user.age}"></span><br/> <h1>选择变量表达式(星号表达式):*{} -> (不推荐)</h1> <!-- *{}必须使用th:object属性来绑定这个对象 在div子标签中使用*来代替绑定的对象${user} --> <div th:object="${user}"> 用户编号:<span th:text="*{id}"></span><br/> 用户姓名:<span th:text="*{username}"></span><br/> 用户年龄:<span th:text="*{age}"></span><br/> </div> <h1>标准变量表达式与选择变量表达式的混合使用(不推荐)</h1> 用户编号<span th:text="*{user.id}"></span><br/> 用户年龄<span th:text="*{user.age}"></span><br/> 用户姓名<span th:text="*{user.username}"></span><br/>
-
url路径表达式
<h1>URL路径表达式:@{....}</h1> <h2>a标签中的绝对路径(没有参数)</h2> <a href="http://www.baidu.com">传统写法:跳转至百度</a><br/> <a th:href="@{http://www.bjpowernode.com}">路径表达式:路径到动力节点</a><br/> <a th:href="@{http://localhost:8080/user/detail1}">跳转至:/user/detail1</a><br/> <a href="http://localhost:8080/user/detail1">传统写法跳转至:/user/detail1</a><br/> <h2>URL路径表达式,相对路径[没有参数](实际开发中推荐使用的)</h2> <a th:href="@{/user/detail1}">跳转至:/user/detail1</a><br/> <h2>绝对路径(带参数)(不推荐使用)</h2> <a href="http://localhost:8080/test?username='zhangsan'">绝对路径,带参数:/test,并带参数username</a><br/> <a th:href="@{http://localhost:8080/test?username=zhangsan}">路径表达工写法,带参数:/test,并带参数username</a><br/> <h2>相对路径(带参数)</h2> <a th:href="@{/test?username=lisi}">相对路径,带参数</a> <h2>相对路径(带参数:后台获取的参数值)</h2> <!--/test?username=1001--> <a th:href="@{'/test?username='+${id}}">相对路径:获取后台参数值</a> <h2>相对路径(带多个参数:后台获取的参数值)</h2> <!-- /test1?id=1001&username=zhaoliu&age=28 --> <a th:href="@{'/test1?id='+${id}+'&username='+${username}+'&age='+${age}}">相对路径(带多个参数:后台获取的参数值)</a> <a th:href="@{/test1(id=${id},username=${username},age=${age})}">强烈推荐使用:@{}相对路径(带多个参数:后台获取的参数值)</a><br/> <a th:href="@{'/test2/'+${id}}">请求路径为RESTful风格</a><br/> <a th:href="@{'/test3/'+${id}+'/'+${username}}">请求路径为RESTful风格</a><br/>
<script type="text/javascript" th:src="@{/js/jquery-1.7.2.min.js}"></script> <script type="text/javascript"> $(function () { alert("------"); alert($("#username").val()); }); </script> <input type="text" id="username" value="999"> <img th:src="@{/img/001.jpg}">
-
遍历list集合
<!-- user 当前循环的对象变量名称(随意) userStat 当前循环对象状态的变量(可选默认就是对象变量名称+Stat) ${userList} 当前循环的集合 --> <div th:each="user,userStat:${userList}"> <span th:text="${userStat.index}"></span> <span th:text="${userStat.count}"></span> <span th:text="${user.id}"></span> <span th:text="${user.nick}"></span> <span th:text="${user.phone}"></span> <span th:text="${user.address}"></span> </div> <div></div> <div th:each="user:${userList}"> <span th:text="${userStat.index}"></span> <span th:text="${userStat.count}"></span> <span th:text="${user.id}"></span> <span th:text="${user.nick}"></span> <span th:text="${user.phone}"></span> <span th:text="${user.address}"></span> </div>
-
遍历map集合
<div th:each="userMap,userMapStat:${userMaps}"> <span th:text="${userMapStat.count}"></span> <span th:text="${userMapStat.index}"></span> <span th:text="${userMap.key}"></span> <span th:text="${userMap.value}"></span> <span th:text="${userMap.value.id}"></span> <span th:text="${userMap.value.nick}"></span> <span th:text="${userMap.value.phone}"></span> <span th:text="${userMap.value.address}"></span> </div> <div> </div> <div th:each="userMap:${userMaps}"> <span th:text="${userMapStat.count}"></span> <span th:text="${userMapStat.index}"></span> <span th:text="${userMap.key}"></span> <span th:text="${userMap.value}"></span> <span th:text="${userMap.value.id}"></span> <span th:text="${userMap.value.nick}"></span> <span th:text="${userMap.value.phone}"></span> <span th:text="${userMap.value.address}"></span> </div>
-
遍历数组
<h1>循环遍历Array数组(使用方法同list一样)</h1> <div th:each="user,userStat:${userArray}"> <span th:text="${userStat.index}"></span> <span th:text="${userStat.count}"></span> <span th:text="${user.id}"></span> <span th:te7ext="${user.phone}"></span> <span th:text="${user.address}"></span> </div>
-
条件判断
<h1>th:if 用法:如果满足条件显示(执行),否则相反</h1> <div th:if="${sex eq 1}"> 男 </div> <div th:if="${sex eq 0}"> 女 </div> <h1>th:unless 用法:与th:if用法相反,即条件判断取反</h1> <div th:unless="${sex ne 1}"> 女 </div> <h1>th:switch/th:case用法</h1> <div th:switch="${productType}"> <span th:case="0">产品0</span> <span th:case="1">产品1</span> <span th:case="*">无此产品</span> </div>
-
内敛表达式
<body th:inline="text"> <h1>内敛文本: th:inline="text"</h1> <div th:inline="text"> 数据:[[${data}]] </div> 数据outside:[[${data}]] <h1>内敛脚本 th:inline="javascript"</h1> <script type="text/javascript" th:inline="javascript"> function showData() { alert([[${data}]]); alert("----"); } </script> <button th:onclick="showData()">展示数据</button>
-
字面量
不成功 </div> <h1>null字面量</h1> <span th:text="${user.id}"></span> <div th:unless="${userDetail eq null}"> 对象已创建,地址不为空 </div> <div th:if="${userDetail.id eq null}"> 空 </div>
-
字符串拼接
<h1>使用更优雅的方式来拼接字符串: |要拼接的字符串内容|</h1> <span th:text="|共${totalRows}条${totalPage}页,当前第${currentPage}页,首页 上一页 下一页 尾页|">共120条12页,当前第1页,首页 上一页 下一页 尾页</span>
-
数字运算
<!-- 三元运算 :表达式?” 正确结果”:” 错误结果” 算术运算: :+ , - , * , / , % 关系比较: :> , < , >= , <= ( gt , lt , ge , le ) 相等判断: :== , != ( eq , ne ) ne -> not equal eq -> equal ge -> great equal le -> little equal gt -> great lt -> little --> <h1>三元运算符 表达式?正确:错误</h1> <div th:text="${sex eq 1 ? '男':'女'}"></div> <div th:text="${sex == 1 ? '男':'女'}"></div> <h1>算术运算</h1> 20+5=<span th:text="20+5"></span><br/> 20-5=<span th:text="20-5"></span><br/> 20*5=<span th:text="20*5"></span><br/> 20/5=<span th:text="20/5"></span><br/> 20%3=<span th:text="20%3"></span><br/> <h1>关系比较</h1> 5>2为<span th:if="5 gt 2">真</span><br/> 5>2为<span th:if="5 > 2">真</span><br/> 5<2<span th:unless="5 lt 2">真</span><br/> 5<2<span th:unless="5 < 2">真</span><br/> 1>=1<span th:if="1 ge 1">真</span><br/> 1>=1<span th:if="1 >= 1">真</span><br/> 1<=1<span th:if="1 le 1">真</span><br/> 1<=1<span th:if="1 <= 1">真</span><br/> <h1>相等判断</h1> <span th:if="${sex == 1}">男</span> <span th:if="${sex eq 1}">男</span> <span th:unless="${sex ne 1}">女</span>
-
基本表达式对象
<h1>从SESSION中获取值</h1> <span th:text="${#session.getAttribute('data')}"></span><br/> <span th:text="${#httpSession.getAttribute('data')}"></span><br/> <span th:text="${session.data}"></span><br/> <script type="text/javascript" th:inline="javascript"> // http://localhost:8080/springboot/user/detail //获取协议名称 var scheme = [[${#request.getScheme()}]]; //获取服务器名称 var serverName = [[${#request.getServerName()}]]; //获取服务器端口号 var serverPort = [[${#request.getServerPort()}]]; //获取上下文根 var contextPath = [[${#request.getContextPath()}]]; var allPath = scheme + "://" +serverName+":"+serverPort+contextPath; var requestURL = [[${#httpServletRequest.requestURL}]]; var queryString = [[${#httpServletRequest.queryString}]]; var requestAddress = requestURL + "?" +queryString; alert(requestAddress); </script>
-
功能表达式对象
<div th:text="${time}"></div> <div th:text="${#dates.format(time,'yyyy-MM-dd HH:mm:ss')}"></div> <div th:text="${data}"></div> <div th:text="${#strings.substring(data,0,10)}"></div> <div th:text="${#lists}"></div>
十九、核心配置文件补充
#关闭logo
spring.mian.banner-mode=off
#项目类型 servlet表示web项目 nome表示java项目
spring-main.web-application-type=servlet
#指定配置类
spring-main-source=com.wangxiangqian.DemoApplication
#延迟初始化
spring.main.lazy-initialization=true
#配置随机值,通过配置文件得到一个随机值,springboot提供RandomValuePropertySource可用于注入随机值(例如,注入一些随机值或测试用例),它可以产生整数,longs,uuid或字符串,如下示例所示:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
#配置文件中可以使用占位符:
my.name = cat
my.desc = ${my.name} is a teacher.
#Duration单位转换
server.servlet.session.timeout=1800s
server.servlet.session.timeout=30m
server.servlet.session.timeout=PT30m
#DataSize 类型单位转换
server.tomcat.max-swallow-size=2048KB
二十、Jasypt敏感信息加密
-
依赖
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency>
-
密钥
#加密解密的密钥key jasypt.encryptor.password=1234 #加密信息 spring.datasource.username=ENC(44WdFjkoq6IQsutoeACsTAzdu8W6qPPbievCkJ36tJ9l5IYaVpkUK+NpPG9uPCFc) spring.datasource.password=ENC(4YGp/Ps1lrkf4dJfN85JLLY35lCMvrGJP39ucrw/8gO9G9NNCh8XiN0zABKQr0jF)
-
应用
@SpringBootTest class ApplicationTests { @Autowired private StringEncryptor stringEncryptor; @Test public void encryptPwd() { //加密 String username = stringEncryptor.encrypt("root"); System.out.println("加密username: " + username); String decUsername = stringEncryptor.decrypt(username); System.out.println("解密username: " + decUsername); //加密 String password = stringEncryptor.encrypt("123456"); System.out.println("password: " + password); String decPassword = stringEncryptor.decrypt(password); System.out.println("解密password: " + decPassword); } }
二十一、springboot数据库连接池
-
默认是HikariCP数据库连接池
-
修改数据库连接池(第一种方式)
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> <exclusions> <!--排除掉HikariCP数据库连接池--> <exclusion> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.23</version> </dependency>
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
-
修改数据库连接池(第二种方式)
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.23</version> </dependency>
二十二、SpringBoot跨域资源共享CORS支持
- 第一种方式
//设置配置bean @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/web/**"); registry.addMapping("/boot/**"); } }; }
- 第二种方式
@Configuration
public class MyConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/web/**");
registry.addMapping("/boot/**");
}
}
-
jsonp跨域请求
$.ajax({ type:"GET", url:"http://192.168.0.104:8080/boot/test", dataType : "jsonp", //返回的数据类型,设置为JSONP方式 jsonp : 'callback', //覆盖默认的 jsonp回调参数名callback jsonpCallback: 'handleResponse', //设置回调函数名 success: function(response, status, xhr){ console.log('状态为:' + status + ',状态是:' + xhr.statusText); console.log(response); }, error: function (XMLHttpRequest, textStatus, errorThrown) { // 状态码 console.log(XMLHttpRequest.status); // 状态 console.log(XMLHttpRequest.readyState); // 错误信息 console.log(textStatus); console.log(errorThrown); } }); }); function handleResponse(response){ console.log(response); }
@RequestMapping("/web/jsonp") public @ResponseBody Object jsonp(){ Map<String,String> map = new HashMap<>(); map.put("k1","v1"); map.put("k2","v3"); return handleResponse({\"k1\":\"v1\",\"k2\":\"v3\"}); }
-
CORS与JSONP比较
CORS与JSONP都是为了跨域,但是CORS比JSONP更强大;
JSONP只支持GET请求,CORS支持所有类型的HTTP请求;
JSONP的优势在于支持老式浏览器;
二十三、静态资源的处理
Spring Boot默认静态资源目录位置位于classpath下,目录名需符合如下规则:
有4个目录下的静态资源可以直接访问:
/static
/public
/resources
/META-INF/resources
#自己修改静态资源文件的位置
spring.resources.static-locations=classpath:/mysource/
二十四、SpringBoot开发最佳实践
1、SpringBoot 程序,每个类应该有一个包,没有包的话会出现问题;
2、一个合理的包结构:
3、我们通常建议您将主应用程序类放在其他类之上的根包中,主类上需要有一个@SpringBootApplication注解,默认是扫描当前包及子类下的标有@Component, @Service, @Repository, @Controller等注解的bean;
4、如果main类上不使用@SpringBootApplication注解,可以使用@EnableAutoConfiguration、@ComponentScan、@Configuration 注解代替;
5、main方法的类也是一个配置类,也是ioc容器中的一个bean,Springboot不推荐使用xml配置方式;
6、还可以通过@Import导入其他bean对象(组件),或者通过@Configuration加入bean组件,或者@Configuration+@Bean,或者@Configuration+@ComponentScan加入bean对象(组件);
7、也可以通过@ImportResource(locations = "classpath:applicationContext.xml")加入xml配置的bean对象(组件);
8、禁止某些自动配置:@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
或者在配置文件中 spring.autoconfigure.exclude= 进行排除,可以达到优化程序的效果;
9、springboot内嵌了web服务器,所以打成一个jar包即可运行,方便我们的开发和调试;
10、延迟初始化bean:spring.main.lazy-initialization=true
ApplicationContext context = new SpringApplicationBuilder()
.lazyInitialization(true)
.sources(com.bjpowernode.Application.class)
.bannerMode(Banner.Mode.CONSOLE)
.run(args);
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.setLazyInitialization(true);
如果要禁用某些bean的延迟初始化,则可以使用@Lazy(value=false)注解将它们的延迟属性显式设置为false;
SpringApplication启用延迟初始化后,将根据需要创建bean,而不是在应用程序启动期间创建bean,因此启用延迟初始化可以减少启动应用程序所需的时间。在Web应用程序中,启用延迟初始化将导致许多与Web相关的Bean直到收到HTTP请求后才被初始化。延迟初始化的缺点是,它可能会延迟发现应用程序的问题。如果错误地配置了Bean的延迟初始化,则可能导致启动时没有问题,在访问调用的时候出现问题,另外还必须注意确保JVM有足够的内存来容纳所有应用程序的bean,而不仅仅是启动过程中初始化的bean,由于这些原因,默认情况下SpringBoot不会开启延迟初始化;
11、CommandLineRunner, ApplicationRunner在springboot启动后回调着两个接口里面的run方法;
二十四、SpringBoot线程池异步调用
-
SpringBoot框架自动装配提供了一个的线程池,用于提交异步任务;
有了线程池我们就只需要写任务即可,提交任务采用@Async注解;(底层是aop)
Springboot自动装配提供的线程池还可以根据需要进行配置:#SpringBoot配置线程池,修改线程池默认配置 spring.task.execution.pool.max-size=99999 spring.task.execution.thread-name-prefix=cat-task- spring.task.execution.pool.queue-capacity=99999
-
我们也可以覆盖SpringBoot自动配置的线程池,用我们自定义的线程池:
@Bean public ThreadPoolTaskExecutor asyncExecutor() { logger.info("start asyncExecutor......"); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(16); //配置最大线程数 executor.setMaxPoolSize(64); //配置队列大小 executor.setQueueCapacity(9999); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix("async-order-"); // rejection-policy:当pool已经达到max pool size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是由调用线程(提交任务的线程)处理该任务 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; }