您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
matthew.ng 14cf887b2e add build.bat command for build pj and changed config 2 年前
gradle/wrapper first commit 2 年前
src add build.bat command for build pj and changed config 2 年前
.gitignore first commit 2 年前
README.md first commit 2 年前
build.bat add build.bat command for build pj and changed config 2 年前
build.gradle write data into db 2 年前
example.launch.json Saving wok's sensor data 2 年前
gradlew first commit 2 年前
gradlew.bat first commit 2 年前
hs_err_pid10376.log Saving wok's sensor data 2 年前
settings.gradle Saving wok's sensor data 2 年前

README.md

frontend:

  • Routes.js (path: ‘xxxWin’ for Window component)
  • load js resources:
    // option 1
    items: [
      Ext.create('App.test.TestPanel',{
        title: 'Title 1'
      }),
      {
        xtype: 'panel',
        title: 'Title 2'
      }
    ]
    
    // option 2
    requires: ['App.xxxx.XxxxPanel'],
    items: [{
      xtype: 'test.testPanel',
      title: 'Title 1'
    }]
    
  • get component e.g.
    me.down('test\\.testPanel') //alias: 'widget.test.testPanel'
    
  • i18n: static/public/i18n/{locale}.json
    // component level
    bind: {
      text: '{i18n.xx.xx}'
    }
    // program level
    App.getI18n('xx.xx') // or App.getI18n().xx.xx
    
  • security
    • App.security.getUser()
    • App.security.isGranted(string | string[])
    • App.security.isGrantedAll(string[])

backend (draft):

  • vs code dev: example.launch.json
  • db migration: resources/db/changelog/changes/** (support subfolder)
    • suggested that one changeset with one DDL
    • filename: {yyyyMMdd}_{number}_{name}/{number}_{name}.sql
    • filename 2(optional): {yyyyMMdd}_{number}_{name}/{number}_{name}/{number}_{name}.sql
    --liquibase formatted sql
    
    --changeset {name}:{id}
    --comment: remarks (optional)
    CREATE TABLE `tableName` (
      `id` INT PRIMARY KEY AUTO_INCREMENT,
      `created` DATETIME NOT NULL DEFAULT NOW(),
      `createdBy` VARCHAR(30),
      `version` INT NOT NULL DEFAULT 0,
      `modified` DATETIME NOT NULL DEFAULT NOW(),
      `modifiedBy` VARCHAR(30),
      `deleted` BOOLEAN NOT NULL DEFAULT FALSE,
    
      `column1` INT NOT NULL,
      `column2` VARCHAR(255)
    );
    
  • controller
    • AbstractController
    • api: /public/** /protected/**
    • RequestBody Class (@NotNull, @NotBlank, @Min, @Max, @Pattern, etc...)
    @NotNull
    @Pattern(regexp = "^Y$|^N$")
    private String YesNo;
    
    • authentication check: @PreAuthorize
    • common response class DataRes, IdRes, RecrodsRes, SuccessRes
    • RESTfull api (http method, http status)
      • http status:
        • 404: record not found
        • 409: record_line not found or record_line not under the record (relation check)
        • 422: something wrong, (e.g. qty not enough)
      • suggest /save api (also allowed for POST: new, PUT: update)
        1. POST /xxxx/save
        2. body:
        {
          "id": 1, //update
          "xx": "xx",
          "updateLines": [
            {
              "id": null, // new
              "xx": "xx"
            },
            {
              // need a relation check
              "id": 1, //update
              "xx": "xx"
            }
          ],
          // need a relation check
          "deleteLineIds": [1, 2]
        }
        
    //example
    @RestController
    @RequestMapping("/xxxx")
    public class ExampleController extends AbstractController {
    
      @PostMapping('/xxx') // @GetMapping @DeleteMapping @PutMapping @PatchMapping
      //@ResponseStatus(HttpStatus.CREATED)
      //@PreAuthorize("hasAuthority('XXX_MAINT')")
      public Xxxx api (@RequestBody @Valid ReqClass req) {
      }
    
      @GetMapping('/{id}')
      public Xxxx getXxx (@PathVariable int id) {
      }
    }
    
  • service
    • AbstractService, AbstractIdEntityService, AbstractBaseEntityService
    • @Transactional(rollbackFor = Exception.class) for write, read only not need transaction
  • dao
    public Optional<User> findByUsernameAndDeletedFalse(String username);
    // same
    @Query("FROM #{#entityName} u WHERE u.deleted = FALSE AND u.username = :username")
    public Optional<User> findByUsername(@Param("username") String username);
    
  • entity
    • IdEntity, BaseEntity
    • validation: @NotNull, @NotBlank, @Min, @Max, @Pattern, etc...
  • jdbcDao
  • reduce @Autowired
    • use constructor
    • try separate class (e.g. FileListController, FileDownloadController)
  • return Optional instead of null
    • return Optional<T> : may null
    • return T : must not null
  • i18n: i18n/messages_{locale(underscore)}.properties
    • messageSource.getMessage("name", null, LocaleUtils.getLocale());
  • reporting:
    • excel:
      • files:
        • excel/{filename}.xlsx
        • excel/{filename}_zh-TW.xlsx
        • excel/{filename}_zh-CN.xlsx
      • load Workbook: ExcelUtils.loadTemplate("excel/{filename}");
      • send out Workbook: ExcelUtils.send(response, workbook, "filename"); // will output filename.xlsx
    • jasper
      • files:
        • reports/{filename}.jrxml
        • reports/{filename}_zh-TW.jrxml
        • reports/{filename}_zh-CN.jrxml
      • compile: JasperUtils.compile("reports/{filename}", params, new JRBeanCollectionDataSource(xxx), Map.of("subReport1","reports/{filename}"));
      • send out: JasperUtils.responsePdf(response, jRerpot, "filename"); // will output filename.pdf
  • mobile:
    • login: POST /mobile/login
    • logout: POST /mobile/logout
    • call api: http headers with
      1. X-ATT-DeviceId
      2. X-ATT-Access-Token