springboot项目license_springboot项目实战笔记

项目总框架

system目录下是整个系统的跳转关系,有登录验证,控制菜单的跳转,和一系列的验证操作

product目录下是用户看到的页面信息,就是管理的产品数据在页面中的显示控制。

common目录是一些组件,帮助用户系统验证或者配置一些其他的配置。

system目录相关知识学习(需要一些common目录下的组件)

druid池的配置

教程1

教程2

//druid配置访问页面

@Configuration

public class DruidConfig {

// 真正整合的地方

@ConfigurationProperties(prefix = "spring.datasource")

@Bean(name="dataSource")

public DataSource dataSource(){

return new DruidDataSource();

}

//配置Druid监控

@Bean

public ServletRegistrationBean statViewServlet(){

//StatViewServlet是druid内置的用来展示druid统计信息的页面,注册为服务servlet后可以使用

ServletRegistrationBean bean=new ServletRegistrationBean(new StatViewServlet(),"/druid/*");

Map initParams=new HashMap<>();

initParams.put("allow", "127.0.0.1");// IP白名单 (没有配置或者为空,则允许所有访问)

// IP黑名单 (存在共同时,deny优先于allow),但是他的使用效果是怎样的呢?设置了所有以后本机还是可以随便访问。

initParams.put("deny", "");

initParams.put("loginUsername","admin");

initParams.put("loginPassword","admin");

initParams.put("resetEnable","false");

bean.setInitParameters(initParams);

return bean;

}

//配置一个web监控的filter

@Bean

public FilterRegistrationBean webStatFilter(){

FilterRegistrationBean bean=new FilterRegistrationBean();

bean.setFilter(new WebStatFilter());

Map initParams=new HashMap<>();

initParams.put("exclusions","*.js,*.css,/druid/*");//忽略的资源

bean.setInitParameters(initParams);

bean.setUrlPatterns(Arrays.asList("/*"));

return bean;

}

}

mybatisplus

快速生成文档注解

链接

如果数据库的容量太小需要set global max_allowed_packet = 102410241024一下。

分页查询

设置一个控制分页查询的类,然后把他添加到bean中

/**

* 开启事务管理,但是具体怎么使用呢?

*/

@EnableTransactionManagement

@Configuration

public class MybatisPlusConfig {

@Bean

public PaginationInterceptor paginationInterceptor() {

PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false

// paginationInterceptor.setOverflow(false);

// 设置最大单页限制数量,默认 500 条,-1 不受限制

// paginationInterceptor.setLimit(500);

// 开启 count 的 join 优化,只针对部分 left join

paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));

return paginationInterceptor;

}

}

在controller写控制分页查询的选项

/**

* 配置分页查询的请求

* 通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。

*/

@ResponseBody

@RequestMapping("/userlist/{id}")

public List listUser(@PathVariable int id){

QueryWrapper queryWrapper = new QueryWrapper<>();

//queryWrapper.eq("age",23);

IPage page = new Page<>(id,2);

IPage userIPage = userMapper.selectPage(page, queryWrapper);

//查看总共查询到多少条数据

//long total = userIPage.getTotal();

//System.out.println(total);

//把这些数据打印出来

// userIPage.getRecords().forEach(user-> System.out.println(user));

//把查询到的数据用json的格式返回回去

List userList = new LinkedList<>();

userIPage.getRecords().forEach(user-> userList.add(user));

return userList;

}

事务管理

教程链接

在myaitsplus类上面开启事务管理

@EnableTransactionManagement

然后在想要进行事务管理的地方@Transactional,当这个方法出现错误的时候就会自动执行事务回滚。

如果想要对事务回滚做更加简单操作可以参考下面链接

教程链接

代码生成器

官方文档

从官网上复制下来的,直接使用就可以

package com.hdeasy.project.comment;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;

import com.baomidou.mybatisplus.core.toolkit.StringPool;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;

import com.baomidou.mybatisplus.generator.AutoGenerator;

import com.baomidou.mybatisplus.generator.InjectionConfig;

import com.baomidou.mybatisplus.generator.config.*;

import com.baomidou.mybatisplus.generator.config.po.TableInfo;

import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;

import java.util.ArrayList;

import java.util.List;

import java.util.Scanner;

public class CodeGenerator {

/**

*

* 读取控制台内容

*

*/

public static String scanner(String tip) {

Scanner scanner = new Scanner(System.in);

StringBuilder help = new StringBuilder();

help.append("请输入" + tip + ":");

System.out.println(help.toString());

if (scanner.hasNext()) {

String ipt = scanner.next();

if (StringUtils.isNotEmpty(ipt)) {

return ipt;

}

}

throw new MybatisPlusException("请输入正确的" + tip + "!");

}

public static void main(String[] args) {

// 代码生成器

AutoGenerator mpg = new AutoGenerator();

// 全局配置

GlobalConfig gc = new GlobalConfig();

String projectPath = System.getProperty("user.dir");

gc.setOutputDir(projectPath + "/src/main/java");

gc.setAuthor("magician");

gc.setOpen(false);

// gc.setSwagger2(true); 实体属性 Swagger2 注解

mpg.setGlobalConfig(gc);

// 数据源配置

DataSourceConfig dsc = new DataSourceConfig();

dsc.setUrl("jdbc:mysql://localhost:3306/easyapp?serverTimezone=UTC&useUnicode=true&useSSL=false&characterEncoding=utf8");

// dsc.setSchemaName("public");

dsc.setDriverName("com.mysql.cj.jdbc.Driver");

dsc.setUsername("root");

dsc.setPassword("root");

mpg.setDataSource(dsc);

// 包配置

PackageConfig pc = new PackageConfig();

pc.setModuleName(scanner("模块名"));

pc.setParent("com.hdeasy.project.test");

mpg.setPackageInfo(pc);

// 自定义配置

InjectionConfig cfg = new InjectionConfig() {

@Override

public void initMap() {

// to do nothing

}

};

// 如果模板引擎是 freemarker

String templatePath = "/templates/mapper.xml.ftl";

// 如果模板引擎是 velocity

// String templatePath = "/templates/mapper.xml.vm";

// 自定义输出配置

List focList = new ArrayList<>();

// 自定义配置会被优先输出

focList.add(new FileOutConfig(templatePath) {

@Override

public String outputFile(TableInfo tableInfo) {

// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!

return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()

+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;

}

});

/*

cfg.setFileCreate(new IFileCreate() {

@Override

public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {

// 判断自定义文件夹是否需要创建

checkDir("调用默认方法创建的目录,自定义目录用");

if (fileType == FileType.MAPPER) {

// 已经生成 mapper 文件判断存在,不想重新生成返回 false

return !new File(filePath).exists();

}

// 允许生成模板文件

return true;

}

});

*/

cfg.setFileOutConfigList(focList);

mpg.setCfg(cfg);

// 配置模板

TemplateConfig templateConfig = new TemplateConfig();

// 配置自定义输出模板

//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别

// templateConfig.setEntity("templates/entity2.java");

// templateConfig.setService();

// templateConfig.setController();

templateConfig.setXml(null);

mpg.setTemplate(templateConfig);

// 策略配置

StrategyConfig strategy = new StrategyConfig();

strategy.setNaming(NamingStrategy.underline_to_camel);

strategy.setColumnNaming(NamingStrategy.underline_to_camel);

strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");

strategy.setEntityLombokModel(true);

strategy.setRestControllerStyle(true);

// 公共父类

strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");

// 写于父类中的公共字段

strategy.setSuperEntityColumns("id");

strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));

strategy.setControllerMappingHyphenStyle(true);

strategy.setTablePrefix(pc.getModuleName() + "_");

mpg.setStrategy(strategy);

mpg.setTemplateEngine(new FreemarkerTemplateEngine());

mpg.execute();

}

}

使用期间报错(The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents more than one time zone.)

在Idea中连接数据库是抛出The server time zone value ‘�й���׼ʱ��’ is unrecogni错误 原因是因为使用了Mysql Connector/J 6.x以上的版本,然后就报了时区的错误

解决办法是 在配置url的时候不能简单写成:

jdbc:mysql://localhost:3306/yzu

而是要写成 :

jdbc:mysql://localhost:3306/yzu?serverTimezone=UTC

SpringMvc的配置

配置一个类继承webmvcConfigurer来配置mvc。可以其中可以配置跨域请求和视图解析器,等等。

@Configuration

public class SpringMVCConfig implements WebMvcConfigurer {

/**

* 配置跨域请求参数

* @param registry

*/

@Override

public void addCorsMappings(CorsRegistry registry) {

registry.addMapping("/**")

.allowedOrigins("*")

.allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")

.allowCredentials(true)

.maxAge(3600)

.allowedHeaders("*");

}

@Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

registry.addResourceHandler("swagger-ui.html")//表示文件路径,名为swagger-ui.html的文件

.addResourceLocations("classpath:/META-INF/resources/");//表示开放资源路径

registry.addResourceHandler("/webjars/**")//表示webjars下的所有文件

.addResourceLocations("classpath:/META-INF/resources/webjars/");//表示开放这个路径下的webjars中的所有文件

}

}

@RestController注解相当于@ResponseBody + @Controller合在一起的作用。

shiro的配置

下午大概写一个注册数据库的东西来注册新的用户然后在配置redis数据库

创建一个shiroconfig类

@Configuration

public class ShiroConfig {

@Bean

public UserRealm myShiroRealm(){

return new UserRealm();

}

@Bean

public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {

ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

factoryBean.setSecurityManager(securityManager);

//通用配置(跳转登录页面,未授权跳转的页面)

factoryBean.setLoginUrl("/autherror?code=1");//未登录跳转地址,返回json

factoryBean.setUnauthorizedUrl("/autherror?code=2");//未授权跳转地址,返回json

Map filterRuleMap = new LinkedHashMap();

//设置shiro内置过滤器

/**

* Shiro内置过滤器,可以实现权限相关的拦截器

* 常用的过滤器:

* anon:无需认证就可以访问

* authc: 必须认证才可以访问

* user: 如果使用rememberMe的功能可以直接访问

* perms: 该资源必须得到资源权限可以访问

* role: 该资源必须得到角色权限才可以访问

*/

filterRuleMap.put("/login", "anon");//登陆

filterRuleMap.put("/index.html","anon");

filterRuleMap.put("/","anon");

filterRuleMap.put("/system/register", "anon");//注册

filterRuleMap.put("/autherror", "anon");//跳转地址

filterRuleMap.put("/resources/css/**", "anon");

filterRuleMap.put("/resources/js/**", "anon");

filterRuleMap.put("/resources/fonts/**", "anon");

filterRuleMap.put("/resources/imags/**", "anon");

//不建议使用这个匹配规则,他把resources下面的所有我们设置的静态资源全部展示出来了,那么我们上面的匹配规则已经没有意义了。初衷:我们只是想把某些想要展示的静态资源展示出来。

//filterRuleMap.put("/resources/**","anon");

//放行静态资源

filterRuleMap.put("/static/**", "anon");

filterRuleMap.put("/druid/**","anon");

filterRuleMap.put("/upload/**", "anon");

filterRuleMap.put("/files/**", "anon");

// filterRuleMap.put("/", "anon");

//放行swagger文档

filterRuleMap.put("/swagger-ui.html", "anon");

filterRuleMap.put("/swagger-resources/**", "anon");

filterRuleMap.put("/v2/**", "anon");

filterRuleMap.put("/webjars/**", "anon");

filterRuleMap.put("/logout", "logout");

filterRuleMap.put("/**", "authc");

factoryBean.setFilterChainDefinitionMap(filterRuleMap);

return factoryBean;

}

//

// /**

// * 之后要使用的类需要这个类的存在,所以从这里把他加入到bean中

// * @return

// */

//

// @Bean(name = "lifecycleBeanPostProcessor")

// public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {

// return new LifecycleBeanPostProcessor();

// }

//

// /**

// * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证

// * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能

// *

// * @return

// */

// @Bean

// @DependsOn({"lifecycleBeanPostProcessor"})//控制bean加载顺序,等到它加载好之后才可以加载

// public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {

// DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();

// advisorAutoProxyCreator.setProxyTargetClass(true);

// return advisorAutoProxyCreator;

// }

//

// @Bean //Advisor:顾问 //开启对shior注解的支持

// public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {

// AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();

// authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);

// return authorizationAttributeSourceAdvisor;

// }

//

// @Value("${spring.redis.host}")

// private String host;

// @Value("${spring.redis.port}")

// private String port;

// @Value("${spring.redis.timeout}")

// private int timeout;

//

// /**

// * 1.redis的控制器,操作redis

// */

// public RedisManager redisManager() {

// RedisManager redisManager = new RedisManager();

// redisManager.setHost(host + ":" + port);

// redisManager.setTimeout(timeout);

// return redisManager;

// }

//

// /**

// * 2.sessionDao

// */

// public RedisSessionDAO redisSessionDAO() {

// RedisSessionDAO sessionDAO = new RedisSessionDAO();

// sessionDAO.setRedisManager(redisManager());

// return sessionDAO;

// }

//

//

// /**

// * 3.会话管理器

// */

// public DefaultWebSessionManager sessionManager() {

// CustomSessionManager sessionManager = new CustomSessionManager();

// sessionManager.setSessionDAO(redisSessionDAO());

// //设置session会话过期时间,单位:毫秒(在无操作时开始计时)

// sessionManager.setGlobalSessionTimeout(1000*60*20);

// //禁用cookie

// sessionManager.setSessionIdCookieEnabled(false);

// //禁用url重写 url;jsessionid=id

// sessionManager.setSessionIdUrlRewritingEnabled(false);

// return sessionManager;

// }

//

// /**

// * 4.缓存管理器

// */

// public RedisCacheManager cacheManager() {

// RedisCacheManager redisCacheManager = new RedisCacheManager();

// redisCacheManager.setRedisManager(redisManager());

// //设置安全信息的主键字段

// redisCacheManager.setPrincipalIdFieldName("userId");

// return redisCacheManager;

// }

@Bean

public SecurityManager securityManager(UserRealm realm) {

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

//设置realm.

securityManager.setRealm(realm);

//将自定义的会话管理器注册到安全管理器中

//securityManager.setSessionManager(sessionManager());

//将自定义的redis缓存管理器注册到安全管理器中

//securityManager.setCacheManager(cacheManager());

return securityManager;

}

}

然后创建一个realm类

public class UserRealm extends AuthorizingRealm {

@Autowired

SysUserMapper userMapper;

//进行授权

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

System.out.println("执行了授权验证");

return null;

}

//进行认证

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

String username = (String) token.getPrincipal();//获取用户名

String password = new String((char[]) token.getCredentials());//获取密码

QueryWrapper queryWrapper = new QueryWrapper<>();

queryWrapper.eq("username",username);

//根据用户名查找数据源

SysUser user = userMapper.selectOne(queryWrapper);

System.out.println(user.toString());

//账号不存在

if(user == null){

throw new UnknownAccountException("账号或者密码不正确");

}

if(!password.equals(user.getPassword())){

throw new IncorrectCredentialsException("账号或者密码不正确");

}

//判断账号是否存在

SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,password,getName());

//authenticationInfo信息交给shiro,调用login的时候会自动比较doGetAuthenticationInfo(AuthenticationToken token)的token和authenticationInfo

return authenticationInfo;

}

}

最后在controller中控制shiro的验证

@RestController

public class SysLoginController {

@PostMapping(value="/login")

public String login(@RequestParam Map loginMap){

String username = loginMap.get("username");

String password = loginMap.get("password");

System.out.println(username+password);

try{

//1.构造登录令牌

//加密密码

password = new Md5Hash(password,username,3).toString();//密码,盐(用户名)就是在生成的加密字符串后面加上用户名,加密次数。

UsernamePasswordToken token = new UsernamePasswordToken(username,password);

//2.获取subject

Subject subject = SecurityUtils.getSubject();

//3.调用login方法,进入realm完成验证

subject.login(token);

//4.获取sessionId

String sessionId =(String) subject.getSession().getId();

System.out.println(sessionId);

//5.返回构造结果

System.out.println("成功");

return "Success";

}catch(Exception e){

System.out.println("失败");

return "fales";

}

}

}

如果前端返回的是json数据就用@RequestBody接收

如果返回的是普通的数据就使用@RequestParam接收

redis数据库

安装redis数据库

在ShiroConfig里面配置的

@Value("${spring.redis.host}")

private String host;

@Value("${spring.redis.port}")

private String port;

@Value("${spring.redis.timeout}")

private int timeout;

/**

* 1.redis的控制器,操作redis

*/

public RedisManager redisManager() {

RedisManager redisManager = new RedisManager();

redisManager.setHost(host + ":" + port);

redisManager.setTimeout(timeout);

return redisManager;

}

/**

* 2.sessionDao

*/

public RedisSessionDAO redisSessionDAO() {

RedisSessionDAO sessionDAO = new RedisSessionDAO();

sessionDAO.setRedisManager(redisManager());

return sessionDAO;

}

/**

* 3.会话管理器

*/

public DefaultWebSessionManager sessionManager() {

CustomSessionManager sessionManager = new CustomSessionManager();

sessionManager.setSessionDAO(redisSessionDAO());

//设置session会话过期时间,单位:毫秒(在无操作时开始计时)

sessionManager.setGlobalSessionTimeout(1000*60*20);

//禁用cookie

sessionManager.setSessionIdCookieEnabled(false);

//禁用url重写 url;jsessionid=id

sessionManager.setSessionIdUrlRewritingEnabled(false);

return sessionManager;

}

/**

* 4.缓存管理器

*/

public RedisCacheManager cacheManager() {

RedisCacheManager redisCacheManager = new RedisCacheManager();

redisCacheManager.setRedisManager(redisManager());

//设置安全信息的主键字段

redisCacheManager.setPrincipalIdFieldName("userId");

return redisCacheManager;

}

spring:

#配置redis数据库

redis:

#数据库索引默认为零

database: 0

#配置redis服务器地址

host: 127.0.0.1

#默认开启端口号,制作者用一个女星的九键键位做的端口

port: 6379

#链接密码默认为空,可以设置密码么?我再安装的时候就没有找到设置的地方

password:

#链接超时时间(毫秒)

timeout: 1000

jedis:

pool:

#连接池最大连接数,负数表示没有链接限制

max-active: 20

#最大空闲连接数

max-idle: 10

getsessionid的那个类暂时没有看清楚所以先不管他。

swagger UI的配置

教程链接

@Configuration

@EnableSwagger2//开启Swagger2

public class SwaggerConfig {

@Bean

public Docket createRestApi(){

return new Docket(DocumentationType.SWAGGER_2)

.pathMapping("/")

.select()

.apis(RequestHandlerSelectors.basePackage("com.hdeasy.project.controller"))//配置映射和扫描路径

.paths(PathSelectors.any())

.build().apiInfo(new ApiInfoBuilder()

.title("SpringBoot整合Swagger")

.description("SpringBoot整合Swagger,详细信息......")

.version("9.0")

.contact(new Contact("hdeasy","www.baidu.com","[email protected]"))

.license("The Apache License")

.licenseUrl("http://www.baidu.com")

.build());

}

}

@Api注解可以用来标记当前Controller的功能。

@ApiOperation注解用来标记一个方法的作用。

@ApiImplicitParam注解用来描述一个参数,可以配置参数的中文含义,也可以给参数设置默认值,这样在接口测试的时候可以避免手动输入。

如果有多个参数,则需要使用多个@ApiImplicitParam注解来描述,多个@ApiImplicitParam注解需要放在一个@ApiImplicitParams注解中。

需要注意的是,@ApiImplicitParam注解中虽然可以指定参数是必填的,但是却不能代替@RequestParam(required = true),前者的必填只是在Swagger2框架内必填,抛弃了Swagger2,这个限制就没用了,所以假如开发者需要指定一个参数必填,@RequestParam(required = true)注解还是不能省略。

如果参数是一个对象(例如上文的更新接口),对于参数的描述也可以放在实体类中。例如下面一段代码:

@ApiModel

public class User {

@ApiModelProperty(value = “用户id”)

private Integer id;

@ApiModelProperty(value = “用户名”)

private String username;

@ApiOperation("登录用户接口")

@ApiImplicitParams(value = {

@ApiImplicitParam(name = "username", value = "用户名", defaultValue = "caochen"),

@ApiImplicitParam(name = "password", value = "密码", defaultValue = "123456", required = true)

}

)

public String login(@RequestParam Map loginMap){

fastjson的配置

教程链接

Fastjson是一个Java库,可用于将Java对象转换为其JSON表示。它还可用于将JSON字符串转换为等效的Java对象。Fastjson可以处理任意Java对象,包括您没有源代码的预先存在的对象。

阿里官方给的定义是, fastjson 是阿里巴巴的开源JSON解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 JavaBean。

速度快

fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。

使用广泛

fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。

测试完备

fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。

使用简单

fastjson的 API 十分简洁。

功能完备

支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。

Fastjson入口类是 com.alibaba.fastjson.JSON,主要的 API 是 JSON.toJSONString 和 parseObject。

package com.alibaba.fastjson;

public abstract class JSON {

// Java对象转换为JSON字符串

public static final String toJSONString(Object object);

//JSON字符串转换为Java对象

public static final T parseObject(String text, Class clazz, Feature... features);

}

序列化:

String jsonString = JSON.toJSONString(obj);

反序列化:

VO vo = JSON.parseObject("...", VO.class);

泛型反序列化:

import com.alibaba.fastjson.TypeReference;

List list = JSON.parseObject("...", new TypeReference>() {});

Fastjson 处理日期的API很简单,例如:

JSON.toJSONStringWithDateFormat(date, "yyyy-MM-dd HH:mm:ss.SSS")

//使用ISO-8601日期格式

JSON.toJSONString(obj, SerializerFeature.UseISO8601DateFormat);

//全局修改日期格式

JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";

JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);

反序列化能够自动识别如下日期格式:

ISO-8601日期格式

yyyy-MM-dd

yyyy-MM-dd HH:mm:ss

yyyy-MM-dd HH:mm:ss.SSS

毫秒数字

毫秒数字字符串

.NET JSON日期格式

new Date(198293238)

slf4j-api的配置

添加好相应的jar包,就是配置好maven然后把logback-spring.xml复制过去

${appName}

%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n

%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n

${LOG_HOME}/${appName}.log

${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log

365

100MB

%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n

再写一个类来加载logback配置

@Configuration

@Aspect

@Slf4j

public class LogAspectConfig {

private static final Logger log = LoggerFactory.getLogger(LogAspectConfig.class);

// 定义切点Pointcut

@Pointcut("execution(* com.hdeasy..controller.*Controller.*(..))")//两个..代表所有子目录,最后括号里的两个..代表所有参数

public void logPointCut() {

}

@Before("logPointCut()")

public void doBefore(JoinPoint joinPoint) throws Throwable {

// 接收到请求,记录请求内容

ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

HttpServletRequest request = attributes.getRequest();

// 记录下请求内容

log.info("请求地址 : " + request.getRequestURL().toString());

log.info("HTTP METHOD : " + request.getMethod());

// 获取真实的ip地址

//logger.info("IP : " + IPAddressUtil.getClientIpAddress(request));

log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "."

+ joinPoint.getSignature().getName());

log.info("参数 : " + Arrays.toString(joinPoint.getArgs()));

// loggger.info("参数 : " + joinPoint.getArgs());

}

@Around("logPointCut()")

public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

long startTime = System.currentTimeMillis();

Object ob = pjp.proceed();// ob 为方法的返回值

log.info("耗时 : " + (System.currentTimeMillis() - startTime));

return ob;

}

@AfterReturning(returning = "ret", pointcut = "logPointCut()")// returning的值和doAfterReturning的参数名一致

public void doAfterReturning(Object ret) throws Throwable {

// 处理完请求,返回内容(返回值太复杂时,打印的是物理存储空间的地址)

log.debug("返回值 : " + ret);

}

}

quartz的配置

教程链接

http协议

教程链接

redis操作

后台处理前端VUE传送过来的json数据

只要传递json数据就可以处理,后台处理好json就好了

rocktmq

session,request,cookie详解

响应vue

后台给vue传送数据,可以先创建一个Result类,来整合你要发送的信息。然后把Request对象返回回去。

你可能感兴趣的:(springboot项目license_springboot项目实战笔记)