{"id":32,"date":"2022-10-19T11:44:35","date_gmt":"2022-10-19T03:44:35","guid":{"rendered":"http:\/\/www.leyiwangyou.top\/?p=32"},"modified":"2022-10-19T16:26:37","modified_gmt":"2022-10-19T08:26:37","slug":"%e4%bd%bf%e7%94%a8springbootangular%e5%bc%80%e5%8f%91%e4%b8%80%e4%b8%aatodolist","status":"publish","type":"post","link":"http:\/\/www.leyiwangyou.top\/?p=32","title":{"rendered":"\u4f7f\u7528springboot+angular\u5f00\u53d1\u4e00\u4e2atodolist"},"content":{"rendered":"<audio class=\"wp-audio-shortcode\" id=\"audio-32-1\" preload=\"none\" style=\"width: 100%;\" controls=\"controls\"><source type=\"audio\/mpeg\" src=\"http:\/\/www.leyiwangyou.top\/wp-content\/uploads\/2022\/10\/Arash-Dooset-Daram-Ft-Helena.mp3?_=1\" \/><a href=\"http:\/\/www.leyiwangyou.top\/wp-content\/uploads\/2022\/10\/Arash-Dooset-Daram-Ft-Helena.mp3\">http:\/\/www.leyiwangyou.top\/wp-content\/uploads\/2022\/10\/Arash-Dooset-Daram-Ft-Helena.mp3<\/a><\/audio>\n<h2>\u540e\u7aef\u4f7f\u7528springboot + spring data jpa<\/h2>\n<ol>\n<li>Bootstrap your application with Spring Initializr: <a href=\"https:\/\/start.spring.io\/\">https:\/\/start.spring.io\/<\/a><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.leyiwangyou.top\/wp-content\/uploads\/2022\/10\/img-20221019102250-300x127.png\" alt=\"\" \/><\/li>\n<li>\n<p>select Dependencies then grnreate.<\/p>\n<h3>\u6ce8\u518c\u767b\u5f55\u6a21\u5757<\/h3>\n<ul>\n<li>\u5b9e\u4f53\u7c7b<\/li>\n<\/ul>\n<pre><code class=\"language-java\">@Entity\n@Data\n@EntityListeners(AuditingEntityListener.class)\npublic class UserRecord {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Integer id;\n\n    private String name;\n\n    private String email;\n\n    private String password;\n\n    @CreatedDate\n    @Temporal(TemporalType.TIMESTAMP)\n    @JsonFormat(pattern = \"yyyy-MM-dd HH:mm:ss\",timezone=\"GMT+8\")\n    private Date createTime;\n\n    @LastModifiedDate\n    @Temporal(TemporalType.TIMESTAMP)\n    @JsonFormat(pattern = \"yyyy-MM-dd HH:mm:ss\",timezone=\"GMT+8\")\n    private Date updateTime;\n\n}<\/code><\/pre>\n<ul>\n<li>Repository<\/li>\n<\/ul>\n<pre><code class=\"language-java\">public interface UserRepository extends CrudRepository<UserRecord,Integer>{\nUserRecord findByName(String name);\n\nUserRecord findByNameAndPassword(String name,String password);\n}<\/code><\/pre>\n<ul>\n<li>Service<\/li>\n<\/ul>\n<pre><code class=\"language-java\">@Service\npublic class UserService {\n\nprivate final UserRepository userRepository;\n\npublic UserService(UserRepository userRepository){\n    this.userRepository = userRepository;\n}\n\npublic List<UserRecord> getAllUsers(){\n    List<UserRecord> userRecords = new ArrayList<>();\n    userRepository.findAll().forEach(userRecords::add);\n    return userRecords;\n}\n\npublic void addUser(UserRecord userRecord){\n    userRepository.save(userRecord);\n}\n\npublic void updateUser(UserRecord userRecord){\n    Optional<UserRecord> userRecordOptional = userRepository.findById(userRecord.getId());\n    if ( userRecordOptional.isPresent() )\n    {\n        UserRecord userRecordFind = userRecordOptional.get();\n        userRecordFind.setName(userRecord.getName());\n        userRecordFind.setEmail(userRecord.getEmail());\n        userRepository.save(userRecordFind);\n    }\n}\n\npublic UserRecord findByName(String name){\n   return userRepository.findByName(name);\n}\n\npublic UserRecord findByNameAndPassword(String name,String password){\n    return userRepository.findByNameAndPassword(name,password);\n}\n}<\/code><\/pre>\n<ul>\n<li>controller<\/li>\n<\/ul>\n<pre><code class=\"language-java\">@Log4j2\n@RestController\n@Tag(name = \"LoginController\", description = \"\u767b\u5f55\u63a5\u53e3\")\npublic class LoginController{\n\nprivate final UserService userService;\n\npublic LoginController(UserService userService){\n    this.userService = userService;\n}\n\n@PostMapping(value=\"\/sign-in\")\n@Operation(summary = \"\u767b\u5f55\", description = \"\u767b\u5f55\")\npublic Result signIn(@RequestBody UserRecord userRecord){\n    String password = DigestUtils.md5DigestAsHex(userRecord.getPassword()\n                                                         .getBytes(StandardCharsets.UTF_8));\n    UserRecord userRecordFind = userService.findByNameAndPassword(userRecord.getName(),password);\n    if ( userRecordFind != null){\n        return ResultUtil.getOK(userRecordFind);\n    }\n    return null;\n}\n\n@PostMapping(value=\"\/sign-up\")\n@Operation(summary = \"\u6ce8\u518c\", description = \"\u6ce8\u518c\")\npublic Result signUp(@RequestBody UserRecord userRecord) throws Exception{\n    UserRecord userRecordFind = userService.findByName(userRecord.getName());\n    if ( userRecordFind != null){\n        throw new Exception(\"user name already exist!\");\n    }\n    String password = DigestUtils.md5DigestAsHex(userRecord.getPassword()\n                                                  .getBytes(StandardCharsets.UTF_8));\n    userRecord.setPassword(password);\n    userService.addUser(userRecord);\n    return ResultUtil.getOK();\n}\n}<\/code><\/pre>\n<\/li>\n<\/ol>\n<h3>TODO CRUD\u6a21\u5757<\/h3>\n<ul>\n<li>\u5b9e\u4f53\u7c7b<\/li>\n<\/ul>\n<pre><code class=\"language-java\">@Entity\n@Data\n@EntityListeners(AuditingEntityListener.class)\n@ToString\npublic class TodoRecord extends AbstractBaseEntity{\n@Id\n@GeneratedValue(strategy = GenerationType.IDENTITY)\nprivate Integer id;\n\n@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = &quot;todoRecord&quot;)\nprivate List&lt;TodoRecordItem&gt; todoRecordItems = new ArrayList&lt;&gt;();\n\nprivate LocalDate todoDay;\n\n@CreatedDate\n@Temporal(TemporalType.TIMESTAMP)\n@JsonFormat(pattern = &quot;yyyy-MM-dd HH:mm:ss&quot;,timezone=&quot;GMT+8&quot;)\nprivate Date createTime;\n\n@LastModifiedDate\n@Temporal(TemporalType.TIMESTAMP)\n@JsonFormat(pattern = &quot;yyyy-MM-dd HH:mm:ss&quot;,timezone=&quot;GMT+8&quot;)\nprivate Date updateTime;\n}\n\n@Entity\n@Data\n@EntityListeners(AuditingEntityListener.class)\n@ToString(exclude = &quot;todoRecord&quot;)\npublic class TodoRecordItem\n{\n@Id\n@GeneratedValue(strategy = GenerationType.IDENTITY)\nprivate Integer id;\n\n@ManyToOne\n@JoinColumn(name = &quot;todo_record_id&quot;)\nprivate TodoRecord todoRecord;\n\nprivate String description;\n\nprivate Boolean completed = false;\n\n@CreatedDate\n@Temporal(TemporalType.TIMESTAMP)\n@JsonFormat(pattern = &quot;yyyy-MM-dd HH:mm:ss&quot;,timezone=&quot;GMT+8&quot;)\nprivate Date createTime;\n\n@LastModifiedDate\n@Temporal(TemporalType.TIMESTAMP)\n@JsonFormat(pattern = &quot;yyyy-MM-dd HH:mm:ss&quot;,timezone=&quot;GMT+8&quot;)\nprivate Date updateTime;\n}<\/code><\/pre>\n<ul>\n<li>Repository<\/li>\n<\/ul>\n<pre><code class=\"language-java\">public interface TodoRecordRepository extends CrudRepository&lt;TodoRecord,Integer&gt;{}\npublic interface TodoRecordItemRepository extends CrudRepository&lt;TodoRecordItem,Integer&gt;{}<\/code><\/pre>\n<ul>\n<li>Service<\/li>\n<\/ul>\n<pre><code class=\"language-java\">@Service\n@Transactional public class TodoRecordService{\n\n    private final TodoRecordRepository todoRecordRepository;\n\n    public TodoRecordService(TodoRecordRepository todoRecordRepository){\n        this.todoRecordRepository = todoRecordRepository;\n    }\n\n    public List&lt;TodoRecordDto&gt; getAllTodoRecords() throws Exception{\n        List&lt;TodoRecord&gt; todoRecords = new ArrayList&lt;&gt;();\n        todoRecordRepository.findAll().forEach(todoRecords::add);\n        List&lt;TodoRecordDto&gt; todoRecordDtos = todoRecords.stream()\n                .map(r -&gt; {\n                    TodoRecordDto todoRecordDto = new TodoRecordDto();\n                    todoRecordDto.setTodoRecordItems(r.getTodoRecordItems()\n                                                             .stream()\n                                                             .map(i -&gt; {\n                                                                 TodoRecordItemDto todoRecordItemDto = new TodoRecordItemDto();\n                                                                 todoRecordItemDto.setDescription(i.getDescription());\n                                                                 todoRecordItemDto.setCompleted(i.getCompleted());\n                                                                 todoRecordItemDto.setId(i.getId());\n                                                                 return todoRecordItemDto;\n                                                             })\n                                                             .collect(Collectors.toList()));\n                    if ( r.getTodoDay() != null )\n                    {\n                        todoRecordDto.setTodoDay(r.getTodoDay());\n                    }\n\n                    todoRecordDto.setId(r.getId());\n                    return todoRecordDto;\n                })\n                .collect(Collectors.toList());\n\n        return todoRecordDtos;\n    }\n\n    public void addTodoRecord(TodoRecordDto todoRecordDto) throws Exception{\n        TodoRecord todoRecord = new TodoRecord();\n        todoRecord.setTodoRecordItems(todoRecordDto.getTodoRecordItems()\n                                              .stream()\n                                              .map(i -&gt; {\n                                                  TodoRecordItem todoRecordItem = new TodoRecordItem();\n                                                  todoRecordItem.setDescription(i.getDescription());\n                                                  todoRecordItem.setTodoRecord(todoRecord);\n                                                  return todoRecordItem;\n                                              })\n                                              .collect(Collectors.toList()));\n        todoRecord.setTodoDay(todoRecordDto.getTodoDay());\n        todoRecordRepository.save(todoRecord);\n    }\n\n    public void deleteTodoRecord(Integer id){\n        todoRecordRepository.deleteById(id);\n    }\n}\n<\/code><\/pre>\n<ul>\n<li>\n<p>Controller<\/p>\n<pre><code class=\"language-java\">\n@RestController\n@Tag(name = &quot;TodoRecordController&quot;, description = &quot;\u6e05\u5355\u63a5\u53e3&quot;)\npublic class TodoRecordController{\n\nprivate final TodoRecordService todoRecordService;\n\nprivate final TodoRecordItemService todoRecordItemService;\n\npublic TodoRecordController(TodoRecordService todoRecordService,TodoRecordItemService todoRecordItemService){\n    this.todoRecordService = todoRecordService;\n    this.todoRecordItemService = todoRecordItemService;\n}\n\n@EnableFilter\n@GetMapping(&quot;\/getAllTodoRecord&quot;)\n@Operation(summary = &quot;\u67e5\u8be2\u6240\u6709\u6e05\u5355&quot;, description = &quot;\u67e5\u8be2\u6240\u6709\u6e05\u5355&quot;,security = { @SecurityRequirement(name = &quot;TENANT-ID&quot;) })\npublic Result getAllTodoRecords() throws Exception{\n    List&lt;TodoRecordDto&gt; allTodoRecords = todoRecordService.getAllTodoRecords();\n    return ResultUtil.getOK(allTodoRecords);\n}\n\n@PostMapping(value=&quot;\/add-todoRecord&quot;)\n@Operation(summary = &quot;\u521b\u5efa\u6e05\u5355&quot;, description = &quot;\u521b\u5efa\u6e05\u5355&quot;,security = { @SecurityRequirement(name = &quot;TENANT-ID&quot;) })\npublic Result addTodoRecord(@RequestBody TodoRecordDto todoRecordDto) throws Exception{\n    todoRecordService.addTodoRecord(todoRecordDto);\n    return ResultUtil.getOK();\n}\n\n@DeleteMapping(value=&quot;\/todoRecord\/{id}&quot;)\n@Operation(summary = &quot;\u5220\u9664\u6e05\u5355&quot;, description = &quot;\u5220\u9664\u6e05\u5355&quot;)\npublic Result deleteTodoRecord(@PathVariable(&quot;id&quot;) Integer id){\n    todoRecordService.deleteTodoRecord(id);\n    return ResultUtil.getOK();\n}\n\n@PostMapping(value=&quot;\/update-todoRecordItem&quot;)\n@Operation(summary = &quot;\u66f4\u65b0\u5355\u4e2a\u4efb\u52a1&quot;, description = &quot;\u66f4\u65b0\u5355\u4e2a\u4efb\u52a1&quot;)\npublic Result updateTodoRecord(@RequestBody TodoRecordItem todoRecordItem){\n    todoRecordItemService.updateTodoRecordItem(todoRecordItem);\n    return ResultUtil.getOK();\n}\n}\n```<\/code><\/pre>\n<\/li>\n<\/ul>\n<h2>\u524d\u7aef\u4f7f\u7528angular\u6846\u67b6<\/h2>\n<ol>\n<li>install angular cli\n<pre><code class=\"language-bash\">npm install -g @angular\/cli\nng generate --help<\/code><\/pre>\n<p>\u4f7f\u7528angular cli\u521b\u5efa\u9879\u76ee\uff0c\u7ec4\u4ef6\uff0cservice\uff0c\u6253\u5305\u7b49<\/p>\n<pre><code class=\"language-bash\">ng new my-first-project\ncd my-first-project\nng serve\nng g c add-todo\nng build clean\nng build --configuration=production<\/code><\/pre>\n<\/li>\n<li>\u767b\u5f55\u6ce8\u518c\u9875\u9762<br \/>\nlogin.component.html<\/li>\n<\/ol>\n<pre><code class=\"language-bash\">< div class=\"main-wrapper\" fxLayout=\"row\" fxLayoutAlign=\"center center\">\n  < mat-card class=\"box\">\n    < mat-card-header>\n      < mat-card-title>Login< \/mat-card-title>\n    < \/mat-card-header>\n    < form class=\"example-form\" [formGroup]=\"loginForm\"  (submit)=\"login()\">\n      < mat-card-content>\n        < mat-form-field class=\"example-full-width\">\n          < input matInput placeholder=\"Username\" formControlName=\"name\" type=\"text\">\n          < mat-error>This field is mandatory.<\/mat-error>\n        < \/mat-form-field>\n\n        < mat-form-field class=\"example-full-width\">\n          < input matInput placeholder=\"Password\" formControlName=\"password\" type=\"password\">\n          < mat-error>This field is mandatory.< \/mat-error>\n        < \/mat-form-field>\n      < \/mat-card-content>\n      < button mat-stroked-button color=\"accent\" class=\"btn-block\"  [disabled]=\"loginForm.invalid\">Login< \/button>\n    < \/form>\n  < \/mat-card>\n< \/div><\/code><\/pre>\n<p>register.component.html<\/p>\n<pre><code class=\"language-bash\">< div class=\"main-wrapper\" fxLayout=\"row\" fxLayoutAlign=\"center center\">\n  < mat-card class=\"box\">\n    < mat-card-header>\n      < mat-card-title>Register< \/mat-card-title>\n    < \/mat-card-header>\n    < form class=\"example-form\" [formGroup]=\"form\"  (submit)=\"register()\">\n      < mat-card-content>\n        < mat-form-field class=\"example-full-width\">\n          < input  formControlName=\"name\" matInput placeholder=\"Username\">\n          < mat-error>This field is mandatory.< \/mat-error>\n        < \/mat-form-field>\n        < mat-form-field class=\"example-full-width\">\n          < input formControlName=\"email\" matInput placeholder=\"Email\">\n          < mat-error>Invalid email address.< \/mat-error>\n        < \/mat-form-field>\n        < mat-form-field class=\"example-full-width\">\n          < input formControlName=\"password\" matInput placeholder=\"Password\" type=\"password\">\n          < mat-error>This field is mandatory.< \/mat-error>\n        < \/mat-form-field>\n      < \/mat-card-content>\n      < button mat-stroked-button color=\"accent\" class=\"btn-block\"  [disabled]=\"form.invalid\">Register< \/button>\n    < \/form>\n  < \/mat-card>\n< \/div><\/code><\/pre>\n<p>login.component.ts<\/p>\n<pre><code class=\"language-ts\">@Component({\n  selector: 'app-login',\n  templateUrl: '.\/login.component.html',\n  styleUrls: ['.\/login.component.css']\n})\nexport class LoginComponent implements OnInit {\n\n  public loginForm: FormGroup = new FormGroup({\n    name: new FormControl('',Validators.required),\n    password: new FormControl('', Validators.required),\n  });\n\n  constructor(private registerService:RegisterService, private notificationService: NotificationService,\n    private router: Router,private tokenStorageService: TokenStorageService) { }\n\n  ngOnInit(): void {\n  }\n\n  login() {\n    if (this.loginForm.valid) {\n      this.registerService.login(this.loginForm.value).subscribe((response:Result)=>{\n        console.log(response);\n        if(response.code == 0){\n          this.tokenStorageService.saveUser(response.data);\n          this.notificationService.success('login successfully');\n          this.goTodo();\n        }else{\n          this.notificationService.success('login fail');\n        }\n\n      });\n    }\n  }\n\n  goTodo() {\n    this.router.navigate(['app']).then(()=>{\n      window.location.reload();\n    });\n    this.router.navigate(['todo']);\n  }\n\n}<\/code><\/pre>\n<p>register.component.ts<\/p>\n<pre><code class=\"language-ts\">@Component({\n  selector: 'app-register',\n  templateUrl: '.\/register.component.html',\n  styleUrls: ['.\/register.component.css']\n})\nexport class RegisterComponent implements OnInit {\n\n  constructor(private registerService:RegisterService, private notificationService: NotificationService,\n    private router: Router) { }\n\n  ngOnInit(): void {\n  }\n\n  public form: FormGroup = new FormGroup({\n    id : new FormControl(null),\n    name: new FormControl('',Validators.required),\n    email: new FormControl('', Validators.email),\n    password: new FormControl('', Validators.required),\n  });\n\n  register(){\n    if (this.form.valid) {\n      this.registerService.register(this.form.value).subscribe((result:Result)=>{\n        console.log(result);\n        if(result.code == 0){\n          this.notificationService.success('register successfully, please login');\n          this.goToLogin();\n        }else{\n          this.notificationService.warn(result.msg);\n        }\n      });\n    }\n  }\n\n  goToLogin() {\n    this.router.navigate(['login']);\n  }\n}<\/code><\/pre>\n<ol start=\"3\">\n<li>TODO list\u9875\u9762<br \/>\ntodo.component.html<\/li>\n<\/ol>\n<pre><code class=\"language-bash\">< div class=\"content\">\n  < div fxLayout=\"row wrap\" fxLayoutGap=\"16px grid\">\n    < div fxFlex=\"25%\" fxFlex.xs=\"100%\" fxFlex.sm=\"33%\" *ngFor=\"let todoRecord of todoRecords\">\n      < mat-card class=\"mat-elevation-z4 backgroundImage\">\n        < mat-card-header>\n          < mat-card-title>{{todoRecord.todoDay}}<\/mat-card-title>\n        < \/mat-card-header>\n        < mat-card-content>\n          < mat-selection-list>\n            < mat-list-option  *ngFor=\"let todoRecordItem of todoRecord.todoRecordItems\" [selected]=\"todoRecordItem.completed\" (click)=\"updateCompleted(todoRecordItem)\">\n              < p  [ngStyle]=\"{'text-decoration':todoRecordItem.completed ? 'line-through' : '' }\">\n                {{todoRecordItem.description}}\n              < \/p>\n            < \/mat-list-option>\n          < \/mat-selection-list>\n        < \/mat-card-content>\n        < mat-card-actions>\n          < button mat-button (click)=\"deleteTodo(todoRecord.id)\">< mat-icon>clear< \/mat-icon>< \/button>\n        < \/mat-card-actions>\n      < \/mat-card>\n    < \/div>\n  < \/div>\n  < \/div><\/code><\/pre>\n<p>todo.component.ts<\/p>\n<pre><code class=\"language-ts\">@Component({\n  selector: 'app-todo',\n  templateUrl: '.\/todo.component.html',\n  styleUrls: ['.\/todo.component.css'],\n  providers: [TodoService]\n})\nexport class TodoComponent implements OnInit {\n\n  todoRecords?: TodoRecord[];\n  desc = '';\n  result!: Result;\n  constructor(private todoService:TodoService) { }\n\n  ngOnInit() {\n    this.getTodos();\n  }\n\n  getTodos(){\n    this.todoService.getTodos().subscribe((result)=>{\n      console.log(result);\n      this.todoRecords=result.data;\n      console.log(this.todoRecords);\n    })\n  }\n\n  deleteTodo(id: any){\n    this.todoService.delteTodos(id).subscribe(response=>{\n      this.getTodos();\n    });\n  }\n\n  updateCompleted(todo: Todo) {\n    this.todoService.updateCompleted(todo).subscribe(response=>{\n      this.getTodos();\n    });\n  }\n}<\/code><\/pre>\n<p>\u8bf7\u6c42\u540e\u7aeftodo.service.ts<\/p>\n<pre><code class=\"language-ts\">const baseUrl = 'http:\/\/localhost:8080\/';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class TodoService {\n\n  todos: Todo[] = [];\n\n  constructor(private http: HttpClient,private tokenStorageService:TokenStorageService) { }\n\n  addTodo(todo: any){\n    const user = this.tokenStorageService.getUser();\n    const headers= new HttpHeaders({'TENANT-ID': user.id.toString()});\n    return this.http.post(baseUrl + 'add-todoRecord', todo,{'headers':headers}).subscribe(response=>{\n      console.log(response);\n    });\n  }\n\n  getTodos():Observable<Result>{\n    const user = this.tokenStorageService.getUser();\n    const headers= new HttpHeaders({'TENANT-ID': user.id.toString()});\n    return this.http.get<Result>(baseUrl + 'getAllTodoRecord\/',{'headers':headers});\n  }\n\n  delteTodos(id:number){\n    return this.http.delete(baseUrl + 'todoRecord\/' + id);\n  }\n\n  updateCompleted(todo: Todo) {\n    return this.http.post(baseUrl + 'update-todoRecordItem', todo);\n  }\n}<\/code><\/pre>\n<h2>\u6570\u636e\u5e93\u4f7f\u7528postgresql<\/h2>\n<pre><code class=\"language-bash\">POM\u6587\u4ef6\u914d\u7f6e\n\n< dependency>\n    < groupId>org.postgresql< \/groupId>\n    < artifactId>postgresql< \/artifactId>\n    < scope>runtime< \/scope>\n< \/dependency><\/code><\/pre>\n<p>application.properties\u6587\u4ef6\u914d\u7f6e<\/p>\n<pre><code class=\"language-properties\">spring.datasource.hikari.connectionTimeout=20000\nspring.datasource.hikari.maximumPoolSize=5\n\nspring.datasource.url=jdbc:postgresql:\/\/localhost:5432\/test\nspring.datasource.username=postgres\nspring.datasource.password=password\n\nspring.jpa.hibernate.ddl-auto=update\nspring.jpa.show-sql=true<\/code><\/pre>\n<h2>\u524d\u540e\u7aef\u5408\u5e76\u90e8\u7f72\u6253\u5305\u6210docker\u955c\u50cf<\/h2>\n<ol>\n<li>\u5c06\u524d\u7aef\u6253\u5305\u540e\u7684\u6587\u4ef6\u590d\u5236\u5230resource\/static\u76ee\u5f55\u4e0b<\/li>\n<li>\u5f15\u5165dockerfile-maven-plugin\u63d2\u4ef6\uff0c\u914d\u7f6e\u81ea\u5df1\u7684\u955c\u50cf\u4ed3\u5e93\u5730\u5740<\/li>\n<\/ol>\n<pre><code class=\"language-bash\">< plugin>\n    < groupId>com.spotify< \/groupId>\n    < artifactId>dockerfile-maven-plugin< \/artifactId>\n    < version>1.4.8< \/version>\n    < executions>\n        < execution>\n            < id>default< \/id>\n            < goals>\n                < goal>build< \/goal>\n                < goal>push< \/goal>\n            < \/goals>\n        < \/execution>\n    < \/executions>\n    < configuration>\n        < repository>yourRepository\/todo< \/repository>\n        < tag>${project.version}< \/tag>\n    < \/configuration>\n< \/plugin><\/code><\/pre>\n<ol start=\"3\">\n<li>\u5f00\u542flocalhost\/127.0.0.1\u7aef\u53e32375\u7684\u76d1\u542c<br \/>\n<img decoding=\"async\" src=\"http:\/\/www.leyiwangyou.top\/wp-content\/uploads\/2022\/10\/img-20221019110826-300x140.png\" alt=\"\" \/><\/li>\n<\/ol>\n<h2>\u4f7f\u7528springdoc-openapi\u7ba1\u7406\u6587\u6863<\/h2>\n<ol>\n<li>\u5f15\u5165dependency<\/li>\n<\/ol>\n<pre><code class=\"language-bash\">< dependency>\n    < groupId>org.springdoc< \/groupId>\n    < artifactId>springdoc-openapi-ui< \/artifactId>\n    < version>1.6.11< \/version>\n< \/dependency><\/code><\/pre>\n<ol start=\"2\">\n<li>\u914d\u7f6eSpringDoc<\/li>\n<\/ol>\n<pre><code class=\"language-java\">@Configuration\npublic class SpringDocConfig\n{\n    @Bean\n    public OpenAPI myOpenAPI()\n    {\n        return new OpenAPI().components(new Components()\n                             .addSecuritySchemes(\"TENANT-ID\", securityScheme(\"TENANT-ID\"))\n        ).info(new Info().title(\"SpringDoc\")\n                                          .description(\"\u6d4b\u8bd5 SpringDoc\")\n                                          .version(\"v1.0.0\"));\n    }\n\n    private SecurityScheme securityScheme(String name) {\n        return new io.swagger.v3.oas.models.security.SecurityScheme()\n                .type(io.swagger.v3.oas.models.security.SecurityScheme.Type.APIKEY)\n                .in(io.swagger.v3.oas.models.security.SecurityScheme.In.HEADER)\n                .name(name);\n    }\n}<\/code><\/pre>\n<ol start=\"3\">\n<li>\n<p>\u542f\u52a8\u9879\u76ee\u8bbf\u95ee\u9875\u9762\uff1a<a href=\"http:\/\/localhost:8080\/swagger-ui\/index.html\">http:\/\/localhost:8080\/swagger-ui\/index.html<\/a><\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.leyiwangyou.top\/wp-content\/uploads\/2022\/10\/img-20221019113550-300x139.png\" alt=\"\" \/><\/p>\n<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>\u540e\u7aef\u4f7f\u7528springboot + spr<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-32","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=\/wp\/v2\/posts\/32","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=32"}],"version-history":[{"count":25,"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=\/wp\/v2\/posts\/32\/revisions"}],"predecessor-version":[{"id":65,"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=\/wp\/v2\/posts\/32\/revisions\/65"}],"wp:attachment":[{"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=32"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=32"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.leyiwangyou.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=32"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}