分类:代码

码农是第一生产力。

Angular 对话框使用

注入对话框引用

constructor(private dialogRef: MatDialogRef<AddOrderDialogComponent>) {
}

输入框校验

<mat-form-field>
  <input matInput type="email" placeholder="Email" tabindex="2" [ngModel]="email"
         (ngModelChange)="onEmailChange($event)" [formControl]="emailInput">
  <mat-error *ngIf="emailInput.hasError('email')">Error email format.</mat-error>
</mat-form-field>
emailInput = new FormControl();

onEmailChange(email: string) {
  this.email = email;
  if (this.emailAuth == true) {
    if (this.emailInput.hasError('email'))
      this.machine = '';
    else
      this.machine = this.getMachine(this.email);
  }
}

调用对话框

onAddOrder() {
  var dialogRef = this.addOrderDialog.open(AddOrderDialogComponent, {width: '300px'});
  dialogRef.componentInstance.product = this.selectProduct;
  dialogRef.afterClosed().subscribe(order => {
    this.regDataDao.addOrder(this.selectProduct, order).subscribe(data => {
      console.log(data);
      this.dataSource.data.push(data);
      this.dataSource.data = this.dataSource.data;
    });
  });
}

关闭对话框

onAddOrder() {
  var result = {name: this.name, email: this.email, machine: this.machine};
  // console.log(result);
  this.dialogRef.close(result);
}

Spring Boot + RestController 配置

RestController 类注解

  • 类注解
  • 根路径

    @RestController
    @RequestMapping("/v1")
    public class RegistratonController {
    

Get 方法

  • 对应查询操作
  • 获取路径参数
  • 获取 URL 参数
  • 无 Post 内容

    @GetMapping(value = "/orders/{product}")
    public List<OrderItem> getOrder(@PathVariable String product,
                                    @RequestParam("column") String column,
                                    @RequestParam("value") String value) {
    

Post 方法

  • 对应 Add 操作
  • 获取路径参数
  • 获取 Post data

    @PostMapping(value = "/orders/{product}")
    public OrderItem addOrder(@PathVariable String product, @RequestBody String json) {
    

Put 方法

  • 一般对应 update 操作
  • 获取路径参数
  • 获取 Post data

    @PutMapping(value = "/orders/{product}")
    public OrderItem updateOrder(@PathVariable String product, @RequestBody String json) {
    

Delete 方法

  • 一般对应 Delete 操作
  • 获取路径参数

    @DeleteMapping(value = "/orders/{product}/{id}")
    public ResponseEntity<OrderItem> deleteOrder(@PathVariable String product, @PathVariable int id) {
    

Spring Boot + JDBC 配置

MySQL 配置

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/registration
    username: root
    password: 123456

DAO 注解

  • DAO 注解
  • jdbcTemplate 自动注入
@Repository
public class RegistrationDAOImpl implements BaseRegistrationDAO {

  private JdbcTemplate jdbcTemplate;

  @Autowired
  public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }
  ...
}

RowMapper 实现

class OrderMapper implements RowMapper<OrderItem> {
  @Override
  public OrderItem mapRow(ResultSet rs, int rowNum) throws SQLException {
    OrderItem orderItem = new OrderItem();
    orderItem.id = rs.getInt("id");
    orderItem.name = rs.getString("UserName");
    return orderItem;
  }
}

查询实现

public List<OrderItem> getOrderItem(String product, String column, String value) {
  String sql = "SELECT id, UserName from my_" + product + " WHERE " + column + "=?";
  return jdbcTemplate.query(sql, new Object[]{value}, new OrderMapper());
}

得到新插入行的 ID

GeneratedKeyHolder holder = new GeneratedKeyHolder();
    jdbcTemplate.update(con -> {
      PreparedStatement statement = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
      statement.setString(1, orderItem.name);
      statement.setString(2, orderItem.email);
      return statement;
    }, holder);
    orderItem.id = holder.getKey().intValue();

Spring Boot + Jpa 配置

H2 配置

spring:
  datasource:
    url: jdbc:h2:r:/myh2
    driver-class-name: org.h2.Driver
    username: root
    password: 123456
  jpa:
    generate-ddl: true
    hibernate:
      ddl-auto: create
      naming:
        strategy: org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy
    show-sql: true
  h2:
    console:
      enabled: true
      path: /console

Bean 扫描注解

  • bean 扫描路径
  • repository bean 扫描路径
  • entity bean 扫描路径
  • getBean method

    @SpringBootApplication
    @ComponentScan("com.fj")
    @EnableJpaRepositories("com.fj.dao")
    @EntityScan("com.fj.entity")
    public class H2jpa01Application {
    
      public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(H2jpa01Application.class, args);
    
        VideoService service = context.getBean(VideoService.class);
        service.addFile("test.mp4");
      }
    }
    
    

Entity 注解

  • 表注解
  • 自增 ID 注解
  • 列注解

    @Entity
    public class Video {
    
      @Id
      @GeneratedValue
      private long id;
    
      @Column
      private Date gmtCreate;
    
      @Column
      private Date gmtModify;
    
      @Column
      private String fileName;
    
      ...//getter and setter
    }
    

Repository 注解

  • Repository 注解
  • 声明为 interface
  • 模板参数为 Entiry, ID 数据类型

    @Repository
    public interface VideoDAO extends CrudRepository<Video, Long> {
    }
    

Service 注解

  • Service 注解
  • DAO 自动注入
  • DAO 方法调用

    @Service
    public class VideoService {
    
      @Autowired
      private VideoDAO videoDAO;
    
      public void addFile(String fileName) {
        Video video = new Video(fileName);
        videoDAO.save(video);
      }
    }
    

Spring Boot + Spring Security + Angular 配置

最简单配置

  • 弹出登录对话框
  • 自定义用户名密码

    @Configurable
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        public void configure(HttpSecurity httpSecurity) {
            try {
                httpSecurity.authorizeRequests().anyRequest().authenticated()
                        .and()
                        .httpBasic();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Autowired
        public void ConfigureGlobal(AuthenticationManagerBuilder auth) {
            try {
                auth.inMemoryAuthentication().withUser("root").password("123456").roles("ADMIN");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

自定义 LoginForm

  • 自定义 form 提交地址
  • 认证结果不跳转
  • 登录对话框中,允许资源访问

    @Configurable
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private CustomAuthFailureHandler customAuthFailureHandler;
    
        @Autowired
        private CustomLoginSuccessHandler customLoginSuccessHandler;
    
        @Autowired
        private CustomLogoutSuccessHandler customLogoutSuccessHandler;
    
        Gson gson = new Gson();
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/login").permitAll()
                        .anyRequest().authenticated()
                        .and()
                    .formLogin()
                        .loginPage("/login").loginProcessingUrl("/auth")
                        .successHandler(customLoginSuccessHandler)
                        .failureHandler(customAuthFailureHandler)
                        .and()
                    .logout().permitAll().logoutSuccessUrl("/logout")
                        .logoutSuccessHandler(customLogoutSuccessHandler)
            ;
            http.csrf().disable();
        }
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().regexMatchers(".*\\.js", ".*\\.css", ".*\\.ico", ".*\\.woff2");
        }
    
        @Autowired
        public void ConfigureGlobal(AuthenticationManagerBuilder auth) {
            try {
                auth.inMemoryAuthentication()
                        .withUser("root").password("123456").roles("ADMIN");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        protected class NoRedirectStrategy implements RedirectStrategy {
            @Override
            public void sendRedirect(HttpServletRequest request,
                                     HttpServletResponse response, String url) throws IOException {
                // no redirect
            }
        }
    
        @Component
        public class CustomLoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    
            public CustomLoginSuccessHandler() {
                super();
                setRedirectStrategy(new NoRedirectStrategy());
            }
    
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request,
                                                HttpServletResponse response,
                                                Authentication authentication)
                    throws ServletException, IOException {
                super.onAuthenticationSuccess(request, response, authentication);
                Writer writer = response.getWriter();
                writer.write(gson.toJson("success"));
            }
        }
    
        @Component
        public class CustomAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    
            public CustomAuthFailureHandler() {
                super();
                setRedirectStrategy(new NoRedirectStrategy());
            }
    
            @Override
            public void onAuthenticationFailure(HttpServletRequest request,
                                                HttpServletResponse response,
                                                AuthenticationException exception)
                    throws IOException, ServletException {
                String error = exception.getMessage();
                //getRedirectStrategy().sendRedirect(request, response, "/login?error=" + error);
                Writer writer = response.getWriter();
                writer.write(gson.toJson(error));
            }
        }
    
        @Component
        public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
            @Override
            public void onLogoutSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication)
                    throws IOException, ServletException {
                Writer writer = response.getWriter();
                writer.write(gson.toJson("success"));
            }
        }
    }
    

Angular 提交

  • 登录

    onLogin() {
        const url = '/auth';
        // let data = {username: this.username, password: this.password };
        // let data = "username=" + this.username + "&password=" + this.password;
        let params = new URLSearchParams();
        params.set('username', this.username);
        params.set('password', this.password);
    
        let header = {
          headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded'),
        };
    
        this.http.post(url, params.toString(), header).subscribe(
          data => {
            console.log(data);
            if (data != null && data == 'success') {
              this.router.navigateByUrl("/");
            } else {
              let snackBarRef = this.snackBar.open("Login failed. " + data, "CLOSE", {
                duration: 3000
              });
              snackBarRef.onAction().subscribe();
            }
          },
          err => {
            console.log("error: " + err.errorMsg);
          }
        );
      }
    
  • 登出

    logout() {
      this.http.get('/logout').subscribe( data => {
        this.router.navigateByUrl('/login');
      });
    }