Spring In Action 5 学习笔记 chapter4 Spring Security部分关键点

关键点

问题:原书中创建的User对象在H2 database中为关键词,导致h2 database报错类似【org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "drop table if exists [*]user CASCADE "; expected "identifier"; SQL statement: drop table if exists user CASCADE [42001-214]】

规避办法:不能使用user关键词作为H2 database表名,本人采用tuser作为表名及类名绕过了此bug。


问题:报错【role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER' at org.springframework.security.config.annotation】

原因及解决办法:原因上面错误已指出,不应该以ROLE_开头,解决办法:

需要将代码

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/design", "/orders")
                .hasRole("ROLE_USER")        //导致bug的代码
            .antMatchers(“/”, "/**").permitAll();
}

改为如下

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .antMatchers("/design", "/orders")
            .access("hasRole('ROLE_USER')")    //修正后的代码
        .antMatchers(“/”, "/**").access("permitAll");
}

 


问题:userRepository中的 findByUsername()总是返回空,导致DesignTacoController.java的showDesignForm方法中报错java.lang.NullPointerException: null 

解决办法

1.检查user.java中是否自动生成代码时设置username为空了,为空则去掉

2.对JPA 的指定方法进行自定义SQL查询,代码如下

public interface TuserRepository extends CrudRepository {
    @Query(value = "SELECT id, username,password FROM TUSER where username=?1",nativeQuery = true)
    Tuser findByUsername(String username);
}

问题:/design页面提交时总报错

原因及解决办法:design页面中有两个form表单,需要为每个表单添加action标记,以便每个表单提交后知道具体转向哪个url对应的controller。具体如下:



问题:登录后访问/design出现浏览器提示403 Forbidden错误

原因及解决办法:原因为CSRF机制,需要在design.html页面中增加csrf的标记  使Thymeleaf自动将token传递给spring security。

至于网上大部分解决方法写的禁用CSRF方法不可取,原书作者也一再强调了。


问题:加了Spring Security后启动程序后无法访问H2database的页面查询数据

原因及解决办法:原因为spring security也对H2 Database的页面进行了保护导致H2 database的页面无法访问。解决办法是在SecurityConfig.java的

protected void configure(HttpSecurity http)

函数中增加如下代码

http
    .antMatchers("/h2-console/**").permitAll() // 放行 H2 的请求
    .and().csrf().ignoringAntMatchers("/h2-console/**") // 禁用 H2 控制台的 CSRF 防护

问题:调试时如何查看jpa生成的sql?

解决:在application.properties中增加以下配置

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true


目录

关键点

部分源码文件

IDEA中代码文件目录

配置相关

pom.xml

application.propertites

TacocloudApplication.java

Security层

SecurityConfig.java

UserRepositoryUserDetailsService.java

RegistrationForm.java

RegistrationController.java

Model层

Ingredient.java

Order.java

Taco.java

Tuser.java

data层

IngredientRepository.java

OrderRepository.java

TacoRepository.java

TuserRepository.java

Controller层

DesignTacoController.java

HomeController.java

WebConfig.java

OrderController.java

IngredientByIdConverter.java

前端 templates

registration.html

home.html

login.html

design.html

orderForm.html

部分sql

schema.sql

data.sql

启动运行

IDEA启动程序后的日志



部分源码文件

IDEA中代码文件目录

Spring In Action 5 学习笔记 chapter4 Spring Security部分关键点_第1张图片

 Spring In Action 5 学习笔记 chapter4 Spring Security部分关键点_第2张图片

 

配置相关

pom.xml

安全相关的关键依赖是spring-boot-starter-security



    4.0.0
    com.wdh
    tacocloud
    0.0.1-SNAPSHOT
    tacocloud
    Demo project for Spring Boot

    
        1.8
        UTF-8
        UTF-8
        2.3.7.RELEASE
    

    
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
        
            org.projectlombok
            lombok
            1.18.24
            provided
        


        
            org.springframework.boot
            spring-boot-starter-validation
            
        

        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
            
        

        
        
            org.eclipse.persistence
            eclipselink
            4.0.0-M3
        

        
        
            com.h2database
            h2
            2.1.214
            runtime
        

        
        
            org.springframework.boot
            spring-boot-starter-security
            2.7.3
        



    

    
        
            
                org.springframework.boot
                spring-boot-dependencies
                ${spring-boot.version}
                pom
                import
            
        
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    1.8
                    1.8
                    UTF-8
                
            
            
                org.springframework.boot
                spring-boot-maven-plugin
                2.3.7.RELEASE
                
                    com.wdh.tacocloud.TacocloudApplication
                
                
                    
                        repackage
                        
                            repackage
                        
                    
                
            
        
    


application.propertites

# 应用名称
spring.application.name=tacocloud
# 应用服务 WEB 访问端口
server.port=8080
# THYMELEAF (ThymeleafAutoConfiguration)
# 开启模板缓存(默认值: true )  wdh:正式上线时设置为true,开发调试时设置为false便于刷新页面获取最新目标
spring.thymeleaf.cache=false
# 检查模板是否存在,然后再呈现
spring.thymeleaf.check-template=true
# 检查模板位置是否正确(默认值 :true )
spring.thymeleaf.check-template-location=true
#Content-Type 的值(默认值: text/html )
spring.thymeleaf.content-type=text/html
# 开启 MVC Thymeleaf 视图解析(默认值: true )
spring.thymeleaf.enabled=true
# 模板编码
spring.thymeleaf.encoding=UTF-8
# 要被排除在解析之外的视图名称列表,⽤逗号分隔
spring.thymeleaf.excluded-view-names=
# 要运⽤于模板之上的模板模式。另⻅ StandardTemplate-ModeHandlers( 默认值: HTML5)
spring.thymeleaf.mode=HTML5
# 在构建 URL 时添加到视图名称前的前缀(默认值: classpath:/templates/ )
spring.thymeleaf.prefix=classpath:/templates/
# 在构建 URL 时添加到视图名称后的后缀(默认值: .html )
spring.thymeleaf.suffix=.html

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

TacocloudApplication.java

package com.wdh.tacocloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TacocloudApplication {
    //注意,使用spring data Jdbc时 会自动执行data.sql和schema.sql
    //注意,使用spring data JPA时 不会自动执行data.sql,仅会执行schema.sql
    //可以打开http://localhost:8080/h2-console,根据idea 控制台打印的H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:27598f8c-e777-4993-83df-7076ce35376b'信息登录进行手动录入数据
    //参考https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.data-initialization.using-jpa

    public static void main(String[] args) {
        SpringApplication.run(TacocloudApplication.class, args);
    }
}

Security层

SecurityConfig.java

package com.wdh.tacocloud.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;

import javax.sql.DataSource;

/**
 * @author WangDH
 * @create 2022-09-02 17:10
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder encoder(){
        PasswordEncoder encoder=new StandardPasswordEncoder("53cr3t");
        return encoder;
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {

        //自定义用户身份验证
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(encoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //super.configure(http);

        //配置为对以下路径需要认证方可访问:/design /orders
        //配置为对其他路径不需要认证
        //上述认证配置的代码顺序很重要
        //配置为使用自定义登录页面
        //登出页面设置为根目录

        //.hasRole("ROLE_USER") //此代码会报错,Caused by: java.lang.IllegalArgumentException: role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER'

        http
                .authorizeRequests()
                    .antMatchers("/design","/orders")
                    .access("hasRole('ROLE_USER')")//.hasRole("USER")

                .antMatchers("/","/**")
                        .permitAll()
                .antMatchers("/h2-console/**").permitAll() // 放行 H2 的请求
                .and().csrf().ignoringAntMatchers("/h2-console/**") // 禁用 H2 控制台的 CSRF 防护
                .and().headers().frameOptions().sameOrigin() // 允许来自同一来源的 H2 控制台的请求
                .and()
                    .formLogin()
                    .loginPage("/login")
                    .defaultSuccessUrl("/design")
                .and()
                    .logout()
                        .logoutSuccessUrl("/");

    }
}

UserRepositoryUserDetailsService.java

package com.wdh.tacocloud.security;

import com.wdh.tacocloud.data.TuserRepository;
import com.wdh.tacocloud.model.Tuser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**
 * @author WangDH
 * @create 2022-09-05 17:56
 */
@Service
public class UserRepositoryUserDetailsService implements UserDetailsService {

    private TuserRepository userRepo;

    @Autowired
    public UserRepositoryUserDetailsService(TuserRepository userRepository) {
        this.userRepo=userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //return null;

        Tuser user=userRepo.findByUsername(username);
        if(user!=null){
            return user;
        }

        throw new UsernameNotFoundException("user["+username+"] not found.");
    }
}

RegistrationForm.java

package com.wdh.tacocloud.security;

import com.wdh.tacocloud.model.Tuser;
import lombok.Data;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author WangDH
 * @create 2022-09-06 9:57
 */
@Data
public class RegistrationForm {

    private String username;
    private String password;

    public Tuser toUser(PasswordEncoder passwordEncoder){
        return new Tuser(username,passwordEncoder.encode(password));
    }

}

RegistrationController.java

package com.wdh.tacocloud.security;

import com.wdh.tacocloud.data.TuserRepository;
import com.wdh.tacocloud.security.RegistrationForm;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author WangDH
 * @create 2022-09-06 9:48
 */
@Controller
@RequestMapping("/register")
public class RegistrationController {
    private TuserRepository userRepo;
    private PasswordEncoder passwordEncoder;


    public RegistrationController(TuserRepository userRepo, PasswordEncoder passwordEncoder) {
        this.userRepo = userRepo;
        this.passwordEncoder = passwordEncoder;
    }

    @GetMapping
    public String registerForm(){
        return "registration";
    }

    @PostMapping
    public String processRegistration(RegistrationForm form){
        userRepo.save(form.toUser(passwordEncoder));
        return "redirect:/login";
    }
}

Model层

Ingredient.java

package com.wdh.tacocloud.model;

import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.Id;

/**
 * @author WangDH
 * @create 2022-08-24 17:18
 */
@Data
@RequiredArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE,force = true) //因JPA需要一个无参构造函数,这里通过注解让lombok生成构造函数
@Entity //JPA需要的注解
public class Ingredient {
    @Id //jpa需要的注解,表明该字段为主键
    private final String id;

    private final String name;

    private final String mytype;

    public static enum Type{
        WRAP,PROTEIN,VEGGIES,CHEESE,SAUCE
    }
}

Order.java

package com.wdh.tacocloud.model;

import lombok.Data;

import javax.persistence.*;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.CreditCardNumber;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author WangDH
 * @create 2022-08-25 10:10
 */
@Data
@Entity
@Table(name="Taco_Order")
public class Order implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private Date placedAt;

  @NotBlank(message="Delivery name is required")
  private String deliveryName;
  
  @NotBlank(message="Street is required")
  private String deliveryStreet;
  
  @NotBlank(message="City is required")
  private String deliveryCity;
  
  @NotBlank(message="State is required")
  private String deliveryState;
  
  @NotBlank(message="Zip code is required")
  private String deliveryZip;

    @CreditCardNumber(message = "Not a valid credit card number")
    private String ccNumber; //Test VISA credit card number: 4005550000000019

    @Pattern(regexp = "^(0[1-9]|1[0-2])([\\/])([1-9][0-9])$",message = "Must be formatted MM/YY")
    private String ccExpiration;

    @Digits(integer = 3,fraction = 0,message = "Invalid CVV")
    private String ccCVV;

    @ManyToMany(targetEntity = Taco.class)
    private List tacos=new ArrayList<>();

    public void addDesign(Taco design){
      this.tacos.add(design);
    }

    @PrePersist
    void placedAt(){
      this.placedAt=new Date();
    }

    @ManyToOne
    private Tuser user;
}

Taco.java

package com.wdh.tacocloud.model;

import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;

/**
 * @author WangDH
 * @create 2022-08-25 9:12
 */
@Data
@Entity
public class Taco {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private Date createdAt;

    @NotNull
    @Size(min = 5,message = "Name must be at least 5 characters long")
    private String name;

    @ManyToMany(targetEntity = Ingredient.class)
    @Size(min = 1,message = "You must choose at least 1 ingredient.")
    private List ingredients;

    @PrePersist
    void createdAt(){
        this.createdAt=new Date();
    }
}

Tuser.java

package com.wdh.tacocloud.model;

import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Arrays;
import java.util.Collection;

/**
 * @author WangDH
 * @create 2022-09-05 17:42
 */
@Entity
@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE,force=true)
@RequiredArgsConstructor
public class Tuser implements UserDetails {
    //UserDetails是Spring内部接口,org.springframework.security.core.userdetails

    //由于user是H2Database的关键字,在IDEA中schema.sql中使用user作为表名会导致H2Database建表错误。

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private final String username;
    private final String password;


    @Override
    public Collection getAuthorities() {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

data层

IngredientRepository.java

package com.wdh.tacocloud.data;

import com.wdh.tacocloud.model.Ingredient;
import org.springframework.data.repository.CrudRepository;

/**
 * @author WangDH
 * @create 2022-08-25 14:43
 *
 * Ingredient实体的数据访问接口
 */
public interface IngredientRepository extends CrudRepository {
    //CrudRepository 已经包含增删改查的实现,这里不需要再写常规的实现代码
}

OrderRepository.java

package com.wdh.tacocloud.data;

import com.wdh.tacocloud.model.Order;
import org.springframework.data.repository.CrudRepository;
import java.util.Date;
import java.util.List;

/**
 * @author WangDH
 * @create 2022-08-25 17:20
 */
public interface OrderRepository extends CrudRepository {
    //CrudRepository 已经包含增删改查的实现,具体可看CrudRepository定义,这里不需要再写实现代码

    //以下是自定义JPA repository
    List findByDeliveryZip(String deliveryZip);

    List readOrdersByDeliveryZipAndPlacedAtBetween(
            String deliveryZip, Date startdate, Date endDate
    );
}

TacoRepository.java

package com.wdh.tacocloud.data;

import com.wdh.tacocloud.model.Taco;
import org.springframework.data.repository.CrudRepository;

/**
 * @author WangDH
 * @create 2022-08-25 17:18
 */
public interface TacoRepository extends CrudRepository {
    //CrudRepository 已经包含增删改查的实现,这里不需要再写实现代码
}

TuserRepository.java

package com.wdh.tacocloud.data;

import com.wdh.tacocloud.model.Tuser;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

/**
 * @author WangDH
 * @create 2022-09-05 17:52
 */
public interface TuserRepository extends CrudRepository {

    @Query(value = "SELECT id, username,password FROM TUSER where username=?1",nativeQuery = true)
    Tuser findByUsername(String username);
}

Controller层

DesignTacoController.java

package com.wdh.tacocloud.controller;

import com.wdh.tacocloud.data.IngredientRepository;
import com.wdh.tacocloud.data.TacoRepository;
import com.wdh.tacocloud.data.TuserRepository;
import com.wdh.tacocloud.model.Ingredient;
import com.wdh.tacocloud.model.Ingredient.Type;
import com.wdh.tacocloud.model.Order;
import com.wdh.tacocloud.model.Taco;
import com.wdh.tacocloud.model.Tuser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author WangDH
 * @create 2022-08-24 17:34
 *
 * 在控制器中注入并使用repository
 */
@Slf4j
@Controller
@RequestMapping("/design")
@SessionAttributes("order")
public class DesignTacoController {

    private final IngredientRepository ingredientRepository;
    private TacoRepository designRepo;
    private TuserRepository tuserRepo;

    @Autowired
    public DesignTacoController(
            IngredientRepository ingredientRepository,
            TacoRepository tacoRepository,
            TuserRepository tuserRepository
            ) {
        this.ingredientRepository = ingredientRepository;
        this.designRepo=tacoRepository;
        this.tuserRepo=tuserRepository;
    }

    @ModelAttribute(name="taco")
    public Taco taco(){
        return new Taco();
    }

    @ModelAttribute(name="order")
    public Order order(){
        return new Order();
    }

    @GetMapping
    public String showDesignForm(Model model, Principal principal){

        List ingredients=new ArrayList<>();
        Iterable listAll= ingredientRepository.findAll();
        listAll.forEach(i->ingredients.add(i));
        Type[] types=Ingredient.Type.values();
        for(Type type:types){
            model.addAttribute(type.toString().toLowerCase(),
                    filterByType(ingredients,type));
        }

        String strLoginUsername=principal.getName();//获取登录的用户名
        log.info("--showDesignForm--strLoginUsername="+strLoginUsername);
        Tuser tuser=tuserRepo.findByUsername(strLoginUsername);
        model.addAttribute("user",tuser);//将已登录的用户对象信息传递到前端Thymeleaf

        return "design";
    }


    private List filterByType(List ingredients,Type type){
        return ingredients.stream().filter(x->x.getMytype().equals(type.toString())).collect(Collectors.toList());
    }


    //接收提交的信息
    //注意:在desgin.html提交信息时如果提示403错误,则需要在design.html页面中增加csrf的标记
    // 
    //由于design.html有两个form,所以每个form都要指定th:action,防止出错
    @PostMapping
    public String processDesign(@Valid Taco design,
                                Errors errors,
                                @ModelAttribute Order order){
        if(errors.hasErrors())
        {
            //log.info("processDesign enter,has error.errors="+errors);
            log.info("processDesign enter,has error.errors");
            return "design";
        }

        log.info("Process design:"+design);

        Taco saved=designRepo.save(design);
        order.addDesign(saved);

        return "redirect:/orders/current";
    }
}

HomeController.java

package com.wdh.tacocloud.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author WangDH
 * @create 2022-08-24 16:25
 */
@Controller
public class HomeController {
    @GetMapping("/")
    public String home(){
        return "home";
    }
}

WebConfig.java

package com.wdh.tacocloud.controller;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author WangDH
 * @create 2022-08-25 13:48 *
 * 声明视图控制器,浏览器输入http://localhost:8082/myhome后即可直接转向myhome.html页面
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/myhome").setViewName("myhome");
        registry.addViewController("/login");//配置收到/login请求时转向相应页面
    }
}

OrderController.java

package com.wdh.tacocloud.controller;

import com.wdh.tacocloud.data.OrderRepository;
import com.wdh.tacocloud.model.Order;
import com.wdh.tacocloud.model.Tuser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
import javax.validation.Valid;
import java.security.Principal;

/**
 * @author WangDH
 * @create 2022-08-25 10:07
 */
@Slf4j
@Controller
@RequestMapping("/orders")
@SessionAttributes("order")
public class OrderController {

    private OrderRepository orderRepo;

    public OrderController(OrderRepository orderRepo){
        this.orderRepo=orderRepo;
    }

    @GetMapping("/current")  //与OrderController的url联合组成/orders/current
    public String orderForm(@AuthenticationPrincipal Tuser user,
                            @ModelAttribute Order order){

        String strLoginUsername=user.getUsername();

        order.setDeliveryName(strLoginUsername);

        return "orderForm";
    }

    @PostMapping
    public String processOrder(
            @Valid Order order,
            Errors errors,
            SessionStatus sessionStatus,
            Authentication authentication
    ){
        if(errors.hasErrors()){
            //log.info("processOrder tips,has errors="+errors);
            log.info("processOrder tips,has errors=");
            return "orderForm";
        }

        Tuser user=(Tuser)authentication.getPrincipal();//获取登录用户
        order.setUser(user);

        orderRepo.save(order);
        sessionStatus.setComplete();//清除session中的缓存

        log.info("Order submitted:"+order);

        return "redirect:/";
    }
}

IngredientByIdConverter.java

package com.wdh.tacocloud.controller;

import com.wdh.tacocloud.data.IngredientRepository;
import com.wdh.tacocloud.model.Ingredient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

/**
 * @author WangDH
 * @create 2022-08-26 11:31
 */
@Component
public class IngredientByIdConverter implements Converter {

    private IngredientRepository ingredientRepo;

    @Autowired
    public IngredientByIdConverter(IngredientRepository ingredientRepo) {
        this.ingredientRepo = ingredientRepo;
    }

    @Override
    public Ingredient convert(String id) {
        return ingredientRepo.findById(id).get();
    }
}

前端 templates

registration.html

tacocloud_jpa\src\main\resources\templates\registration.html




    
    Register - Taco Cloud


Register




home.html




    
    Taco-Cloud.This is my spring boot home page


Taco-Cloud.hello world! spring boot.Welcome to my site.

login.html




    
    Login


Login

unable to login.check id and pwd.

New Here? click here to register.



design.html




    
    Taco cloud
    


Design your taco,4

Ingredient Errors.

Designate your wrap:

INGREDIENT

Designate your proteins:

INGREDIENT

Designate your cheeses:

INGREDIENT

Designate your veggies:

INGREDIENT

Designate your sauces:

INGREDIENT

Name your taco creation:


XXX Name Errors.


The login username=


orderForm.html




    
    Taco Cloud-Order Form
    


    

Order your taco creations:

Design another taco
Please correct the problems below and resubmit.

Deliver my taco masterpieces to ...

Name Error
Street Error
City Error
State Error
Zip Error

Here is how i will pay ...

CC Num Error
Expiration Errors.
CVV Errors.

部分sql

schema.sql

路径:\tacocloud_jpa\src\main\resources\schema.sql

在程序启动时会自动创建到H2 database中

create table if not exists Ingredient (
  id varchar(4) not null PRIMARY KEY,
  name varchar(25) not null,
  mytype varchar(10) not null
);

create table if not exists Taco (
  id identity,
  name varchar(50) not null,
  createdAt timestamp not null
);

create table if not exists Taco_Ingredients (
  taco bigint not null,
  ingredient varchar(4) not null
);

alter table Taco_Ingredients
    add foreign key (taco) references Taco(id);
alter table Taco_Ingredients
    add foreign key (ingredient) references Ingredient(id);

create table if not exists Taco_Order (
	id identity,
	deliveryName varchar(50) not null,
	deliveryStreet varchar(50) not null,
	deliveryCity varchar(50) not null,
	deliveryState varchar(2) not null,
	deliveryZip varchar(10) not null,
	ccNumber varchar(16) not null,
	ccExpiration varchar(5) not null,
	ccCVV varchar(3) not null,
    placedAt timestamp not null
);

create table if not exists Taco_Order_Tacos (
	tacoOrder bigint not null,
	taco bigint not null
);

alter table Taco_Order_Tacos
    add foreign key (tacoOrder) references Taco_Order(id);
alter table Taco_Order_Tacos
    add foreign key (taco) references Taco(id);

data.sql

路径:tacocloud_jpa\src\main\resources\data.sql

注意,当使用jpa时该文件不会自动执行插入数据操作,需要登录http://localhost:8080/h2-console页面后手动拷贝此sql执行数据新增,以便design页面加载后有数据。

delete from Taco_Order_Tacos;
delete from Taco_Ingredients;
delete from Taco;
delete from Taco_Order;

delete from Ingredient;
insert into Ingredient (id, name, mytype)
                values ('FLTO', 'Flour Tortilla11', 'WRAP');
insert into Ingredient (id, name, mytype)
                values ('COTO', 'Corn Tortilla22', 'WRAP');
insert into Ingredient (id, name, mytype)
                values ('GRBF', 'Ground Beef33', 'PROTEIN');
insert into Ingredient (id, name, mytype)
                values ('CARN', 'Carnitas', 'PROTEIN');
insert into Ingredient (id, name, mytype)
                values ('TMTO', 'Diced Tomatoes', 'VEGGIES');
insert into Ingredient (id, name, mytype)
                values ('LETC', 'Lettuce', 'VEGGIES');
insert into Ingredient (id, name, mytype)
                values ('CHED', 'Cheddar', 'CHEESE');
insert into Ingredient (id, name, mytype)
                values ('JACK', 'Monterrey Jack', 'CHEESE');
insert into Ingredient (id, name, mytype)
                values ('SLSA', 'Salsa', 'SAUCE');
insert into Ingredient (id, name, mytype)
                values ('SRCR', 'Sour Cream', 'SAUCE');

启动运行

查看IDEA中提示【Tomcat started on port(s): 8080 (http) with context path ''】【Completed initialization in 153 ms】类似字样后就可打开浏览器访问此应用了。

未登录时:浏览器直接输入内页地址【http://localhost:8080/design】会被强制跳转到登录也【http://localhost:8080/login】

注册页:【http://localhost:8080/register】

登录页:【http://localhost:8080/login】

登录后默认跳转至:【http://localhost:8080/design】

内页(design.html)输入相关信息后提交会跳转至【http://localhost:8080/orders/current】

登出后会跳转至【http://localhost:8080/】

IDEA启动程序后的日志

"C:\Program Files\Java\jdk1.8.0_111\bin\java.exe" -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-javaagent:D:\JavaDevEnv\JetBrains\IntelliJ IDEA 2018.3.6\lib\idea_rt.jar=11189:D:\JavaDevEnv\JetBrains\IntelliJ IDEA 2018.3.6\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_111\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\rt.jar;D:\JavaWorkspace\IdeaProjects\SpringInAction\tacocloud_jpa\target\classes;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-thymeleaf\2.3.7.RELEASE\spring-boot-starter-thymeleaf-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter\2.3.7.RELEASE\spring-boot-starter-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-logging\2.3.7.RELEASE\spring-boot-starter-logging-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\JavaDevEnv\maven_repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\JavaDevEnv\maven_repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;D:\JavaDevEnv\maven_repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;D:\JavaDevEnv\maven_repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;D:\JavaDevEnv\maven_repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\JavaDevEnv\maven_repository\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;D:\JavaDevEnv\maven_repository\org\thymeleaf\thymeleaf-spring5\3.0.11.RELEASE\thymeleaf-spring5-3.0.11.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\thymeleaf\thymeleaf\3.0.11.RELEASE\thymeleaf-3.0.11.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\attoparser\attoparser\2.0.5.RELEASE\attoparser-2.0.5.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\unbescape\unbescape\1.1.6.RELEASE\unbescape-1.1.6.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;D:\JavaDevEnv\maven_repository\org\thymeleaf\extras\thymeleaf-extras-java8time\3.0.4.RELEASE\thymeleaf-extras-java8time-3.0.4.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-web\2.3.7.RELEASE\spring-boot-starter-web-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-json\2.3.7.RELEASE\spring-boot-starter-json-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\com\fasterxml\jackson\core\jackson-databind\2.11.3\jackson-databind-2.11.3.jar;D:\JavaDevEnv\maven_repository\com\fasterxml\jackson\core\jackson-annotations\2.11.3\jackson-annotations-2.11.3.jar;D:\JavaDevEnv\maven_repository\com\fasterxml\jackson\core\jackson-core\2.11.3\jackson-core-2.11.3.jar;D:\JavaDevEnv\maven_repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.3\jackson-datatype-jdk8-2.11.3.jar;D:\JavaDevEnv\maven_repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.3\jackson-datatype-jsr310-2.11.3.jar;D:\JavaDevEnv\maven_repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.3\jackson-module-parameter-names-2.11.3.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-tomcat\2.3.7.RELEASE\spring-boot-starter-tomcat-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.41\tomcat-embed-core-9.0.41.jar;D:\JavaDevEnv\maven_repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.41\tomcat-embed-websocket-9.0.41.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-web\5.2.12.RELEASE\spring-web-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-beans\5.2.12.RELEASE\spring-beans-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-webmvc\5.2.12.RELEASE\spring-webmvc-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-context\5.2.12.RELEASE\spring-context-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-expression\5.2.12.RELEASE\spring-expression-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-devtools\2.3.7.RELEASE\spring-boot-devtools-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot\2.3.7.RELEASE\spring-boot-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-autoconfigure\2.3.7.RELEASE\spring-boot-autoconfigure-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\projectlombok\lombok\1.18.24\lombok-1.18.24.jar;D:\JavaDevEnv\maven_repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;D:\JavaDevEnv\maven_repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;D:\JavaDevEnv\maven_repository\net\bytebuddy\byte-buddy\1.10.18\byte-buddy-1.10.18.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-core\5.2.12.RELEASE\spring-core-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-jcl\5.2.12.RELEASE\spring-jcl-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-validation\2.3.7.RELEASE\spring-boot-starter-validation-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;D:\JavaDevEnv\maven_repository\org\hibernate\validator\hibernate-validator\6.1.6.Final\hibernate-validator-6.1.6.Final.jar;D:\JavaDevEnv\maven_repository\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar;D:\JavaDevEnv\maven_repository\org\jboss\logging\jboss-logging\3.4.1.Final\jboss-logging-3.4.1.Final.jar;D:\JavaDevEnv\maven_repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-data-jpa\2.3.7.RELEASE\spring-boot-starter-data-jpa-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-aop\2.3.7.RELEASE\spring-boot-starter-aop-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\aspectj\aspectjweaver\1.9.6\aspectjweaver-1.9.6.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-jdbc\2.3.7.RELEASE\spring-boot-starter-jdbc-2.3.7.RELEASE.jar;D:\JavaDevEnv\maven_repository\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-jdbc\5.2.12.RELEASE\spring-jdbc-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\jakarta\transaction\jakarta.transaction-api\1.3.3\jakarta.transaction-api-1.3.3.jar;D:\JavaDevEnv\maven_repository\jakarta\persistence\jakarta.persistence-api\2.2.3\jakarta.persistence-api-2.2.3.jar;D:\JavaDevEnv\maven_repository\org\hibernate\hibernate-core\5.4.25.Final\hibernate-core-5.4.25.Final.jar;D:\JavaDevEnv\maven_repository\org\javassist\javassist\3.27.0-GA\javassist-3.27.0-GA.jar;D:\JavaDevEnv\maven_repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;D:\JavaDevEnv\maven_repository\org\jboss\jandex\2.1.3.Final\jandex-2.1.3.Final.jar;D:\JavaDevEnv\maven_repository\org\dom4j\dom4j\2.1.3\dom4j-2.1.3.jar;D:\JavaDevEnv\maven_repository\org\hibernate\common\hibernate-commons-annotations\5.1.2.Final\hibernate-commons-annotations-5.1.2.Final.jar;D:\JavaDevEnv\maven_repository\org\glassfish\jaxb\jaxb-runtime\2.3.3\jaxb-runtime-2.3.3.jar;D:\JavaDevEnv\maven_repository\org\glassfish\jaxb\txw2\2.3.3\txw2-2.3.3.jar;D:\JavaDevEnv\maven_repository\com\sun\istack\istack-commons-runtime\3.0.11\istack-commons-runtime-3.0.11.jar;D:\JavaDevEnv\maven_repository\com\sun\activation\jakarta.activation\1.2.2\jakarta.activation-1.2.2.jar;D:\JavaDevEnv\maven_repository\org\springframework\data\spring-data-jpa\2.3.6.RELEASE\spring-data-jpa-2.3.6.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\data\spring-data-commons\2.3.6.RELEASE\spring-data-commons-2.3.6.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-orm\5.2.12.RELEASE\spring-orm-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-tx\5.2.12.RELEASE\spring-tx-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-aspects\5.2.12.RELEASE\spring-aspects-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\eclipse\persistence\eclipselink\4.0.0-M3\eclipselink-4.0.0-M3.jar;D:\JavaDevEnv\maven_repository\com\sun\xml\bind\jaxb-xjc\4.0.0-M3\jaxb-xjc-4.0.0-M3.jar;D:\JavaDevEnv\maven_repository\com\sun\xml\bind\jaxb-core\4.0.0-M3\jaxb-core-4.0.0-M3.jar;D:\JavaDevEnv\maven_repository\org\eclipse\angus\angus-activation\1.0.0\angus-activation-1.0.0.jar;D:\JavaDevEnv\maven_repository\com\h2database\h2\2.1.214\h2-2.1.214.jar;D:\JavaDevEnv\maven_repository\org\springframework\boot\spring-boot-starter-security\2.7.3\spring-boot-starter-security-2.7.3.jar;D:\JavaDevEnv\maven_repository\org\springframework\spring-aop\5.2.12.RELEASE\spring-aop-5.2.12.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\security\spring-security-config\5.3.6.RELEASE\spring-security-config-5.3.6.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\security\spring-security-core\5.3.6.RELEASE\spring-security-core-5.3.6.RELEASE.jar;D:\JavaDevEnv\maven_repository\org\springframework\security\spring-security-web\5.3.6.RELEASE\spring-security-web-5.3.6.RELEASE.jar" com.wdh.tacocloud.TacocloudApplication

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.7.RELEASE)

2022-09-07 13:57:02.885  INFO 1108 --- [  restartedMain] com.wdh.tacocloud.TacocloudApplication   : Starting TacocloudApplication on 14JPYI7CBESDNFK with PID 1108 (D:\JavaWorkspace\IdeaProjects\SpringInAction\tacocloud_jpa\target\classes started by Administrator in D:\JavaWorkspace\IdeaProjects\SpringInAction\tacocloud_jpa)
2022-09-07 13:57:02.885  INFO 1108 --- [  restartedMain] com.wdh.tacocloud.TacocloudApplication   : No active profile set, falling back to default profiles: default
2022-09-07 13:57:02.948  INFO 1108 --- [  restartedMain] o.s.b.devtools.restart.ChangeableUrls    : The Class-Path manifest attribute in D:\JavaDevEnv\maven_repository\com\sun\xml\bind\jaxb-xjc\4.0.0-M3\jaxb-xjc-4.0.0-M3.jar referenced one or more files that do not exist: file:/D:/JavaDevEnv/maven_repository/com/sun/xml/bind/jaxb-xjc/4.0.0-M3/jaxb-core.jar,file:/D:/JavaDevEnv/maven_repository/com/sun/xml/bind/jaxb-xjc/4.0.0-M3/jaxb-impl.jar
2022-09-07 13:57:02.948  INFO 1108 --- [  restartedMain] o.s.b.devtools.restart.ChangeableUrls    : The Class-Path manifest attribute in D:\JavaDevEnv\maven_repository\com\sun\xml\bind\jaxb-core\4.0.0-M3\jaxb-core-4.0.0-M3.jar referenced one or more files that do not exist: file:/D:/JavaDevEnv/maven_repository/com/sun/xml/bind/jaxb-core/4.0.0-M3/jakarta.activation-api.jar,file:/D:/JavaDevEnv/maven_repository/com/sun/xml/bind/jaxb-core/4.0.0-M3/jakarta.xml.bind-api.jar
2022-09-07 13:57:02.948  INFO 1108 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2022-09-07 13:57:02.948  INFO 1108 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2022-09-07 13:57:03.827  INFO 1108 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2022-09-07 13:57:03.890  INFO 1108 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 45ms. Found 4 JPA repository interfaces.
2022-09-07 13:57:04.404  INFO 1108 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-09-07 13:57:04.404  INFO 1108 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-09-07 13:57:04.404  INFO 1108 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.41]
2022-09-07 13:57:04.482  INFO 1108 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-09-07 13:57:04.482  INFO 1108 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1534 ms
2022-09-07 13:57:04.529  INFO 1108 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-09-07 13:57:04.623  INFO 1108 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2022-09-07 13:57:04.732  INFO 1108 --- [  restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration    : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:c573c85b-45f1-4306-b148-51094d4aa9ce'
2022-09-07 13:57:04.779  INFO 1108 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2022-09-07 13:57:04.841  INFO 1108 --- [  restartedMain] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-09-07 13:57:04.872  INFO 1108 --- [  restartedMain] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.25.Final
2022-09-07 13:57:04.966  INFO 1108 --- [  restartedMain] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2022-09-07 13:57:05.060  INFO 1108 --- [  restartedMain] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: 
    
    drop table if exists ingredient CASCADE 
Hibernate: 
    
    drop table if exists taco CASCADE 
Hibernate: 
    
    drop table if exists taco_ingredients CASCADE 
Hibernate: 
    
    drop table if exists taco_order CASCADE 
Hibernate: 
    
    drop table if exists taco_order_tacos CASCADE 
Hibernate: 
    
    drop table if exists tuser CASCADE 
Hibernate: 
    
    drop sequence if exists hibernate_sequence
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: 
    
    create table ingredient (
       id varchar(255) not null,
        mytype varchar(255),
        name varchar(255),
        primary key (id)
    )
Hibernate: 
    
    create table taco (
       id bigint not null,
        created_at timestamp,
        name varchar(255) not null,
        primary key (id)
    )
Hibernate: 
    
    create table taco_ingredients (
       taco_id bigint not null,
        ingredients_id varchar(255) not null
    )
Hibernate: 
    
    create table taco_order (
       id bigint not null,
        cccvv varchar(255),
        cc_expiration varchar(255),
        cc_number varchar(255),
        delivery_city varchar(255),
        delivery_name varchar(255),
        delivery_state varchar(255),
        delivery_street varchar(255),
        delivery_zip varchar(255),
        placed_at timestamp,
        user_id bigint,
        primary key (id)
    )
Hibernate: 
    
    create table taco_order_tacos (
       order_id bigint not null,
        tacos_id bigint not null
    )
Hibernate: 
    
    create table tuser (
       id bigint not null,
        password varchar(255),
        username varchar(255),
        primary key (id)
    )
Hibernate: 
    
    alter table taco_ingredients 
       add constraint FK7y679y77n5e75s3ss1v7ff14j 
       foreign key (ingredients_id) 
       references ingredient
Hibernate: 
    
    alter table taco_ingredients 
       add constraint FK27rycuh3mjaepnba0j6m8xl4q 
       foreign key (taco_id) 
       references taco
Hibernate: 
    
    alter table taco_order 
       add constraint FK7aps3q40owoysjeb69gx5puq5 
       foreign key (user_id) 
       references tuser
Hibernate: 
    
    alter table taco_order_tacos 
       add constraint FKfwvqtnjfview9e5f7bfqtd1ns 
       foreign key (tacos_id) 
       references taco
Hibernate: 
    
    alter table taco_order_tacos 
       add constraint FKcxwvdkndaqmrxcen10vkneexo 
       foreign key (order_id) 
       references taco_order
2022-09-07 13:57:05.652  INFO 1108 --- [  restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2022-09-07 13:57:05.668  INFO 1108 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2022-09-07 13:57:05.964  WARN 1108 --- [  restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-09-07 13:57:06.105  INFO 1108 --- [  restartedMain] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@33344fa7, org.springframework.security.web.context.SecurityContextPersistenceFilter@1afb6c99, org.springframework.security.web.header.HeaderWriterFilter@2d4fb172, org.springframework.security.web.csrf.CsrfFilter@4e9e193a, org.springframework.security.web.authentication.logout.LogoutFilter@53da7c63, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@275c4b54, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@45640a2a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@512f5b2f, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@9913c7b, org.springframework.security.web.session.SessionManagementFilter@65dbc852, org.springframework.security.web.access.ExceptionTranslationFilter@1d2c08a7, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@63f7a4d6]
2022-09-07 13:57:06.214  INFO 1108 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2022-09-07 13:57:06.323  WARN 1108 --- [  restartedMain] org.thymeleaf.templatemode.TemplateMode  : [THYMELEAF][restartedMain] Template Mode 'HTML5' is deprecated. Using Template Mode 'HTML' instead.
2022-09-07 13:57:06.401  INFO 1108 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-09-07 13:57:06.417  INFO 1108 --- [  restartedMain] com.wdh.tacocloud.TacocloudApplication   : Started TacocloudApplication in 3.836 seconds (JVM running for 4.49)
2022-09-07 13:57:44.806  INFO 1108 --- [nio-8080-exec-7] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-09-07 13:57:44.807  INFO 1108 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-09-07 13:57:44.960  INFO 1108 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet        : Completed initialization in 153 ms
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        tuser
        (password, username, id) 
    values
        (?, ?, ?)
Hibernate: 
    SELECT
        id,
        username,
        password 
    FROM
        TUSER 
    where
        username=?
Hibernate: 
    select
        ingredient0_.id as id1_0_,
        ingredient0_.mytype as mytype2_0_,
        ingredient0_.name as name3_0_ 
    from
        ingredient ingredient0_
2022-09-07 13:58:25.797  INFO 1108 --- [nio-8080-exec-8] c.w.t.controller.DesignTacoController    : --showDesignForm--strLoginUsername=suser1
Hibernate: 
    SELECT
        id,
        username,
        password 
    FROM
        TUSER 
    where
        username=?
Hibernate: 
    select
        ingredient0_.id as id1_0_0_,
        ingredient0_.mytype as mytype2_0_0_,
        ingredient0_.name as name3_0_0_ 
    from
        ingredient ingredient0_ 
    where
        ingredient0_.id=?
2022-09-07 13:58:31.962  INFO 1108 --- [nio-8080-exec-4] c.w.t.controller.DesignTacoController    : Process design:Taco(id=null, createdAt=null, name=wdhtoco, ingredients=[Ingredient(id=FLTO, name=Flour Tortilla11, mytype=WRAP)])
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        taco
        (created_at, name, id) 
    values
        (?, ?, ?)
Hibernate: 
    insert 
    into
        taco_ingredients
        (taco_id, ingredients_id) 
    values
        (?, ?)
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        taco_order
        (cccvv, cc_expiration, cc_number, delivery_city, delivery_name, delivery_state, delivery_street, delivery_zip, placed_at, user_id, id) 
    values
        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        taco_order_tacos
        (order_id, tacos_id) 
    values
        (?, ?)
2022-09-07 13:59:04.815  INFO 1108 --- [io-8080-exec-10] c.w.t.controller.OrderController         : Order submitted:Order(id=3, placedAt=Wed Sep 07 13:59:04 CST 2022, deliveryName=suser1, deliveryStreet=2, deliveryCity=3, deliveryState=4, deliveryZip=5, ccNumber=4005550000000019, ccExpiration=12/22, ccCVV=123, tacos=[Taco(id=2, createdAt=Wed Sep 07 13:58:31 CST 2022, name=wdhtoco, ingredients=[Ingredient(id=FLTO, name=Flour Tortilla11, mytype=WRAP)])], user=Tuser(id=1, username=suser1, password=0cfb338800503e5f20618ff77aa69868763399a38a3b79e168ff8529e1367ec5d51cf8e638134a99))

你可能感兴趣的:(java,spring,boot,intellij-idea,spring,java)