一. mybatis和数据库库的结合
1. 所需的maven依赖及配置
- 使用
MySQL
做底层数据库,因此需要使用mysql-connector-java
的jar包,实现JDBC
连接。 - 使用,
mybatis
将springboot
与数据库整合,需要使用mybatis-spring-boot-starter
的jar包。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
- 在
application.properties
中配置数据源信息:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/lucy?useUnicode = true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=lucylee
2. mybatis的整合流程
- 整合与调用流程,充分体现了
mvc
的思想。
① 创建实体类,为数据库中的表创建对应的model。
② 创建映射类,使用@Mapper
注解,实现常见的CRUD(create、retrieval、update、delete)
。
③ 创建serviec类,使用@Service
注解。使用@Autowired
注解实现映射类的自动装配,并消除getter/seteer
方法。
④ 创建Controller
类,使用@RestController
注解,负责处理用户请求,实现请求的url映射。会调用service类,实现对数据库的操作。 - 映射类实例:
@Mapper
public interface AuthorMapper {
@Insert("insert into t_author(real_name, nick_name) values(#{real_name}, #{nick_name})")
int add(@Param("realName") String realName, @Param("nickName") String nickName);
@Update("update t_author set real_name = #{real_name}, nick_name = #{nick_name} where id = #{id}")
int update(@Param("real_name") String realName, @Param("nick_name") String nickName, @Param("id") Long id);
@Delete("delete from t_author where id = #{id}")
int delete(Long id);
@Select("select id, real_name as realName, nick_name as nickName from t_author where id = #{id}")
Author findAuthor(@Param("id") Long id);
@Select("select id, real_name as realName, nick_name as nickName from t_author")
List<Author> findAuthorList();
}
3. mybatis的实现原理
-
mybatis
底层还是采用原生jdbc
来对数据库进行操作的,只是通过SqlSessionFactory,SqlSession Executor,StatementHandler,ParameterHandler,ResultHandler和TypeHandler
等几个处理器封装了这些过程。
-
引导层:引导层是配置和启动
MyBatis
配置信息的方式,MyBatis
提供两种方式来引导MyBatis
:基于XML配置文件的方式和基于Java API
的方式。 -
框架支持层:
① 事务管理机制:事务管理机制对于ORM(对象-关系映射)
框架而言是不可缺少的一部分
MyBatis
的事务管理分为两种形式:
(1)使用JDBC
的事务管理机制:即利用java.sql.Connection
对象完成对事务的提交(commit())、回滚(rollback())、关闭(close())
等;
(2)使用MANAGED
的事务管理机制:这种机制MyBatis
自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic
)来实现对事务的管理。
② 缓存机制:为了提高数据利用率和减小服务器和数据库的压力,MyBatis
会对于一些查询提供会话级别的数据缓存,会将对某一次查询,放置到SqlSession
中,在允许的时间间隔内,对于完全相同的查询,MyBatis 会直接将缓存结果返回给用户,而不用再到数据库中查找。
③ SQL
语句的配置方式:传统的MyBatis
配置SQL
语句方式就是使用XML
文件进行配置的,但是这种方式不能很好地支持面向接口编程的理念,为了支持面向接口的编程,MyBatis
引入了Mapper接口的概念,面向接口的引入,对使用注解来配置SQL 语句成为可能
,用户只需要在接口上添加必要的注解即可,不用再去配置XML文件了
,但是,目前的MyBatis
只是对注解配置SQL 语句提供了有限的支持
,某些高级功能还是要依赖XML配置文件配置SQL 语句
。
- 数据处理层:数据处理层可以说是
MyBatis
的核心,两大功能:a. 通过传入参数构建动态SQL语句;b. SQL语句的执行以及封装查询结果集成List。 - 接口层:
MyBatis
和数据库的交互有两种方式:a.使用传统的MyBatis提供的API;b. 使用Mapper接口
(我们用的就是这种)
参考链接:
《深入理解mybatis原理》 MyBatis的架构设计以及实例分析
Mybatis之工作原理
二. MVC的思想
1. 视图
- 视图是
用户看到并与之交互的界面
(它可以包括一些可以显示数据信息的页面,或者展示形式。例如jsp,html,asp,php)。 - 对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和象XHTML,XML/XSL,WML等一些标识语言和Web services.
MVC
一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式
。
2. 模型
- 模型表示
企业数据和业务规则
(可以说就是后端接口,用于业务处理
)。 - 在MVC的三个部件中,模型拥有最多的处理任务。例如操作数据库。
- 被模型返回的数据是中立的,就是说
模型与数据格式无关
,这样一个模型能为多个视图提供数据。 - 由于应用于
模型
的代码只需写一次就可以被多个视图重用
,所以减少了代码的重复性。
3. 控制器
- 控制器
接受用户的输入并调用模型和视图去完成用户的需求
(接受客户发送的请求
,根据请求调用所对应的接口
,然后模型业务处理后返回的数据
,由控制器决定调用那个View展示
)。 - 所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它
只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据
。
4. 关于模板引擎
ThymeLeaf
模板引擎的maven
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 网页中使用ThymeLeaf模板引擎:
<html lang="en" xmlns:th="http://www.thymeleaf.org">
- 整体介绍:
Thymeleaf
是 Web 和独立环境的现代服务器端 Java 模板引擎
,能够处理HTML,XML,JavaScript,CSS 甚至纯文本,是spring boot官方推荐模板引擎。
模板引擎原理图如下,模板引擎的作用都是将模板(页面)和数据进行整合然后输出显示
,区别在于不同的模板使用不同的语法,如 JSP 的 JSTL 表达式,以及 JSP 自己的表达式和语法,同理 Thymeleaf 也有自己的语法。
- 本科毕设时使用腾讯的
js模板引擎
:artTemplate
,它采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行性能,并且同时支持 NodeJS 和浏览器。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>basic-demo</title>
<script src="../dist/template.js"></script>
</head>
<body>
<div id="content"></div>
<script id="test" type="text/html">
{{if isAdmin}}
<h1>{{title}}</h1>
<ul>
{{each list as value i}}
<li>索引 {{i + 1}} :{{value}}</li>
{{/each}}
</ul>
{{/if}}
</script>
<script>
var data = {
title: '基本例子',
isAdmin: true,
list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;
</script>
</body>
</html>
参考链接:
总结一下MVC思想
三、云SDK
1. 对七牛云最大的感触
- 第一次接触云存储服务,听说过腾讯云、阿里云等云存储服务。
最简单的认识
:就是将我们的数据存储在云服务器上
。 - 将七牛云作为图片服务器,发现它
上传文件的编程比想象中的还要简单
。
@Service
public class QiniuService {
private static final Logger logger = LoggerFactory.getLogger(QiniuService.class);
//设置好账号的ACCESS_KEY和SECRET_KEY
String ACCESS_KEY = "q777AFqoeBvycQ07EXXl_LffIcBwMSgXBE2529VI";
String SECRET_KEY = "oJ2ac4KvxcrcscqKjzTI_GT-f8qj_6UDqznWFk3U";
//要上传的空间
String bucketname = "toutiao";
//密钥配置
Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
//创建上传对象
Configuration cfg = new Configuration(Zone.zone0());
UploadManager uploadManager = new UploadManager(cfg);
private static String QINIU_IMAGE_DOMAIN = "http://pp2fxkka4.bkt.clouddn.com/";
//简单上传,使用默认策略,只需要设置上传的空间名就可以了
public String getUpToken() {
return auth.uploadToken(bucketname);
}
public String saveImage(MultipartFile file) throws IOException {
try {
int dotPos = file.getOriginalFilename().lastIndexOf(".");
if (dotPos < 0) {
return null;
}
String fileExt = file.getOriginalFilename().substring(dotPos + 1).toLowerCase();
if (!ToutiaoUtil.isFileAllowed(fileExt)) {
return null;
}
String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileExt;
//调用put方法上传
Response res = uploadManager.put(file.getBytes(), fileName, getUpToken());
//打印返回的信息
if (res.isOK() && res.isJson()) {
return QINIU_IMAGE_DOMAIN + JSONObject.parseObject(res.bodyString()).get("key");
} else {
logger.error("七牛异常:" + res.bodyString());
return null;
}
} catch (QiniuException e) {
// 请求失败时打印的异常的信息
logger.error("七牛异常:" + e.getMessage());
return null;
}
}
}
- 在学习的过程中,发现有
实时缩图
的功能,七牛云提供了图片处理接口,其中的imageView2
:图片基本处理接口可对图片进行缩略操作
,生成各种缩略图,十分方便!参考链接:图片基本处理 - 这些云SDK都有非常
完善的技术文档
,学习和使用起来非常的方便。
四、AJAX的使用
1. 什么是AJAX?
Ajax
即“Asynchronous Javascript And XML
”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。- Ajax = 异步
JavaScript
和XML
或者是HTML
(标准通用标记语言的子集)。 - Ajax 是一种用于创建快速
动态网页
的技术。 - Ajax 是一种在无需重新加载整个网页的情况下,能够
更新部分网页
的技术。 - 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现
异步更新
。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。 - 传统的网页(不使用
Ajax
)如果需要更新内容,必须重载整个网页页面。 - 本科毕设中大量使用功能
AJAX
实现动态的数据加载、异步更新:基于BlinkDB的海量数据查询
,用户请求几乎都是通过AJAX
进行提交,有些请求结果使用artTemplate
进行展示。
2. AJAX原理
Ajax
的原理简单来说通过XmlHttpRequest
对象来向服务器发异步请求,从服务器获得数据,然后用javascript
来操作DOM(Document Object Model,文档对象模型)
而更新页面。HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法(接口)。
- 在同一个页面实现数据的动态加载:
- 考虑到使用原生
JavaScript
实现的Ajax
代码复杂、不简洁,本系统的实现将使用基于jQuery
的已经封装好的Ajax代码
。具体如下:
$.ajax(
type: 请求方式“post”或“get”,
async: 如果为true,表示异步请求;如果为false,表示同步请求,
data: 向服务器传递的数据,一般为JSON对象,
url: 发送请求的地址,比如Servlet类,
dataType: 服务器返回数据类型,比如html、XML、JSON,
success: function(data){
······//成功后的处理方法
},
error: function(data){
······//失败后的处理方法
}
});
五、Spring框架
1. spring框架
2. 依赖注入(Dependency Injection,DI)和控制反转(Inversion of Control,IOC)
-
一个系统的运作需要多个类的合作来实现业务逻辑,这导致在实际的运行过程中
某些对象会与其他对象具有相互关系
,这种相互关系叫做依赖关系
。 -
在传统的编程中,对象A依赖对象B,
对象A会主动创建对象B
。论是创建还是使用对象B,控制权都在对象A自己手上
。
-
在IoC中,由容器统一管理对象之间的依赖关系。
对象A不再主动去创建对象B
,而是被动等待,等待容器创建好对象B后反向的注入到自身
,即容器将依赖注入对象A中(DI
)。 -
对象A获得依赖对象B,从主动变成了被动,
控制权发生了颠倒
,因此叫控制反转
。
-
IoC的实质: 对依赖对象B的控制权转移到了容器中,体现了
The Hollywood Principle:Don't call us,we'll call you(别找我,我会来找你的)
。IoC的两种实现方式: 依赖注入和依赖查找。 -
所谓的依赖注入,就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。
-
IoC
和DI
之间的关系:依赖注入(DI)和控制反转(IoC)是从不同的角度描述的同一件事情
,IoC侧重于原理
,DI侧重于实现
。可以说,DI是IoC 的具体实现。 -
好处:对象从主动变为被动的等待IoC容器来创建并注入它所需要的资源,这样有效的分离了对象和它所需要的外部资源,使得它们
松散耦合
。有利于功能复用,更重要的是使得程序的体系结构变得非常灵活。 -
举例子:吃饭使用一次性筷子, 从主动买一次性筷子(new一格筷子对象)到由佣人每次都将一次性筷子送到我手上。、
-
对于spring配置一个bean时,如果需要给该bean提供一些初始化参数,则需要通过依赖注入方式,所谓的依赖注入就是通过spring将bean所需要的一些参数传递到bean实例对象的过程,
spring的常用依赖注入方法
:Setter方法注入
、构造器注入
、基于注解的注入
。 -
Setter方法注入:
<bean id="OutputHelper" class="com.yiibai.output.OutputHelper">
<property name="outputGenerator">
<ref bean="CsvOutputGenerator" />
</property>
</bean>
- 构造器注入注入:
<bean id="OutputHelper" class="com.yiibai.output.OutputHelper">
<constructor-arg>
<bean class="com.yiibai.output.impl.CsvOutputGenerator" />
</constructor-arg>
</bean>
@Autowired
自动装配:@Autowired
注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过@Autowired的使用来消除 getter/setter方法
,实现我们要精简程序的目的。
3. 面向切面编程(Aspect Oriented Programming,AOP)和AspectJ
AOP
技术利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来
,便于减少系统的重复代码,降低模块之间的耦合度
,并有利于未来的可操作性和可维护性。- 在一个系统中,我们会发现有很多业务都需要实现日志功能,方便后面的系统运行和维护。我们不可能为每个业务单独的去实现一个日志功能,这时候使用AOP将
日志功能
封装为“切面”,这个切面会自动捕获所有的业务在运行时调用的方法,然后为这些方法记录日志。
- AOP的几个重要概念:
1. 横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2. 切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
3. 连接点(joinpoint):被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4. 切入点(pointcut):对连接点进行拦截的定义
5. 通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知
五类。
6. 目标对象:代理的目标对象
7. 织入(weave):将切面应用到目标对象并导致代理对象创建的过程
8. 引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。
AOP
的一种实现方式:@AspectJ注解驱动的切面
,使用时需要在pom文件中添maven依赖:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
- 常用的
AspectJ
注解,其实就是Advice的五种类型:
@Before
– 方法执行前运行;
@After
– 运行在方法返回结果后;
@AfterReturning
– 运行在方法返回一个结果后,在拦截器返回结果;
@AfterThrowing
– 运行方法在抛出异常后;
@Around
– 围绕方法执行运行,结合以上这三个通知。 - 具体的编程实例:
@Aspect
@Component
public class LogAspect {
private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Before("execution(* com.newcoder.toutiao.controller.*Controller.*(..))")
public void beforeMethod(JoinPoint joinPoint){
StringBuilder sb = new StringBuilder();
for (Object arg : joinPoint.getArgs()){
sb.append(arg.toString() + "|");
}
logger.info("beforeMethod:" + sb.toString());
}
@After("execution(* com.newcoder.toutiao.controller.*Controller.*(..))")
public void afterMethod(){
logger.info("afterMethod:");
}
}
4. 拦截器(interceptor)
- 个人觉得拦截器和AOP有异曲同工之处,拦截器会在
请求后、controller之前
,controller之后、渲染之前
做一些业务逻辑的处理。
- 实现流程:
① 创建一个类实现HandlerInterceptor
接口,重写接口的方法,使用@Component
注解
② 创建一个类继承WebMvcConfigurerAdapter
类并重写addInterceptors
方法,在addInterceptors中注册拦截器
,使用@Configuration
注解。
@Component
public class LoginRequiredInterceptor implements HandlerInterceptor {
@Autowired
private HostHolder hostHolder;
/**
* 预处理回调方法,实现处理器的预处理
* 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
if (hostHolder.getUser() == null) {
httpServletResponse.sendRedirect("/home");
return false;
}
return true;
}
/**
* 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
* 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
*/
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, ModelAndView modelAndView) throws Exception {
}
/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
* 如性能监控中我们可以在此记录结束时间并输出消耗时间,
* 还可以进行一些资源清理,类似于try-catch-finally中的finally,
* 但仅调用处理器执行链中
*/
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
}
//要使用@Configuration注解
@Configuration
public class ToutiaoWebConfiguration extends WebMvcConfigurationSupport {
@Autowired
PassportInterceptor passportInterceptor;
@Autowired
LoginRequiredInterceptor loginRequiredInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//判断用户是否合法
registry.addInterceptor(passportInterceptor);
//判断用户是否有权限访问页面
registry.addInterceptor(loginRequiredInterceptor).addPathPatterns("/setting*");
super.addInterceptors(registry);
}
}
5. spring中的重要注解
注解 | 使用环境 | 作用 |
---|---|---|
@Mappper | spring boot整合mybatis,dao层(持久层) | 使用@Mapper将dao接口交给Spring进行管理,不用写Mapper映射文件(XML),自动为这个dao接口生成一个实现类,让别的类进行引用 |
@Service | 服务层 | 服务层组件,用于标注业务层组件 |
@Controller | 控制层 | 控制层组件,用于标注控制层组件 |
@RestController | 控制层 | 是@Controller和@ResponseBody的结合体,两个标注合并起来的作用。@Controller, @RestController都是用来表示Spring某个类的是否可以接收HTTP请求 |
@Repository | dao层(持久层) | 持久层组件,用于标注数据访问组件,即dao(data access object)组件 |
@Repository | dao层(持久层) | 持久层组件,用于标注数据访问组件,即dao(data access object)组件 |
@component | 泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services、 @Mappper 等的时候),我们就可以使用@Component来标注这个类。他可以把普通pojoPlain Ordinary Java Object,简单的Java对象)实例化到spring容器中,相当于配置文件中的bean标签 | |
@Autowired | 在类中定义其他类的对象时 | 自动装配: @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过@Autowired的使用来消除 getter/setter方法,实现我们要精简程序的目的。 |
@Configuration | 配置类 | @Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。 |
六、其他
1. 重定向
- 重定向中的
301表示永久性转移
,下次直接跳转到新的页面不用请求server;302表示临时性转移
。
@RequestMapping(value = "/redirect/{code}")
public void redirect(@PathVariable("code")int code,
HttpServletResponse response, HttpSession session){
System.out.println("redirect ...");
/*RedirectView redirectView = new RedirectView("/",true);
if (code == 301){
redirectView.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
}
return redirectView;*/
/*通过redirect告诉浏览器实现跳转,由于Spring Boot使用了@RestController注解,
* 这样的写法只能返回字符串:return "redirect:/"
* 需要使用HttpServletResponse实现重定向*/
//return "redirect:/";
session.setAttribute("name", "lucy");
try {
response.sendRedirect("/");
}catch (IOException e){
e.printStackTrace();
}
}
2. Redis
Redis
是key-value数据库
(NoSQL
数据库),数据存储在内存,性能卓越。官网命令
① Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
② Redis 与其他 key - value 缓存产品相比有以下三个特点:
(1)Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
(2)Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
(3)Redis支持数据的备份,即master-slave模式的数据备份。
③ Redis 优势:
(1)性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
(2)丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
(3)原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。
(4)多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
(5)丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
- 使用
Jedis封装了对Redis的操作
,引入Jedis
可以方便的对Redis
进行访问,建议使用!
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.0</version>
</dependency>
- Redis的两种持久化方法:
RDB(Redis DataBase)
和AOF(Append Only File)
。 - Redis
默认使用RDB
,指定时间间隔T,数据自动从内存写入磁盘。重启Redis
时读取磁盘上的数据,如dump.rdb。 AOF
使用日志
的形式记录每个写操作
,将写操作追加到文件中,重启Redis
后会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。牛客中Redis的使用场景:
PV(page view,页面浏览量)、点赞、关注、排行榜、验证码(使用setex实现验证码的有效期限制)、缓存、异步队列、判题队列。Redis
中默支持16个数据库,编号0-15
,可以使用select num
的方式进行数据库的选择。- Redis中的pool,防止
BLPOP
这样的方法阻塞线程
。使用注意:如果通过pool获取资源后不关闭连接,最多只能开启8个pool,编号0-7
。(Redis中所有的编号都是从0开始
)
private JedisPool jedisPool = null;
public String get(String key) {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 设置最大10个连接
jedisPoolConfig.setMaxTotal(10);
jedisPool = new JedisPool(jedisPoolConfig, "localhost", 6379);
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.get(key);
} catch (Exception e) {
logger.error("发生异常" + e.getMessage());
return null;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
3. 返回json数据乱码的解决
@RequestMapping(path = {"/news/{newsId}"}, method = {RequestMethod.GET, RequestMethod.POST},
produces = {"application/json;charset=utf-8"})
public ModelAndView newsDetail(@PathVariable(name = "newsId")int newId) {
News news = newsService.getNews(newId);
if (news != null){
//评论
}
User user = userService.getUser(news.getUser_id());
ModelAndView modelAndView = new ModelAndView("/detail");
modelAndView.addObject("news", news);
modelAndView.addObject("user", user );
return modelAndView;
//return "资讯详情页";
}