初识 Spring MVC——练手小项目

这篇文章转载自我的个人博客

初始Spring MVC

前几天开始了我的spring学习之旅,由于之前使用过MVC模式来做项目,所以我先下手的是 Spring MVC,做个练手项目,非常简单

项目介绍:

用户输入信息 -> 后台处理 -> 输出信息

开始
  1. 创建Spring MVC 项目(创建时下载所需文件)




2.创建完的项目目录是这样的



  1. 配置Web项目结构

参考另一篇文章IDEA如何创建及配置Web项目(多图)

有变化的是: 不需要自己创建 lib 文件夹,在创建项目时已经建立,另外在 WEB-INF 建立 jsp 用于存放 .jsp 文件,其他的都没什么区别

配置完的样子(文件夹旁有箭头是因为我在做完项目才截图,具体的类以及其他文件都已在内):



  1. 配置Spring MVC的核心 —— dispatcher-servlet.xml

Spring MVC provides an annotation-based programming model where @Controller and @RestController components use annotations to express request mappings, request input, exception handling, and more. Annotated controllers have flexible method signatures and do not have to extend base classes nor implement specific interfaces.

如官方文档所说,我也使用了注解来定义控制器(Controller)和服务(Service).

首先需要添加的是

<context:component-scan base-package="controller"/>
<context:component-scan base-package="service"/>

这样我们就能通过注解来定义Controller以及Service.

然后,我们需要配置视图解析器,在具体操作时只要写出视图的名称(xxx),就可以采用URL拼接的方式,达到这种效果:/WEB-INF/jsp/xxx.jsp

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>
  1. 开始进行具体的操作

首先是基本数据类:

public class Product {
    private long id;
    private String name;
    private String price;
    private String inventory;

    public void setId(long id) {
        this.id = id;
    }
    public long getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }
    public String getName() { return name; }
    public void setPrice(String price) {
        this.price = price;
    }
    public String getPrice() { return price; }
    public void setInventory(String inventory) {
        this.inventory = inventory;
    }
    public String getInventory() { return inventory; }
}


接下来是收集用户输入所需要的表单类:

public class ProductForm {
    private String name;
    private String price;
    private String inventory;
    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public void setInventory(String inventory) {
        this.inventory = inventory;
    }

    public String getName() {
        return name;
    }
    public String getPrice() {
        return price;
    }
    public String getInventory() {
        return inventory;
    }
}


然后编写服务接口,以及它的实现类

import domain.Product;

public interface ProductService {
    Product add(Product product);
    Product get(long id);
}

ProductServiceImpl就是刚才配置的服务(Service)

import domain.Product;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

@Service
public class ProductServiceImpl implements ProductService{
    private Map<Long, Product> productMap = new HashMap<>();
    private AtomicLong atomicLong = new AtomicLong();

    @Override
    public Product add(Product product){
        long id = atomicLong.incrementAndGet();
        product.setId(id);
        productMap.put(id, product);
        return product;
    }

    @Override
    public Product get(long id){
        return productMap.get(id);
    }
}


最重要的是控制器

采用@Autowired注解的方式自动装配Service,
使用@RequestMapping注解的方式,将注解中的路径映射到控制器:

import domain.Product;
import form.ProductForm;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import service.ProductService;

@Controller
public class ProductController {
    //日志记录具体操作
    private static final Log logger = LogFactory.getLog(ProductController.class);

    @Autowired
    private  ProductService productService;

    //method = RequestMethod.POST表示只接受POST形式的请求
    @RequestMapping(value = "/product_save", method = RequestMethod.POST)
    //采用POST的方式发送请求
    public String saveProduct(ProductForm productForm, RedirectAttributes redirectAttributes){
        logger.info("saveProduct called");

        //获得用户输入
        Product product = new Product();
        product.setName(productForm.getName());
        product.setPrice(productForm.getPrice());
        product.setInventory(productForm.getInventory());

        //添加有记录的产品,并且根据ID进行重定向
        Product savedProduct = productService.add(product);
        redirectAttributes.addFlashAttribute("message", "Add product Successfully");
        return "redirect:/product_view/" + savedProduct.getId();
    }

    //根据ID,将用户输入展示在ProductView中
    @RequestMapping(value = "product_view/{id}")
    public String viewProduct(@PathVariable Long id, Model model){
        //根据ID得到信息
        Product product = productService.get(id);
        model.addAttribute("product", product);
        //ProductView.jsp
        return "ProductView";
    }
}



需要注意的是,在现在的Spring版本中,如果直接对Service进行注解,将会有产生警告:

按住Alt + Enter 修正错误,会看见提示:

官方推荐使用构造器注入

到此为止,后台工作就结束了

  1. 页面

接下来是JSP的编写:

首先是用户输入的页面 (ProductForm.jsp)

<body>
    <div>
        <form action="product_save" method="post">
            <fieldset>
                <legend>Add a product</legend>
                <p>
                    <label for="name">Product Name: </label>
                    <input type="text" id="name" name="name">
                </p>
                <p>
                    <label for="price">Price: </label>
                    <input type="text" id="price" name="price">
                </p>
                <p>
                    <label for="inventory">Inventory: </label>
                    <input type="text" id="inventory" name="inventory">
                </p>
                <p>
                    <input id="reset" type="reset" tabindex="4">
                    <input id="submit" type="submit" tabindex="5" value="Add Product">
                </p>
            </fieldset>
        </form>
    </div>
</body>

比较表单中的<form action="product_save">
和控制器中的@RequestMapping(value = "/product_save")就能够知道,通过@RequestMapping注解,任何"/product_save"开头的路径都会被映射到控制器中,并采用saveProduct()方法

然后是显示用户输入的页面 (ProductView.jsp)

<body>
    <div>
        <h3>${message}</h3>
        <h4>Details:</h4>
        Product Name: ${product.name}<br>
        Price: ${product.price}<br>
        Inventory: ${product.inventory}<br>
    </div>
</body>

${message}就是刚才在控制器中重定向页面的属性,它会在页面头部输出"Add product Successfully"

项目构建完毕

最终的目录结构是这样:

然后我们运行, 输入:

页面难看,主要是用Spring MVC做出来的就可以了

结果是这样的:

目光移至URL,填写信息提交后,页面重定向至 product_view/{id} 处,当前id = 1

到处,我们的这个练手的小项目就结束了,有什么问题都可以私信我

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,112评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,432评论 6 342
  • 1、Spring MVC请求流程 (1)初始化:(对DispatcherServlet和ContextLoderL...
    拾壹北阅读 1,920评论 0 12
  • 、最好的事情莫过于回到温暖的宿舍里,看着一群温暖的你们。虽然每天的任务很繁琐,但还好我们在一起面对。体育课上,正在...
    听过许多心里话阅读 269评论 0 0
  • 关键词:权利要求书、说明书、项目组织、写作流程、发表流程 1. 工作描述 专利申报是科学研究与技术研究成果认证和保...
    马骋阅读 1,143评论 0 7