003-maven开发Java脚手架archrtype-技术点说明
一、概述
二、技术点说明
2.1、项目结构
凡auto包或文件件,均会被代码生成器再次生成二修改
1、model层
po:BasePO基础类,统一了数据库的基础字段【数据库必须添加如下,与mybatis-plus生成器匹配】
strategy.setSuperEntityColumns("id","delflag","status","remark","created_datetime","updated_datetime");
po:auto数据库表生成的原始类 【不允许修改】,如需扩展可以继承、复合扩展
2、dao层
mapper:auto数据库映射代码生成器自动生成,不允许修改,如需扩展需自定义在auto外,如 AccountBalanceExtMapper
同时修改xml,注意xml内部配置正确的 namespace ,: <mapper namespace="com.aaa.test.mapper.AccountBalanceExtMapper">
3、service层
auto自动生成文件【不允许修改】
base:IBaseService、BaseServiceImpl 【基础项目不用继承,使用IService即可】
自定义实现需要在auto同级编写即可。
4、web层
主要在controller包下,auto自动生成mapper,更具代码生成器生成,注意权限控制。base 基础,如后续,重新代码生成可不生成web层代码。
其他包主要是统一输出使用。参看下面统一输出。
2.2、springboot与mybatisplus整合
【代码生成器、分页、逻辑删除】参看 代码
代码生成:test-demo-generator
1、重写 基于继承BaseController的模板。框架已提供。
2、代码生成器文件MybatisPlusGenerator
package com.aaa.test.generator; import com.baomidou.mybatisplus.core.toolkit.StringPool;
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.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType; import java.util.ArrayList;
import java.util.List; public class MybatisPlusGenerator { // region 待修改配置 // 数据库信息 jdbc:mysql://localhost:3358/test?useUnicode=true&useSSL=false&characterEncoding=utf8
private static final String DATABASE_DRIVER_NAME = "com.mysql.cj.jdbc.Driver"; //com.mysql.jdbc.Driver
private static final String DATABASE_HOST = "localhost";
private static final String DATABASE_PORT = "3358";
private static final String DATABASE = "test";
private static final String DATABASE_USERNAME = "root";
private static final String DATABASE_PASSWORD = "123456";
private static final String DATABASE_URL = "jdbc:mysql://" + DATABASE_HOST + ":" + DATABASE_PORT + "/" + DATABASE
+ "?useUnicode=true&useSSL=false&characterEncoding=UTF8&serverTimezone=UTC"; //endregion // 所有文件开启 覆盖配置
// 指定表名配置,不指定代表所有
public static void main(String[] args) {
String[] tableNames = null;//new String[]{"account_balance"};
generator(
//new LayerType[]{LayerType.entity,LayerType.mapperxml},
null,
tableNames);
System.out.println("==========ok=========");
} //包名 com.github.bjlhx15
private static final String packageName = "com.aaa.test"; //代码生成路径 相对当前的路径
private static final String baseProjectPath = System.getProperty("user.dir"); //代码注释作者
private static final String author = "<a>https://www.cnblogs.com/bjlhx/</a>"; // 数据库信息 jdbc:mysql://localhost:3358/test?useUnicode=true&useSSL=false&characterEncoding=utf8
private static final String DATABASE_DRIVER_NAME = "com.mysql.cj.jdbc.Driver"; //com.mysql.jdbc.Driver
private static final String DATABASE_HOST = "localhost";
private static final String DATABASE_PORT = "3358";
private static final String DATABASE = "test";
private static final String DATABASE_USERNAME = "root";
private static final String DATABASE_PASSWORD = "123456";
private static final String DATABASE_URL = "jdbc:mysql://" + DATABASE_HOST + ":" + DATABASE_PORT + "/" + DATABASE
+ "?useUnicode=true&useSSL=false&characterEncoding=UTF8&serverTimezone=UTC"; // 生成的分层代码
enum LayerType {
entity("/test-demo-model"),
mapper("/test-demo-dao"),
mapperxml("/test-demo-web"),
service("/test-demo-service"),
web("/test-demo-web"),
; LayerType(String path) {
this.path = path;
} /**
* 路径
*/
private String path;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
} /**
* 逆向工程 生成分层代码,默认覆盖模式
*
* @param layerTypes 要生成的分层名 null 全部,指定的话只生成指定的包
* @param tableNames 要生成的表名
*/
private static void generator(LayerType[] layerTypes, String[] tableNames) {
if (layerTypes == null) {
layerTypes = LayerType.values();
}
for (LayerType layerType : layerTypes) {
String projectPath = baseProjectPath + layerType.getPath();
// 全局配置
GlobalConfig gc = getGlobalConfig(projectPath);
// 数据源配置
DataSourceConfig dsc = getDataSourceConfig();
// 包配置
PackageConfig pc = getPackageConfig();
// xml配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() { }
};
if (layerType.equals(LayerType.mapperxml)) {
// 自定义配置
cfg = getInjectionConfig(projectPath);
}
// 策略配置**(个性化定制)**
StrategyConfig strategy = getStrategyConfig(tableNames, pc); //代码生成器
new AutoGenerator()
.setGlobalConfig(gc)//全局
.setDataSource(dsc)//数据源
.setPackageInfo(pc)//包配置
.setCfg(cfg)//自定义 xml
//.setTemplate(new TemplateConfig().setXml(null))//自定义 xml 此处设置为null,就不会再java下创建xml的文件夹了
.setTemplate(getTemplateConfig(layerType))
.setStrategy(strategy) //个性化策略
.setTemplateEngine(new FreemarkerTemplateEngine())//模板引擎
.execute();//执行
}
} // 策略配置**(个性化定制)**
private static StrategyConfig getStrategyConfig(String[] tableNames, PackageConfig pc) {
StrategyConfig strategy = new StrategyConfig();
//数据库表映射到实体的命名策略,该处下划线转驼峰命名
strategy.setNaming(NamingStrategy.underline_to_camel);
//数据库表映射到实体的命名策略,该处下划线转驼峰命名
strategy.setColumnNaming(NamingStrategy.underline_to_camel); if (tableNames != null && tableNames.length > 0) {
strategy.setInclude(tableNames); //被扫描的表名 需要包含的表名,允许正则表达式(与exclude二选一配置)
} //实体类自动继承Entity,不需要也可以
strategy.setSuperEntityClass(String.format("%s.po.BasePO", packageName));
//【实体】是否为lombok模型(默认 false)
strategy.setEntityLombokModel(false);
// 写于父类中的公共字段
strategy.setSuperEntityColumns("id","delflag","status","remark","created_datetime","updated_datetime"); // 自定义 service 父类
//strategy.setSuperServiceClass(String.format("%s.service.BaseService", packageName));
// 自定义 service 实现类父类
//strategy.setSuperServiceImplClass(String.format("%s.service.impl.BaseServiceImpl", packageName)); // 控制层是否使用Rest风格 生成 @RestController 控制器
strategy.setRestControllerStyle(true);
//控制层自动继承父类BaseController,不需要也可以 BaseController
strategy.setSuperControllerClass(String.format("%s.controller.base.BaseController", packageName));
strategy.setControllerMappingHyphenStyle(true); //根据表名来建对应的类名,如果你的表名没有什么下划线,比如test,那么你就可以取消这一步
//strategy.setTablePrefix(pc.getModuleName() + "_");
return strategy;
} //xml 定制化
private static InjectionConfig getInjectionConfig(String projectPath) {
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
//xml 配置
List<FileOutConfig> focList = new ArrayList();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称================================模块名(自己设置)
return projectPath + "/src/main/resources/mapper/"
+ "/autoxml/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
return cfg;
} // 数据源配置
private static DataSourceConfig getDataSourceConfig() {
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl(DATABASE_URL)
// dsc.setSchemaName("public");
.setDriverName(DATABASE_DRIVER_NAME)
.setUsername(DATABASE_USERNAME)
.setPassword(DATABASE_PASSWORD)
.setTypeConvert(new MySqlTypeConvert() {
@Override
public DbColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
//将数据库中timestamp转换成date
if (fieldType.toLowerCase().contains("timestamp")) {
return DbColumnType.DATE;
}
return (DbColumnType) super.processTypeConvert(globalConfig, fieldType);
}
});
return dsc;
} // 包配置
private static PackageConfig getPackageConfig() {
PackageConfig pc = new PackageConfig();
//pc.setModuleName(moduleName)//自定义模块名 account
pc.setParent(packageName)//《====包名(自己手动设置)com.lihongxu.test 与 module组合
.setEntity("po.auto")//Entity包名
.setMapper("mapper.auto")//mapper包名
.setService("service.auto")
.setController("controller.auto");
return pc;
} // 全局配置
private static GlobalConfig getGlobalConfig(String projectPath) {
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(projectPath + "/src/main/java");//生成文件的输出目录
gc.setOpen(false);//是否打开输出目录 默认true
gc.setFileOverride(true);// 是否覆盖已有文件 默认false
gc.setActiveRecord(false);//开启 ActiveRecord 模式 默认false gc.setAuthor(author);// 作者名
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);//开启 BaseResultMap 默认false
gc.setBaseColumnList(true);//开启 baseColumnList 默认false
gc.setServiceName("I%sService"); //service接口 命名方式 例如:%sBusiness 生成 UserBusiness
gc.setSwagger2(true); //实体属性 Swagger2 注解 // 自定义文件命名,注意 %s 会自动填充表实体属性! 使用定制化生成了
// gc.setMapperName("%sMapper");
// gc.setXmlName("%sMapper");
// gc.setServiceName("%sService");
// gc.setServiceImplName("%sServiceImpl");
// gc.setControllerName("%sController");
return gc;
} //生成分层代码
private static TemplateConfig getTemplateConfig(LayerType layerType) {
TemplateConfig templateConfig = new TemplateConfig();
switch (layerType) {
case entity:
templateConfig.setEntity(new TemplateConfig().getEntity(false))
.setMapper(null)
.setXml(null)
.setService(null)
.setServiceImpl(null)
.setController(null);
break;
case mapper:
templateConfig.setEntity(null)
.setMapper(new TemplateConfig().getMapper())
.setXml(null)
.setService(null)
.setServiceImpl(null)
.setController(null);
break;
case mapperxml:
templateConfig.setEntity(null)
.setMapper(null)
.setXml(null)
.setService(null)
.setServiceImpl(null)
.setController(null);
break;
case service:
templateConfig.setEntity(null)
.setMapper(null)
.setXml(null)
.setService(new TemplateConfig().getService())
.setServiceImpl(new TemplateConfig().getServiceImpl())
.setController(null);
break;
case web:
templateConfig.setEntity(null)
.setMapper(null)
.setXml(null)
.setService(null)
.setServiceImpl(null)
// .setController(new TemplateConfig().getController());
.setController("/templates/basecontroller.java");
break;
default:
throw new IllegalArgumentException("参数匹配错误,请检查");
}
return templateConfig;
}
}
逻辑删除
1、父类BasePO
//使用@TableLogic注解实现逻辑删除
@TableLogic
@TableField(value = "delflag", exist = true)
protected Integer delflag = 0;
2、配置文件
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
2.3、log4j2整合
参看 代码
2.4、统一响应【统一异常处理】
1、设置统一响应输出类 BaseResponse
package com.aaa.test.response; import com.aaa.test.enums.ErrorCodeEnum; /**
* 统一返回结果
*/
public class BaseResponse<T> {
/**
* 返回的data
* */
private T data; /**
* 错误码
* */
private Integer errorCode; /**
* 错误信息
* */
private String errorMsg; /**
* 是否成功
* */
private boolean success = false; /**
* 出现异常的构造函数
* */
public BaseResponse(ErrorCodeEnum errorCodeEnum) {
this.errorCode = errorCodeEnum.getErrorCode();
this.errorMsg = errorCodeEnum.getErrorMsg();
} /**
* 成功返回的结果
* */
public BaseResponse(T data) {
success = true;
this.data = data;
} /**
* 成功返回的结果
* */
public BaseResponse(boolean success,ErrorCodeEnum errorCodeEnum,T data) {
this.success = success;
this.data = data;
this.errorCode = errorCodeEnum.getErrorCode();
this.errorMsg = errorCodeEnum.getErrorMsg();
} public static <T> BaseResponse success(T data) {
return new BaseResponse(data);
}
public static <T> BaseResponse success(ErrorCodeEnum errorCodeEnum) {
return new BaseResponse(true,errorCodeEnum,null);
} public static BaseResponse fail(ErrorCodeEnum errorCodeEnum) {
return new BaseResponse(errorCodeEnum);
} public static BaseResponse fail() {
return new BaseResponse(ErrorCodeEnum.result_exception);
} public T getData() {
return data;
} public void setData(T data) {
this.data = data;
} public Integer getErrorCode() {
return errorCode;
} public void setErrorCode(Integer errorCode) {
this.errorCode = errorCode;
} public String getErrorMsg() {
return errorMsg;
} public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
} public boolean isSuccess() {
return success;
} public void setSuccess(boolean success) {
this.success = success;
} @Override
public String toString() {
return "BaseResponse{" +
"data=" + data +
", errorCode='" + errorCode + '\'' +
", errorMsg='" + errorMsg + '\'' +
", success=" + success +
'}';
}
}
其中用到了错误码 ErrorCodeEnum
package com.aaa.test.enums; /**
* 错误代码枚举类
*/
public enum ErrorCodeEnum {
// 成功类响应
success(200000, "成功"),
no_response_data(200001, "没有返回数据"), //请求类响应码
Param_does_not_exist(400001, "查找参数不存在"),
Param_does_not_correct(400002, "所传参数格式不正确"),
HttpMediaTypeNotSupportedException(400003, "不支持的Content-type类型"), result_exception(600000, "待处理服务端异常"), ; ErrorCodeEnum(Integer errorCode, String errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
} /**
* 错误码
*/
private Integer errorCode; /**
* 错误信息
*/
private String errorMsg; public Integer getErrorCode() {
return errorCode;
} public void setErrorCode(Integer errorCode) {
this.errorCode = errorCode;
} public String getErrorMsg() {
return errorMsg;
} public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}
技术需求
1、统一响应类支持静态的成功失败方法
2、错误码,设计应为6位数值类型,其中200000 类别为成功类型,400000为请求类型码,500000为服务端异常,其他大于 600000码为客户自定义码,
2、Controller编写
支持controller多种响应参数
常见类型String,int,Integer、Map、Object、单个类等
支持使用上述:BaseResponse 包装响应类
支持使用:ResponseEntity接收类型
通过统一响应处理返回统一:BaseResponse格式
3、统一响应处理方案
编写RestControllerAdvice,对响应,以及异常统一处理
/**
* 统一返回结果异常处理类
*/
@RestControllerAdvice
public class ResponseResultBodyAdvice implements ResponseBodyAdvice<Object> {
private final Logger log = LoggerFactory.getLogger(ResponseResultBodyAdvice.class);
private static final Class<? extends Annotation> ANNOTATION_TYPE = ResponseBody.class; /**
* 判断类或者方法是否使用了 @ResponseResultBody
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
// swagger2 过滤
if (returnType.getMethod().getDeclaringClass().getName().contains("springfox.documentation.swagger")) {
//因为使用了 RestControllerAdvice 与swagger2 而swagger2也会响应 responsebody 故会被此拦截
// 如果想使用swagger2生效 需要不被拦截处理 或者自定义一个 ResponseBody 注解来处理
return false;
}
return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ANNOTATION_TYPE) || returnType.hasMethodAnnotation(ANNOTATION_TYPE);
} /**
* 当类或者方法使用了 @ResponseResultBody 就会调用这个方法
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 避免已经返回基础类型 多次转换
if (body instanceof BaseResponse) {
return body;
}
return BaseResponse.success(body);
} /**
* 提供对标准Spring MVC异常的处理
*
* @param ex the target exception
* @param request the current request
*/
@ExceptionHandler(Exception.class)
public final ResponseEntity<BaseResponse<?>> exceptionHandler(Exception ex, WebRequest request) {
log.error("ExceptionHandler: {}", ex.getMessage());
HttpHeaders headers = new HttpHeaders();
if (ex instanceof HttpMediaTypeNotSupportedException) {
// 针对 返回String 类型 需要客户端设置Content-type 为application/json
return this.handleResultException(new ResultException(ErrorCodeEnum.HttpMediaTypeNotSupportedException),
headers, request);
} else if (ex instanceof ResultException) {
return this.handleResultException((ResultException) ex, headers, request);
}
//TODO: 这里可以自定义其他的异常拦截
return this.handleException(ex, headers, request);
} /**
* 对ResultException类返回返回结果的处理
*/
protected ResponseEntity<BaseResponse<?>> handleResultException(ResultException ex, HttpHeaders headers, WebRequest request) {
BaseResponse<?> body = BaseResponse.fail((ex.getErrorCodeEnum()));
HttpStatus status = null;
if (ex.getErrorCodeEnum().getErrorCode().intValue() >= 500000) {
status = HttpStatus.INTERNAL_SERVER_ERROR;
} else if (ex.getErrorCodeEnum().getErrorCode().intValue() >= 400000) {
status = HttpStatus.BAD_REQUEST;
}
return this.handleExceptionInternal(ex, body, headers, status, request);
} /**
* 异常类的统一处理
*/
protected ResponseEntity<BaseResponse<?>> handleException(Exception ex, HttpHeaders headers, WebRequest request) {
BaseResponse<?> body = BaseResponse.fail();
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
return this.handleExceptionInternal(ex, body, headers, status, request);
} /**
* org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
* handleExceptionInternal(java.lang.Exception, java.lang.Object, org.springframework.http.HttpHeaders,
* org.springframework.http.HttpStatus, org.springframework.web.context.request.WebRequest)
* <p>
* A single place to customize the response body of all exception types.
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
* request attribute and creates a {@link ResponseEntity} from the given
* body, headers, and status.
*/
protected ResponseEntity<BaseResponse<?>> handleExceptionInternal(
Exception ex, BaseResponse<?> body, HttpHeaders headers, HttpStatus status, WebRequest request) {
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
}
return new ResponseEntity<>(body, headers, status);
}
}
上述在返回String类型,以及Object等类型或者为空时会出现类型转换异常。做以下处理:
1、配置WebMvcConfigurer,将 MappingJackson2HttpMessageConverter
/旧版本 WebMvcConfigurerAdapter spring5弃用了 WebMvcConfigurerAdapter
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//提到最前面 ,主要为了处理基础类型时 XXX not cast String type 类似问题,结合请求类型必须为application/json
// 提前使用MappingJackson2HttpMessageConverter 处理 避免使用 StringHttpMessageConverter处理 String类型
converters.add(0,new MappingJackson2HttpMessageConverter());
}
}
主要作用://提到最前面 ,主要为了处理基础类型时 XXX not cast String type 类似问题,结合请求类型必须为application/json
// 提前使用MappingJackson2HttpMessageConverter 处理 避免使用 StringHttpMessageConverter处理 String类型
2、编写controller级别aop,主要作用处理,对象为null,以及String为null,转换为BaseResponse时的类型转换异常
/**
* 统一结果处理切面, 注意返回时 null 时候 处理
*/
@Aspect
@Component
public class ResponseAspect {
@Around("execution(* com.aaa.test.controller..*(..))")
public Object controllerProcess(ProceedingJoinPoint pjd) throws Throwable {
Object result = pjd.proceed();
// 是null特殊处理
if (result == null) {
try {
MethodSignature signature = (MethodSignature) pjd.getSignature();
Class returnType = signature.getReturnType();
if("java.lang.Object".equals(returnType.getName())){
// object 使用此方式
return BaseResponse.success(result);
}else if("java.lang.String".equals(returnType.getName())){
// 字符串 初始化一个新的返回
return returnType.newInstance();
}
//其他默认 返回
return result;
}catch (Exception ex){
ex.printStackTrace();
}
}
return result;
}
}
针对RestControllerAdvice 与swagger2 问题
如果 RestControllerAdvice 增加了 ResponseBody的拦截 此时swagger2会接收不到服务端资源。swagger2会接收自己的格式的数据,所以出问题,需要在 supports 方法处理过滤,其他有工具插件也需要过滤,或者所有controller的自定一个ResponseBody。如定义个注解ResponseResultBody,给对应的Controller使用 这里拦截 这个即可
003-maven开发Java脚手架archrtype-技术点说明的更多相关文章
- 002-maven开发Java脚手架archrtype【如无定制开发,请直接看3.3使用】
一.概述 项目基础构建需要:项目结构,spring框架,orm,连接池,数据库,单元测试等等. 上述即使复用:001-脚手架发展,基础代码结构+mybatis代码生成,基础代码结构,也需要修改成自己单 ...
- Java和.NET(C#)的开发用到的技术对比总结
前言 声明:我指的是一般的Java和.NET(C#)的后台开发用到的技术总结 最近一直在应聘ing,楼主的项目还是.NET(C#)项目居多,Java项目相对少,在这也吐槽下,招.NET(C#)的公司实 ...
- IntelliJ IDEA: maven & jetty 开发 java web
之前使用eclipse + maven + jetty开发java web应用,本着no zuo no gain的想法, 折腾了一下Intellj idea下开发环境的搭建,顺带学习了maven re ...
- 关于java' web杂谈(其实是课后作业1)1 网站系统开发需要掌握的技术
1 网站系统开发需要掌握的技术:(借鉴度娘)https://zhidao.baidu.com/question/1701850648247880220.html 需要掌握的有:Java(JavaEE) ...
- 《Maven在Java项目开发中的应用》论文笔记(十七)
标题:Maven在Java项目开发中的应用 一.基本信息 时间:2019 来源:山西农业大学 关键词:Maven:Java Web:仓库:开发人员:极限编程; 二.研究内容 1.Maven 基本原理概 ...
- 2016 年 Java 工具和技术的调查:IDEA 已超过
最近「技术最前线」看到 RebelLabs 做了一次 2016 年 Java 工具与技术的调查,调查报告虽然是 6 月公布的,但数据一点也不过时. 所以「技术最前线」忙会了一中午,写了这篇文章,带大家 ...
- java的JSP技术
java的JSP技术 [toc] 1.JSP简介 Jsp技术是用来开发java web的页面显示的,所有MVC模型里面的视图层,所以视图层的开发 jsp不是编程语言,三个英文是java server ...
- 崔用志-微信开发-java版本
崔用志-微信开发-java版本 今天看到一些关于微信开发的知识蛮好的博客,分享给大家,希望对大家有帮助. 微信开发准备(一)--Maven仓库管理新建WEB项目 微信开发准备(二)--springmv ...
- Atitit 开发2d游戏的技术选型attilax总结
Atitit 开发2d游戏的技术选型attilax总结 1.1. 跨平台跨平台:一定要使用跨平台的gui技术,目前最好的就是h5(canvas,webgl,dom) +js了..1 1.2. 游戏前后 ...
随机推荐
- A quick introduction to Source Insight for seamless development platform between Linux and Windows
前言 Source Insight是一个面向项目开发的程序编辑器和代码浏览器,它拥有内置的对C/C++, C#和Java等程序的分析.能分析源代码并在工作的同时动态维护它自己的符号数据库,并自动显示有 ...
- 【HICP Gauss】数据库 数据库管理(shutdown 日志 连接命令)-5
数据库关闭终止Zengine进程关闭数据库 会导致无法预料的状态 建议shutdown关闭数据库 shutdown 模式1.normal默认 停止新请求 断开等待会话 关闭服务 终止主进程 需要连接发 ...
- 关于struct和typedef struct
以 struct TelPhone{ ]; ]; }; 为例 这里先定义了一个 TelPhone的结构体. 加入需要为TelPhone定义一个别名: 其语法为 typedef TelPhone TP: ...
- 业余时间折腾了个微信小程序版本的街机游戏模拟器(吾爱街机),8090后的童年回忆,欢迎大家体验
好多年没来博客园了,有段时间想玩街机游戏,发现都需要下载安装,现在小程序这么流行,是不是可以集成到小程序里(无需下载,在线玩),出于这想法,就业余时间折腾了下,分享给大家,偶尔可以回味畅玩下. 中间遇 ...
- rhce 考试题目总结
rhce 考试题目总结归类 开机需要做的事: 检查系统版本 配置yum源 修改selinux的模式 ping一下server机器 1.分区类题目 1.1 rhcsa 第十五题 添加swap分区 要点: ...
- K3二次开发后台表
select * from icclasstype where fname_chs like '%供货%' 用此表基本上可以查询到所有的表 select * from POrequest --采购申请 ...
- Centos7安装HBase1.4
准备 1.hadoop集群已安装,这里将在Centos7安装Hadoop2.7的基础上安装hbase1.4,所以是同样的三台机器,其规划如下: hostname IP地址 部署规划 node1 172 ...
- ztree异步加载---------补发周日内容
上周六老师要求和大三的进行JAVA知识交流,总体来说就是给大三学长做的东西打分,然后大三学长再教我们如果构建ztree.毕竟第一次接触ztree,所以有很多不了解,但通过周六日努力,还是做出来了.现在 ...
- window对象方法(open和close)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 第三章 - SQL基础及元数据获取
SQL的介绍 SQL的定义:结构化查询语句 SQL的作用:对库和表进行操作 SQL的常用分类 DDL 数据定义语言(Data Definition Language) DCL 数据控制语言(Data ...