【坐在沙发上看电视,女友洗完澡出来蛮开心的问我,亲爱的:为什么洗完澡总觉得自己漂亮了好多?我问她:你洗澡的时候洗了头吧?她说:是啊!我回答说:那肯定是脑子进水了…刚说完这句我就后悔了,看着女票的脸色,我想静静…】
SpringBoot整合其它技术大合集???
本篇文章是《一步一步学SpringBoot(二)》教学视频的简单课件,内容不是很详细,想了解全部内容,可以到上面的视频地址观看学习。
preHandle****:**预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);
返回值:true表示继续流程(如调用下一个拦截器或处理器);
false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle****:**后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion****: 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion 。
public class WebAppConfig extends WebMvcConfigurerAdapter
具体类如下:
package com.example.interceptor.test; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Created by Ay on 2017/8/23. */ @Configuration public class InterceptorConfig extends WebMvcConfigurerAdapter { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new UserSecurityInterceptor()).addPathPatterns("/springdata/*"); } }
public void addInterceptors(InterceptorRegistry registry){ }
registry.addInterceptor可以通过此方法添加拦截器, 可以是spring提供的或者自己添加的
具体类如下:
package com.example.interceptor.test; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Created by Ay on 2017/8/23. */ public class UserSecurityInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception { //业务处理 System.out.println("preHandle"); return true; } @Override public void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { //业务处理 System.out.println("postHandle"); } @Override public void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception { //业务处理 System.out.println("afterCompletion"); } }
具体类如下:
package com.example.interceptor.test; import io.swagger.annotations.ApiOperation; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author Ay * @date 2017/1/24. */ @RestController @RequestMapping(value="/springdata") @EnableAutoConfiguration @EnableScheduling public class AyInterceptorsTestController { @RequestMapping("/ay") @ApiOperation(value = "ay",httpMethod ="GET", response = String.class,notes = "index") public String index(){ return "Hello Ay..."; } @RequestMapping("/test") @ApiOperation(value = "test",httpMethod ="GET", response = String.class,notes = "index") public String test(){ return "Hello Ay..."; } }
假如你已经安装好了mongoDB数据库,并新建了一个test数据库。那么开始吧
1)pom文件添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
2)创建实体
package com.example.mongodb.test; import org.springframework.data.mongodb.core.mapping.Document; import javax.persistence.Id; /** * 描述: * @author Ay * @date 2017/08/22 */ @Document public class AyTest { @Id private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
3)服务层
package com.example.mongodb.test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.stereotype.Component; import java.util.List; /** * Created by Ay on 2017/8/23. */ @Component public class UserDaoImpl { @Autowired private MongoTemplate mongoTemplate; public void save(){ AyTest ayTest = new AyTest(); ayTest.setId("2"); ayTest.setName("al"); mongoTemplate.save(ayTest); } }
###mongodb spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.database=test
package com.example.mongodb.test; import com.example.intellij.test.AyTest; import com.example.intellij.test.AyTestService; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; /** * Created by Ay on 2017/1/24. */ @RestController @RequestMapping("/mongo") public class MongoDBTestController { @Autowired private UserDaoImpl userDaoImpl; @RequestMapping("/al") public String index2(){ userDaoImpl.save(); return "Hello Ay..."; } }
1.不同环境配置可以配置不同的参数~
2.便于部署,提高效率,减少出错~
配置激活选项
spring.profiles.active=dev ### 代表使用开发环境
2.添加其他配置文件
application.properties:
#激活哪一个环境的配置文件 spring.profiles.active=dev
1)添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!-- 排查默认日志包 --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- 引入log4j2依赖 start--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <!-- 引入log4j2依赖 end-->
2)application.properties添加
logging.config=classpath:log4j2.xml
3)resources文件夹下添加文件 log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="Console" /> </Root> </Loggers> </Configuration>
4)测试下
package com.example.log4j2.test; import com.example.intellij.test.AyTestService; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * Created by Ay on 2017/1/24. */ @RestController @RequestMapping("/log4j2") public class Log4JTestController { @Autowired private AyTestService ayTestService; Logger logger = LogManager.getLogger(this.getClass()); @RequestMapping("/al") public String index2(){ logger.info("method start"); logger.equals("method start"); return "Hello Ay..."; } }
在Spring Boot中,当我们使用了spring-boot-starter-jdbc或spring-boot-starter-data-jpa依赖的时候,框 架会自动默认分别注入DataSourceTransactionManager或JpaTransactionManager。所以我们不需要任何额外 配置就可以用@Transactional注解进行事务的使用。
1)主要是@Transactional这个注解的使用
package com.example.transaction.test; import com.example.intellij.test.AyTest; import com.example.intellij.test.AyTestService; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; /** * Created by Ay on 2017/1/24. */ @RestController @RequestMapping("/transaction") public class TransactionTestController { @Autowired private AyTestService ayTestService; @RequestMapping("/ay") @Transactional public String index() { AyTest ayTest = new AyTest(); ayTest.setId("1"); ayTest.setName("ay"); AyTest ayTest2 = new AyTest(); ayTest2.setId("2"); ayTest2.setName("al & ay"); AyTest ayTest3 = new AyTest(); ayTest3.setId("3"); ayTest3.setName("al"); ayTestService.insert(ayTest); ayTestService.insert(ayTest2); //这边出现异常 String s = null; s.split(","); ayTestService.insert(ayTest3); return "Hello Ay..."; } }
1)在resources/static文件夹下新建3个文件:401.html,404.html,500.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 我是一个漂亮的401 </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 我是一个漂亮的404 </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 我是一个漂亮的500 </body> </html>
2)开发配置类
package com.example.errorpage.test; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.web.servlet.ErrorPage; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; /** * Created by Ay on 2017/8/23. */ @Configuration public class ErrorPageConfig { @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html"); ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"); ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html"); container.addErrorPages(error401Page, error404Page, error500Page); } }; } }
略,可看我录制的《一步一步学SpringBoot(二)》教学视频
Druid是Java语言中最好的数据库连接池,并且能够提供强大的监控和扩展功能。
<!-- druid start --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.18</version> </dependency> <!-- druid end -->
#mysql配置信息 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test2 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # 下面为连接池的补充设置,应用到上面所有数据源中 # 初始化大小,最小,最大 spring.datasource.initialSize=5 spring.datasource.minIdle=5 spring.datasource.maxActive=20 # 配置获取连接等待超时的时间 spring.datasource.maxWait=60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 spring.datasource.timeBetweenEvictionRunsMillis=60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 spring.datasource.minEvictableIdleTimeMillis=300000 spring.datasource.validationQuery=SELECT 1 FROM DUAL spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false # 打开PSCache,并且指定每个连接上PSCache的大小 spring.datasource.poolPreparedStatements=true spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 spring.datasource.filters=stat,wall,log4j # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 合并多个DruidDataSource的监控数据 #spring.datasource.useGlobalDataSourceStat=true
package com.example.druid.test; import com.alibaba.druid.support.http.WebStatFilter; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; /** * druid过滤器. * @author Administrator * */ @WebFilter(filterName="druidWebStatFilter",urlPatterns="/*", initParams={ @WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源 } ) public class DruidStatFilter extends WebStatFilter { }
package com.example.druid.test; import com.alibaba.druid.support.http.StatViewServlet; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; /** * druid数据源状态监控. * @author Administrator * */ @WebServlet(urlPatterns="/druid/*", initParams={ @WebInitParam(name="allow",value="192.168.1.72,127.0.0.1"),// IP白名单 (没有配置或者为空,则允许所有访问) @WebInitParam(name="deny",value="192.168.1.73"),// IP黑名单 (存在共同时,deny优先于allow) @WebInitParam(name="loginUsername",value="admin"),// 用户名 @WebInitParam(name="loginPassword",value="123456"),// 密码 @WebInitParam(name="resetEnable",value="false")// 禁用HTML页面上的“Reset All”功能 } ) public class DruidStatViewServlet extends StatViewServlet { private static final long serialVersionUID = 1L; }
1)引入pom文件
<!-- spring-retry start --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> <!-- spring-retry start -->
2)自定义一个简单异常
package com.example.retry.test; /** * Created by Ay on 2017/8/22. */ public class BusinessException extends Exception{ }
3)服务类
package com.example.retry.test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Recover; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Component; @Component("remoteService") public class RemoteService { private static final Logger logger = LoggerFactory.getLogger(RemoteService.class); @Retryable(value= {BusinessException.class},maxAttempts = 5,backoff = @Backoff(delay = 5000,multiplier = 2)) public void call() throws Exception { logger.info("do something..."); throw new BusinessException(); } @Recover public void recover(BusinessException e) { //具体的业务逻辑 logger.info(" --------------------------- "); logger.info(e.getMessage()); } }
4)测试类
package com.example.retry.test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/retry") public class TestController { private static final Logger logger = LoggerFactory.getLogger(TestController.class); @Autowired private RemoteService remoteService; @RequestMapping("/test") public String login() throws Exception { remoteService.call(); return String.valueOf("11"); } }
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
2)新建model和数据库表
package com.example.springdata.test; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * 描述: * @author Ay * @date 2017/08/22 */ @Entity public class AyTest { @Id private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
3)新建UserRepository
package com.example.springdata.test; import org.springframework.data.repository.CrudRepository; import java.util.List; /** * @author Ay * @date 2017/08/22 */ public interface UserRepository extends CrudRepository<AyTest, String> { List<AyTest> findByIdAndName(String id, String name); }
4)测试类
package com.example.springdata.test; import com.example.intellij.test.Ay; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.UUID; /** * Created by Ay on 2017/1/24. */ @RestController @RequestMapping("/springdata") public class SpringDataController { @Autowired private UserRepository userRepository; @RequestMapping("/test") public String index() { AyTest ayTest = new AyTest(); ayTest.setId("60"); ayTest.setName("ay and al"); //select * from ay_test where id = '60' and name = "al" List<AyTest> ayTestList = userRepository.findByIdAndName("60","ay and al"); return "Hello Ay..."; } }
【1】 http://www.cnblogs.com/bianzy/p/5822426.html
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>1.3.5.RELEASE</version> </dependency>
首先要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。
@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
@ServerEndpoint(value = "/websocket") @Component public class MyWebSocket { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; /** * 连接建立成功调用的方法*/ @OnOpen public void onOpen(Session session) { this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在线数加1 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); try { sendMessage(CommonConstant.CURRENT_WANGING_NUMBER.toString()); } catch (IOException e) { System.out.println("IO异常"); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息*/ @OnMessage public void onMessage(String message, Session session) { System.out.println("来自客户端的消息:" + message); //群发消息 for (MyWebSocket item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * 发生错误时调用 @OnError public void onError(Session session, Throwable error) { System.out.println("发生错误"); error.printStackTrace(); } public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } /** * 群发自定义消息 * */ public static void sendInfo(String message) throws IOException { for (MyWebSocket item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { MyWebSocket.onlineCount++; } public static synchronized void subOnlineCount() { MyWebSocket.onlineCount--; } }
<!DOCTYPE HTML> <html> <head> <title>My WebSocket</title> </head> <body> Welcome<br/> <input id="text" type="text" /><button onclick="send()">Send</button> <button onclick="closeWebSocket()">Close</button> <div id="message"> </div> </body> <script type="text/javascript"> var websocket = null; //判断当前浏览器是否支持WebSocket if('WebSocket' in window){ websocket = new WebSocket("ws://localhost:8084/websocket"); } else{ alert('Not support websocket') } //连接发生错误的回调方法 websocket.onerror = function(){ setMessageInnerHTML("error"); }; //连接成功建立的回调方法 websocket.onopen = function(event){ setMessageInnerHTML("open"); } //接收到消息的回调方法 websocket.onmessage = function(event){ setMessageInnerHTML(event.data); } //连接关闭的回调方法 websocket.onclose = function(){ setMessageInnerHTML("close"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.close(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML){ document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //关闭连接 function closeWebSocket(){ websocket.close(); } //发送消息 function send(){ var message = document.getElementById('text').value; websocket.send(message); } </script> </html>
你的鼓励,我的动力,一分都是爱
来着《战狼2》
有个老人在河边钓鱼,一个小孩走过去看他钓鱼,老人技巧纯熟,所以没多久就钓上了满篓的鱼,老人见小孩很可爱,要把整篓的鱼送给他,小孩摇摇头,老人惊异的问道:「你为何不要?」小孩回答:「我想要你手中的钓竿。」老人问:「你要钓竿做什么?」小孩说:「这篓鱼没多久就吃完了,要是我有钓竿,我就可以自己钓,一辈子也吃不完。」
我想你一定会说:好聪明的小孩。错了,他如果只要钓竿,那他一条鱼也吃不到。因为,他不懂钓鱼的技巧,光有鱼竿是没用的,因为钓鱼重要的不在“钓竿”,而在“钓技”。
[有太多人认为自己拥有了人生道上的钓竿,再也无惧于路上的风雨,如此,难免会跌倒于泥泞地上。就如小孩看老人,以为只要有钓竿就有吃不完的鱼,像职员看老板,以为只要坐在办公室,就有滚进的财源。]
无
如果有带给你一丝丝小快乐,就让快乐继续传递下去,欢迎鼓励,点赞、顶、欢迎留下宝贵的意见、多谢支持!