<Spring实战>第二章:开发Web应用

在Spring Web应用中,获取和处理数据是控制器的任务,数据渲染到HTML中并在浏览器中展现则是视图的任务。

构造需要的组件
  • 定义taco配料属性的领域类。
  • 获取配料信息并将其传递至视图的SpringMVC控制器。
  • 在用户浏览器中渲染配料列表的视图模板。
请求
请求配料
HTML
Web浏览器
C
设计taco的控制器
设计视图

2.1.1 构建领域类

在Tao Cloud应用中,领域对象包括taco设计、组成这些设计的配料、顾客以及顾客所下的订单。

首先关注taco的原料。taco的配料是非常简单的对象,每种配料都有一个名称和类型,以便于对其进行可视化的分类(蛋白质、奶酪、酱汁等)。每种配料还有一个ID。
如下Ingredient类定义了我们所需的领域对象。

package tacos;

import lombok.Data;
import lombok.RequiredArgsConstructor;

@Data
@RequiredArgsConstructor
public class Ingredient {

    private final String id;
    private final String name;
    private final Type type;

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

2.1.2 创建控制器类

在SpringMVC框架中,控制器的主要职责是处理HTTP请求,要么将请求传递给视图以便于渲染HTML(浏览器展现),要么直接将数据写入响应体(RESTful)。
我们需要一个控制器完成如下功能:

  • 处理路径为"/design"的HTTP GET请求
  • 构建配料的列表
  • 处理请求,并将配料数据传递给要渲染为HTML的视图模板,发送给发起请求的Web浏览器。

import com.example.demo.Ingredient.Ingredient;
import com.example.demo.Ingredient.Ingredient.Type;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacocontroller {

    @GetMapping
    public String showDesignForm(Model model){
        List<Ingredient> ingredients = Arrays.asList(
                new Ingredient("FLTO", "Flour Tortilla", Type.WRAP),
                new Ingredient("COTO", "Corn Tortilla", Type.WRAP),
                new Ingredient("GRBF", "Ground Beef", Type.PROTEIN),
                new Ingredient("CARN", "Carnitas", Type.PROTEIN),
                new Ingredient("TMTO", "Diced Tomatoes", Type.VEGGIES),
                new Ingredient("LETC", "Diced Tomatoes", Type.VEGGIES),
                new Ingredient("CHED", "Cheddar", Type.CHEESE),
                new Ingredient("JACK", "Monterrey", Type.SAUCE),
                new Ingredient("SLSA", "Salsa", Type.SAUCE)
        );

        Type[] types = Type.values();
        for (Type type : types){
            model.addAttribute(type.toString().toLowerCase(),
                    filterByType(ingredients, type));
        }

        model.addAttribute("design", new Taco());

        return "design";
    }

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

}
  • @Slf4j 是Lombok所提供的注解
  • @Controller 这个注解会将这个类标识为控制器,并且将其作为组件扫描的候选者
  • @RequestMapping 指定该控制器所处理的请求类型
处理GET请求

@RequestMapping
@GetMapping 结合级别@RequestMapping,指明当接收到对"/design"的HTTP GET请求时,将会调用showDesignForm()来处理请求。

  • Model对象负责在控制器和展现数据的视图之间传递数据。

2.1.3设计视图

design.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Taco Cloud</title>
    <link rel="stylesheet" th:href="@{/styles.css}" />
</head>

<body>
    <h1>Design your tacol!</h1>
    <img th:src="@{/images/TacoCloud.png}"/>

    <form method="POST" th:object="${design}">
        <div class="grid">
            <div class="ingredient-group" id="wraps">
                <h3>Designate your wrap:</h3>
                <div th:each="ingredient : ${wrap}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>

            <div class="ingredient-group" id="proteins">
                <h3>Pick your protein:</h3>
                <div th:each="ingredient : ${protein}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>

            <div class="ingredient-group" id="cheese">
                <h3>Choose your cheese:</h3>
                <div th:each="ingredient : ${cheese}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>

            <div class="ingredient-group" id="veggies">
                <h3>Determine your veggies</h3>
                <div th:each="ingredient : ${veggies}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>

            <div class="ingredient-group" id="sauces">
                <h3>Select your sauce:</h3>
                <div th:each="ingredient : ${sauce}">
                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                    <span th:text="${ingredient.name}">INGREDIENT</span><br/>
                </div>
            </div>
        </div>

<!--        <div>-->
<!--            <h3>Name your taco creation:</h3>-->
<!--            <input type="text" th:field="*{name}"/>-->
<!--            <br/>-->

<!--            <button>Submit your taco</button>-->
<!--        </div>-->
    </form>
</body>
</html>

我对这本书无语了,不注释掉这个按钮,会一直报错,一直白页面。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值