在SpringBoot中使用JWT
JWT简介
简介
JSON Web token简称JWT, 是用于对应用程序上的用户进行身份验证的标记。也就是说, 使用 JWTS 的应用程序不再需要保存有关其用户的 cookie 或其他session数据。此特性便于可伸缩性, 同时保证应用程序的安全。
在身份验证过程中, 当用户使用其凭据成功登录时, 将返回 JSON Web token, 并且必须在本地保存 (通常在本地存储中)。每当用户要访问受保护的路由或资源 (端点) 时, 用户代理(user agent)必须连同请求一起发送 JWT, 通常在授权标头中使用Bearer schema。后端服务器接收到带有 JWT 的请求时, 首先要做的是验证token。
JWT的格式
JWT就是一个字符串,经过加密处理与校验处理的字符串,形式为:A.B.C
A由JWT头部信息header加密得到
B由JWT用到的身份验证信息json数据加密得到
C由A和B加密得到,是校验部分
怎样使用token?
可以放到HTTP请求的请求头中,通常是Authorization字段。
流程图

JWT 实战
加入Maven jwt 依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
在application.proterties中加入配置
# 加密yan
jwt.secret=A0B1C2D3E4F5G6H7I8J9KALBMCNDOEPFQ0R1S2T3U4V5W6X7Y8Z9
# tocken 过期时间,单位秒
jwt.expire=300
# 需要认证的url,多个URL使用英文逗号,分割
jwt.authorised-urls=/apis/fis/redis/**
JwtHelper工具类
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class JwtHelper {
private Long EXPIRATION_TIME;
private String SECRET;
private final String TOKEN_PREFIX = "Bearer";
private final String HEADER_STRING = "Authorization";
public JwtHelper(<span class="hljs-built_in"><span class="hljs-built_in">String</span></span> secret, long expire) {
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.EXPIRATION_TIME = expire;
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.SECRET = secret;
System.out.println(<span class="hljs-string"><span class="hljs-string">"正在初始化Jwthelper,expire="</span></span>+expire);
}
public JSONObject generateToken(<span class="hljs-built_in"><span class="hljs-built_in">Map</span></span><<span class="hljs-built_in"><span class="hljs-built_in">String</span></span>, <span class="hljs-built_in"><span class="hljs-built_in">Object</span></span>> claims) {
Calendar c = Calendar.getInstance();
c.setTime(<span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-built_in"><span class="hljs-built_in">Date</span></span>());
c.add(Calendar.SECOND, EXPIRATION_TIME.intValue());
<span class="hljs-built_in"><span class="hljs-built_in">Date</span></span> d = c.getTime();
<span class="hljs-built_in"><span class="hljs-built_in">String</span></span> jwt = Jwts.builder()
.setClaims(claims)
.setExpiration(d)
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
JSONObject json = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JSONObject();
json.put(<span class="hljs-string"><span class="hljs-string">"token"</span></span>,TOKEN_PREFIX + <span class="hljs-string"><span class="hljs-string">" "</span></span> + jwt);
json.put(<span class="hljs-string"><span class="hljs-string">"token-type"</span></span>, TOKEN_PREFIX);
json.put(<span class="hljs-string"><span class="hljs-string">"expire-time"</span></span>,<span class="hljs-keyword"><span class="hljs-keyword">new</span></span> SimpleDateFormat(<span class="hljs-string"><span class="hljs-string">"yyyy-MM-dd HH:ss:mm"</span></span>).format(d) );
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> json;
}
public <span class="hljs-built_in"><span class="hljs-built_in">Map</span></span><<span class="hljs-built_in"><span class="hljs-built_in">String</span></span>, <span class="hljs-built_in"><span class="hljs-built_in">Object</span></span>> validateTokenAndGetClaims(HttpServletRequest request) {
<span class="hljs-built_in"><span class="hljs-built_in">String</span></span> token = request.getHeader(HEADER_STRING);
System.out.println(<span class="hljs-string"><span class="hljs-string">"token is:"</span></span>+token);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (token == <span class="hljs-literal"><span class="hljs-literal">null</span></span>) {
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-literal"><span class="hljs-literal">null</span></span>;
}
<span class="hljs-built_in"><span class="hljs-built_in">Map</span></span><<span class="hljs-built_in"><span class="hljs-built_in">String</span></span>, <span class="hljs-built_in"><span class="hljs-built_in">Object</span></span>> body = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, <span class="hljs-string"><span class="hljs-string">""</span></span>))
.getBody();
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> body;
}
}
JWT过滤器JwtFilter
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.util.AntPathMatcher;
/**
- JWT过滤器
- @author 李庆海
*/
public class JwtFilter implements Filter {
private JwtHelper jwtHelper;
private List<String> urls = null;
private static final org.springframework.util.PathMatcher pathMatcher = new AntPathMatcher();
public JwtFilter(JwtHelper jwtHelper, String[] authorisedUrls) {
this.jwtHelper = jwtHelper;
urls = Arrays.asList(authorisedUrls);
}
<span class="hljs-meta"><span class="hljs-meta">@Override</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">init</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(FilterConfig filterConfig)</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span><span class="hljs-function"> ServletException </span></span>{
<span class="hljs-comment"><span class="hljs-comment">//SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());</span></span>
}
<span class="hljs-meta"><span class="hljs-meta">@Override</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">doFilter</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(ServletRequest request, ServletResponse response, FilterChain chain)</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span><span class="hljs-function"> IOException, ServletException </span></span>{
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setCharacterEncoding(<span class="hljs-string"><span class="hljs-string">"UTF-8"</span></span>);
httpResponse.setContentType(<span class="hljs-string"><span class="hljs-string">"application/json; charset=utf-8"</span></span>);
httpResponse.setHeader(<span class="hljs-string"><span class="hljs-string">"Access-Control-Allow-Origin"</span></span>, <span class="hljs-string"><span class="hljs-string">"*"</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-string"><span class="hljs-string">"OPTIONS"</span></span>.equals(httpRequest.getMethod())) {
httpResponse.setStatus(HttpStatus.NO_CONTENT.value()); <span class="hljs-comment"><span class="hljs-comment">// HttpStatus.SC_NO_CONTENT = 204</span></span>
httpResponse.setHeader(<span class="hljs-string"><span class="hljs-string">"Access-Control-Allow-Credentials"</span></span>, <span class="hljs-string"><span class="hljs-string">"true"</span></span>);
httpResponse.setHeader(<span class="hljs-string"><span class="hljs-string">"Access-Control-Allow-Headers"</span></span>, <span class="hljs-string"><span class="hljs-string">"Content-Type, x-requested-with, Token"</span></span>);
httpResponse.setHeader(<span class="hljs-string"><span class="hljs-string">"Access-Control-Allow-Methods"</span></span>, <span class="hljs-string"><span class="hljs-string">"OPTIONS,GET,POST,DELETE,PUT"</span></span>);
}
String spath = httpRequest.getServletPath();
<span class="hljs-keyword"><span class="hljs-keyword">try</span></span> {
<span class="hljs-comment"><span class="hljs-comment">// 验证受保护的接口</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (String url : urls) {
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (pathMatcher.match(url, spath)) {
Object token = jwtHelper.validateTokenAndGetClaims(httpRequest);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (token != <span class="hljs-keyword"><span class="hljs-keyword">null</span></span>) {
chain.doFilter(request, response);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
}<span class="hljs-keyword"><span class="hljs-keyword">else</span></span>{
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, <span class="hljs-string"><span class="hljs-string">"未授权或者授权已经过期"</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
}
}<span class="hljs-keyword"><span class="hljs-keyword">else</span></span>{
chain.doFilter(request, response);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
}
}
} <span class="hljs-keyword"><span class="hljs-keyword">catch</span></span> (Exception e) {
e.printStackTrace();
}
chain.doFilter(request, response);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
}
<span class="hljs-meta"><span class="hljs-meta">@Override</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">destroy</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span><span class="hljs-function"> </span></span>{
}
}
配置JWT
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import cn.com.yd.fis.client.jwt.JwtFilter;
import cn.com.yd.fis.client.jwt.JwtHelper;
@Configuration
public class JwtConfig {
<span class="hljs-meta"><span class="hljs-meta">@Value</span></span>(<span class="hljs-string"><span class="hljs-string">"${jwt.secret}"</span></span>)
<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> String secret;
<span class="hljs-meta"><span class="hljs-meta">@Value</span></span>(<span class="hljs-string"><span class="hljs-string">"${jwt.expire}"</span></span>)
<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> <span class="hljs-keyword"><span class="hljs-keyword">long</span></span> expire;
<span class="hljs-meta"><span class="hljs-meta">@Value</span></span>(<span class="hljs-string"><span class="hljs-string">"${jwt.authorised-urls}"</span></span>)
<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> String[] authorisedUrls;
<span class="hljs-meta"><span class="hljs-meta">@Bean</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> JwtHelper </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">jwtHelperBean</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span><span class="hljs-function"> </span></span>{
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JwtHelper(secret, expire);
}
<span class="hljs-meta"><span class="hljs-meta">@Bean</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> FilterRegistrationBean </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">basicFilterRegistrationBean</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span><span class="hljs-function"> </span></span>{
FilterRegistrationBean registrationBean = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> FilterRegistrationBean();
JwtFilter filter = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JwtFilter(jwtHelperBean(), authorisedUrls);
registrationBean.setFilter(filter);
List<String> urlPatterns = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> ArrayList<String>();
urlPatterns.add(<span class="hljs-string"><span class="hljs-string">"/*"</span></span>);
registrationBean.setUrlPatterns(urlPatterns);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> registrationBean;
}
}
在Controller中使用JWT
此处仅为说明jwt的用法,在实际应用时可以根据具体的业务需要加入不同的或者更多的参数,一并作为claims进行参数传递。
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import cn.com.yd.fis.client.jwt.JwtHelper;
import cn.com.yd.fis.client.util.JsonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@RestController
@RequestMapping("${api-url}/auth")
public class AuthorizeController {
<span class="hljs-meta"><span class="hljs-meta">@Autowired</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> JwtHelper jwtHelper;
<span class="hljs-meta"><span class="hljs-meta">@PostMapping</span></span>(<span class="hljs-string"><span class="hljs-string">"/login"</span></span>)
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> Object </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">login</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(String loginName,String password)</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span><span class="hljs-function"> Exception </span></span>{
Map<String, Object> claims = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> HashMap<String, Object>();
claims.put(<span class="hljs-string"><span class="hljs-string">"loginName"</span></span>, loginName);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-string"><span class="hljs-string">"1"</span></span>.equals(password)) {
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> JsonResult.success(jwtHelper.generateToken(claims));
} <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> {
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> JsonResult.fail(<span class="hljs-string"><span class="hljs-string">"登录帐号或者登录密码错误"</span></span>);
}
}
}
辅助工具类JsonResult
import com.alibaba.fastjson.JSONObject;
public class JsonResult {
public static JSONObject success(Object obj) {
JSONObject json = new JSONObject();
json.put("state", true);
json.put("msg", "成功");
if (null != obj) {
json.put("obj", obj);
}
return json;
}
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span><span class="hljs-function"> JSONObject </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">fail</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(Object obj)</span></span></span><span class="hljs-function"> </span></span>{
JSONObject json = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JSONObject();
json.put(<span class="hljs-string"><span class="hljs-string">"state"</span></span>, <span class="hljs-keyword"><span class="hljs-keyword">false</span></span>);
json.put(<span class="hljs-string"><span class="hljs-string">"msg"</span></span>, <span class="hljs-string"><span class="hljs-string">"失败"</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">null</span></span> != obj) {
json.put(<span class="hljs-string"><span class="hljs-string">"obj"</span></span>, obj);
}
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> json;
}
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span><span class="hljs-function"> JSONObject </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">toJSONObject</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params"><span class="hljs-keyword">boolean</span></span></span></span><span class="hljs-function"><span class="hljs-params"> state, String msg, Object obj)</span></span></span><span class="hljs-function"> </span></span>{
JSONObject json = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JSONObject();
json.put(<span class="hljs-string"><span class="hljs-string">"state"</span></span>, state);
json.put(<span class="hljs-string"><span class="hljs-string">"msg"</span></span>, msg);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">null</span></span> != obj) {
json.put(<span class="hljs-string"><span class="hljs-string">"obj"</span></span>, obj);
}
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> json;
}
}
在SpringBoot中使用JWT的更多相关文章
- 如何在SpringBoot中集成JWT(JSON Web Token)鉴权
这篇博客主要是简单介绍了一下什么是JWT,以及如何在Spring Boot项目中使用JWT(JSON Web Token). 1.关于JWT 1.1 什么是JWT 老生常谈的开头,我们要用这样一种工具 ...
- SpringBoot系列 - 集成JWT实现接口权限认证
会飞的污熊 2018-01-22 16173 阅读 spring jwt springboot RESTful API认证方式 一般来讲,对于RESTful API都会有认证(Authenticati ...
- 在SpringBoot中使用SpringSecurity
@ 目录 提出一个需求 解决方案: 使用SpringSecurity进行解决 SpringSecurity和SpringBoot结合 1. 首先在pom.xml中引入依赖: 2. 配置用户角色和接口的 ...
- SpringBoot 集成SpringSecurity JWT
目录 1. 简介 1.1 SpringSecurity 1.2 OAuth2 1.3 JWT 2. SpringBoot 集成 SpringSecurity 2.1 导入Spring Security ...
- SpringBoot + SpringSecurity + Mybatis-Plus + JWT + Redis 实现分布式系统认证和授权(刷新Token和Token黑名单)
1. 前提 本文在基于SpringBoot整合SpringSecurity实现JWT的前提中添加刷新Token以及添加Token黑名单.在浏览之前,请查看博客: SpringBoot + Sp ...
- SpringBoot中yaml配置对象
转载请在页首注明作者与出处 一:前言 YAML可以代替传统的xx.properties文件,但是它支持声明map,数组,list,字符串,boolean值,数值,NULL,日期,基本满足开发过程中的所 ...
- 如何在SpringBoot中使用JSP ?但强烈不推荐,果断改Themeleaf吧
做WEB项目,一定都用过JSP这个大牌.Spring MVC里面也可以很方便的将JSP与一个View关联起来,使用还是非常方便的.当你从一个传统的Spring MVC项目转入一个Spring Boot ...
- springboot中swaggerUI的使用
demo地址:demo-swagger-springboot springboot中swaggerUI的使用 1.pom文件中添加swagger依赖 2.从github项目中下载swaggerUI 然 ...
- spring-boot+mybatis开发实战:如何在spring-boot中使用myabtis持久层框架
前言: 本项目基于maven构建,使用mybatis-spring-boot作为spring-boot项目的持久层框架 spring-boot中使用mybatis持久层框架与原spring项目使用方式 ...
随机推荐
- 洛谷 P1951 收费站_NOI导刊2009提高(2) 最短路+二分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1951 收费站_NOI导刊2009提高(2) 其 ...
- Leetcode598.Range Addition II范围求和2
给定一个初始元素全部为 0,大小为 m*n 的矩阵 M 以及在 M 上的一系列更新操作. 操作用二维数组表示,其中的每个操作用一个含有两个正整数 a 和 b 的数组表示,含义是将所有符合 0 < ...
- 2019阿里云开年Hi购季基础云产品分会场全攻略!
2019阿里云云上Hi购季活动已经于2月25日正式开启,从已开放的活动页面来看,活动分为三个阶段: 2月25日-3月04日的活动报名阶段.3月04日-3月16日的新购满返+5折抢购阶段.3月16日-3 ...
- Thinkphp js、css压缩类minify
说明:Minify 是用PHP5开发的应用,通过遵循一些Yahoo的优化规则来提高网站的性能.它会合并多个CSS或者JavaScript文件,移除一些不必要的空格和注释,进行gzip压缩,并且会设置浏 ...
- Spring_代理
1.代理模式. 2.静态代理原理及实践. 3.动态代理原理及实践. 4.Spring AOP原理及实战. 静态代理原理及实践 package test.staticProxy; // 接口 publi ...
- 人不能同时在两个地方做猪(Scrum Team)
在一个神奇的国度里生活着许多动物, 其中有猪, 鸡, 和鹦鹉. 它们每天搞头脑风暴, 琢磨如何创业, 最后鹦鹉提议它们合伙开一个早餐店: 具体分工如下: 猪: 提供猪肉, 做熏猪肉 (bacon) 鸡 ...
- Spring MVC JSON自己定义类型转换
版权声明:版权归博主全部.转载请带上本文链接.联系方式:abel533@gmail.com https://blog.csdn.net/isea533/article/details/28625071 ...
- 【水滴石穿】douban-movies-react-native
这个项目的话,倒是可以做一个支架页面,就是你需要什么东西,你就可以在里面加,不过也是比较难的地方 就是数据流,数据处理的部分.react可以处理数据的方式很多,没有见过类似于古老的vue时候可以使用的 ...
- 遇到的bug
1 div出现莫名其妙的空白bug 之前写了一个后台管理系统,项目不小加上是改版,很多的js都是用的之前的, bug多到自己都不想看, 其中有个是用iframe 框架加载表格页面,但是右边跟下边出 ...
- 如何把一个普通的Eclipse项目改造成Eclipse Plugin项目
New Project->Plug-in from existing JAR Archive 同时要记得不仅要将你要转换的项目的jar包选上,同时还要将项目依赖的jar包全部选上(要不然会找不到 ...