---
# System prepended metadata

title: Spring Boot

---

# 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/)