# Spring Boot ## [spring initializr](https://start.spring.io/) ### [IOC](https://en.wikipedia.org/wiki/Inversion_of_control) - [DI (Dependency Injection)](https://www.educative.io/answers/what-is-dependency-injection-in-java) - [ref 2](https://medium.com/groupon-eng/dependency-injection-in-java-9e9438aa55ae) ### controller / service / repository ```java @RestController @RequestMapping(value = "/rest/employee") public class EmployeeController { @Autowired @Qualifier("employeeService") private IEmployeeService employeeService; } ``` ### [AOP](https://openhome.cc/Gossip/SpringGossip/AOPConcept.html) - design pattern [proxy](https://refactoring.guru/design-patterns/proxy) ![](https://i.imgur.com/79C30su.png) ![](https://i.imgur.com/bvvEz64.png) ```java @Aspect @Component public class ServiceAspect { @Pointcut("execution(* com.demo.service.*.*(..))") public void serviceMethods() { // only use for AOP pointcut } @Before(value = "serviceMethods()") public void serviceBefore(JoinPoint joinPoint) { //...... } } ``` ### Architecture - MVC - 3-tier ### RESTful API ### ORM 選讀 - [JPA](https://www.vogella.com/tutorials/JavaPersistenceAPI/article.html) - [sample](https://bitbucket.org/re102162189/springboot_jpa_mybatis_security/src/master/src/main/java/com/demo/service/SkillService.java) ```java @Service public class SkillService implements ISkillService { @Autowired private SkillRepository skillRepository; @Override public Optional<Skill> findByIdJpa(long id) { return skillRepository.findById(id); } @Override public Optional<Skill> findByIdJpaQuery(long id) { return skillRepository.findByIdUsingQuery(id); } } public interface SkillRepository extends JpaRepository<Skill, Long> { @Query("SELECT s FROM Skill s JOIN FETCH s.employees e WHERE s.id = :id") Optional<Skill> findByIdUsingQuery(@Param("id") long id); } ``` ### MyBatis / JDBCTemplate - [sample](https://bitbucket.org/re102162189/springboot_jpa_mybatis_security/src/master/src/main/java/com/demo/jdbc/dao/SkillJdbcDao.java) ```java @Repository public class SkillJdbcDao { private static final String SELECT = // "SELECT s.id AS id, s.name AS name, e.id AS e_id, e.name AS e_name" + " FROM skill s" + " INNER JOIN employee_skill es ON s.id=es.skill_id" + " INNER JOIN employee e ON e.id=es.employee_id" + " WHERE s.id=:id"; private static final String UPDATE = "UPDATE skill SET name=:name WHERE id=:id"; private static final String INSERT = "INSERT INTO skill (name) VALUES (:name)"; private static final String DELETE = "DELETE FROM skill WHERE id=:id"; @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public Optional<Skill> findById(long id) { return namedParameterJdbcTemplate.queryForObject(SELECT, new MapSqlParameterSource("id", id), new SkillRowMapper()); } public int insert(Skill skill) { return namedParameterJdbcTemplate.update(INSERT, new BeanPropertySqlParameterSource(skill)); } public int update(Skill skill) { return namedParameterJdbcTemplate.update(UPDATE, new BeanPropertySqlParameterSource(skill)); } public int delete(long id) { return namedParameterJdbcTemplate.update(DELETE, new MapSqlParameterSource("id", id)); } } ``` ### Security - [CSRF](https://blog.techbridge.cc/2017/02/25/csrf-introduction/) - [CORS](https://shubo.io/what-is-cors/) - [sample](https://bitbucket.org/re102162189/springboot_jpa_mybatis_security/src/master/src/main/java/com/demo/config/SecurityConfig.java) ```java @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private Realm realm; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { String readUsername = realm.getReadUsername(); String readPassword = encoder().encode(realm.getReadPassword()); String readRole = realm.getReadRole(); String writeUsername = realm.getWriteUsername(); String writePassword = encoder().encode(realm.getWritePassword()); String writeRole = realm.getWriteRole(); UserDetails readUser = User.builder() .username(readUsername) .password(readPassword) .roles(readRole) .build(); UserDetails writeUser = User.builder() .username(writeUsername) .password(writePassword) .roles(writeRole, readRole) .build(); auth.inMemoryAuthentication() .withUser(readUser) .withUser(writeUser); } @Override protected void configure(HttpSecurity http) throws Exception { String readRole = realm.getReadRole(); String writeRole = realm.getWriteRole(); http.httpBasic().and() .authorizeRequests() .antMatchers(HttpMethod.GET, "/rest/**").hasAnyRole(readRole, writeRole) .antMatchers(HttpMethod.POST, "/rest/**").hasRole(writeRole) .antMatchers(HttpMethod.PUT, "/rest/**").hasRole(writeRole) .antMatchers(HttpMethod.DELETE, "/rest/**").hasRole(writeRole) .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .csrf().disable() .cors().disable(); } @Bean public PasswordEncoder encoder() { return new BCryptPasswordEncoder(); } } ``` ### Sample Code - [git](https://bitbucket.org/re102162189/springboot_jpa_mybatis_security/)