Springboot
Unit1
-
Application.java
-
@SpringBootApplication includes
- @SpringBootConfiguration
special @Configuration
- @EnableAutoConfiguration
enable spring boot auto config
- @ComponentScan
enable component scan
scan something such as @Component @Controller @Service
- @SpringBootConfiguration
-
main() Application.run(Application.class, args);
-
-
ApplicationTest.java
- test context
- @RunWith(SpringRunner,.class)
- @SpringBootTest
- regard as Application.java
-
Spring Application
- Spring MVC process web request with controller (MVC -> Model View Controlller)
@Controller
@GetMappeing processes HTTP GET request
use Thymeleaf templates path: /src/main/resoureces/templates - define view
static resources path: /src/main/resources/static/
- test controller
MockMvc
- Spring MVC process web request with controller (MVC -> Model View Controlller)
Unit2
-
lombok dynamically generate getter, setter and so on
@Data @RequiredArgsConstructor
@Slf4j automatic generate SLF4J logger -
@RequestMapping general processing request uesd for class @RequestMapping(method=RequestMethod.GET) @GetMapping @PostMapping @PutMapping @DeleteMapping @PatchMapping used for method
-
design view include JavaServer Pages\Thymeleaf\FreeMarker\Mustache\template based on Groovy
- Thymeleaf
@{} is relative path /src/main/resource/static
image<img th:src="@{}"/>
<p th:text="${name}"></p>
name is a attribute of Model
<div th:each="element : ${test}><div>
repeat redering
<input name="output" type="test" th:value"${}>
input data<form method="POST" th:object="${design"}>
form data
- Thymeleaf
-
process form submit
- when submit form, data will be binded with object.
redirect:
redirect prefix<form>
action attribute used to specify URL
e.g.<form th:action="@{test}">
-
check form input
- use Bean Validation API\Hibernate Validattor
- @NOTNull not null
- @NOTNull not null and not 0
- @Size(min=
int
, message=String
) control size - @CreditCardNumber check credit card number from hibernate validattor
- @Pattern regular expression
- @Valid the object need check after blind before use the method
e.g.
@PostMapping public String processOrder(@Valid Order order, Errors errors) { if (errors.hasErrors()) { return "orderForm"; } log.info("Order submitted: " + order); return "redirect:/"; }
-
show check error
<label for="name">Name: </label> <input type="text" th:field="*{name}"/> <!-- end::allButValidation[] --> <span class="validationError" th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</span>
-
view controller
package tacos.web; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("home"); } }
-
cache templates
- application.properties
spring.thymeleaf.cache=false
disable cache
- application.properties
Unit3
-
JDBC
-
JdbcTemplate
@Repository
@Autowired@Override public Ingredient findOne(String id) { return jdbc.queryForObject( "select id, name, type from Ingredient where id=?", new RowMapper<Ingredient>() { public Ingredient mapRow(ResultSet rs, int rowNum) throws SQLException { return new Ingredient( rs.getString("id"), rs.getString("name"), Ingredient.Type.valueOf(rs.getString("type"))); }; }, id); }
-
insert
-
insert data use Jdbc.update()
@Override public Ingredient save(Ingredient ingredient) { jdbc.update( "insert into Ingredient (id, name, type) values (?, ?, ?)", ingredient.getId(), ingredient.getName(), ingredient.getType().toString()); return ingredient; }
-
complex insert update() recevie a PrepareStatementCreator and a KeyHolder. The key Holder will provide the key content.
@Override public Taco save(Taco taco) { long tacoId = saveTacoInfo(taco); taco.setId(tacoId); for (Ingredient ingredient : taco.getIngredients()) { saveIngredientToTaco(ingredient, tacoId); } return taco; } private long saveTacoInfo(Taco taco) { taco.setCreatedAt(new Date()); PreparedStatementCreator psc = new PreparedStatementCreatorFactory( "insert into Taco (name, createdAt) values (?, ?)", Types.VARCHAR, Types.TIMESTAMP ).newPreparedStatementCreator( Arrays.asList( taco.getName(), new Timestamp(taco.getCreatedAt().getTime()))); KeyHolder keyHolder = new GeneratedKeyHolder(); jdbc.update(psc, keyHolder); return keyHolder.getKey().longValue(); } private void saveIngredientToTaco( Ingredient ingredient, long tacoId) { jdbc.update( "insert into Taco_Ingredients (taco, ingredient) " + "values (?, ?)", tacoId, ingredient.getId()); }
-
@SessionAttributes("
parameter
") add session attribute @SeesionAttribute take out SessionStatus.setComplete() clear @ModelAttribute add and take out -
SimpleJdbcInsert
@Override public Order save(Order order) { order.setPlacedAt(new Date()); long orderId = saveOrderDetails(order); order.setId(orderId); List<Taco> tacos = order.getTacos(); for (Taco taco : tacos) { saveTacoToOrder(taco, orderId); } return order; } private long saveOrderDetails(Order order) { @SuppressWarnings("unchecked") Map<String, Object> values = objectMapper.convertValue(order, Map.class); values.put("placedAt", order.getPlacedAt()); //Not compatible long orderId = orderInserter .executeAndReturnKey(values) .longValue(); return orderId; } private void saveTacoToOrder(Taco taco, long orderId) { Map<String, Object> values = new HashMap<>(); values.put("tacoOrder", orderId); values.put("taco", taco.getId()); orderTacoInserter.execute(values); }
-
-
-
JPA Java Persistence API
- @Entity identify entity
@Id primary key
@GeneratedValue
@ManyToMany declare a new table @Table(name=String
)
@PrePersist before persistence execute the method - repository
extends CrudREpository<ObjectType
,IdType
> - customize JPA repository
through method name define a operation
List<Order> readOrderByDeliveryZipAndPlacedAtBetween(String deliveryZip, Date startDate, date endDate);
read``Order``By``DeliveryZip``And``PlacedAt``Between
@Query("
sql string
") - @Entity identify entity
Unit4
-
configure Spring Security
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { }
user information storage
-
based on memory
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("buzz") .password("infinity") .authorities("ROLE_USER") .and() .withUser("woody") .password("bullseye") .authorities("ROLE_USER"); }
-
based on JDBC
spring security provide database define
table users: username password enabled
table authority: username authority
table groups: id name
table group_members: group_id name
table group_authorities: group_id authoritycustomize user information query
@Autowired dataSource dataSource; protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .jdbcAuthentication() .dataSource(dataSource) .usersByUsernameQuery( "select username, password, enabled from Users " + "where username=?") .authoritiesByUsernameQuery( "select username, authority from UserAuthorities " + "where username=?"); } ``` Query basic agreement: the only parameter is **username** transcode: .passwordEncoder(`Stirng`)
-
LDAP as back end Lightweight Directory Access Protocol
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .ldapAuthentication() .userSearchFilter("(uid={0})") .groupSearchFilter("member={0}"); }
-
customize user authenticate Spring Data repository
-
define a entity User implements UserDetails
@Override public Collection<? extends GrantedAuthority> getAuthorities() { return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); }
every user has the authority ROLE_USER
-
define a repository interface extends CrudRepository<User, Long> define a method findByUsername(
String
) -
create user details service
@Service public class UserRepositoryUserDetailsService implements UserDetailsService { private UserRepository userRepo; @Autowired public UserRepositoryUserDetailsService(UserRepository userRepo) { this.userRepo = userRepo; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepo.findByUsername(username); if (user != null) { return user; } throw new UsernameNotFoundException( "User '" + username + "' not found"); } }
add config
@Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder encoder() { return new StandardPasswordEncoder("53cr3t"); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(userDetailsService) .passwordEncoder(encoder()); }
-
register
-
-
-
protect Web request
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/design", "/orders") .access("hasRole('ROLE_USER')") .antMatchers("/", "/**").access("permitAll") //access() + SpEL .and() .formLogin() .loginPage("/login") .and() .logout() .logoutSuccessUrl("/") .and() .csrf() .ignoringAntMatchers("/h2-console/**") .and() .headers() .frameOptions() .sameOrigin() ; }
know who the user is
-
add parameter Principal
use principal.getName() to get userName -
add parameter Authentication
use authentication.getPrincipal() to get a Object and then use coercion to get User -
add parameter @AuthenticationPrincipal User user
-
can be used in anywhere
Authentication authentcation = SecuurityContextHolder.getContext().getAuthentication(); User user = (User) authentication.getPrincipal();
-
Unit5
-
configure
application.properties / application.yml
-
Servlet port
server: port:9090
-
datasource
spring: datasource: url: jdbc:mysql://localhost/table username: root password: root schema: - name-schema.sql data: - name.sql
-
log
logging: file: path level: root: WARN org: springframework: scurity: DEBUG
-
create specific attribute
test: example: ${spring.application.name}
-
customize configuration attribute
@ConfiguraionProperties(prefix=String
)configure meta data
src/main/resources/META-INF
{ "properties": [ { "name":"taco.orders.page-size", "type":"java.lang.String", "descrption":"lalala" } ] }
-
profile
application-{profile name}.yml
–spring.profiles.active={profile name}
@Profile({profile name}) before method of class definition
-