Spring MVC入门实践

1. 简介

spring mvc是spring框架的一个组件,该组件的作用是在url访问与后台java bean之间起到访问控制,路由映射的作用,传统的是servlet + jsp + java,spring将这个流程整合为spring mvc。
模型(Model):指java bean产生的一些信息,如模型数据。
视图(View):jsp的统称,占位符,标签元素确定展示形式,可以引用前端js文件。
控制器(Controller):spring mvc主要起到路由与方法映射的作用,被映射的类称为控制器。
有两种方式配置url与控制类的映射,XML方式与java注解方式。

2. 请求流程

image.png

xml方式配置实现url映射
1)web.xml : 在web.xml中配置/与DispatcherServlet的映射,所有http请求都经过DispatcherServlet调度,DispatcherServlet将其转发到另一个具体映射类简单url处理器映射(SimpleUrlHandlerMapping),接下来流转到第二个配置文件springmvc-servlet.xml。

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

2)springmvc-servlet.xml :在SimpleUrlHandlerMapping bean下配置具体url与Controller的映射,例如/index与indexController。

<bean id="simpleUrlHandlerMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/index">indexController</prop>
            </props>
        </property>
    </bean>
    <bean id="indexController" class="controller.IndexController"></bean> 

3)控制器:IndexController.java : Controller会将http请求头request作为参数,此阶段可以获取url参数,经过逻辑处理后,通过模型与视图对象(ModelAndView)将模型数据与视图打包,此时的视图只是逻辑视图名index.jsp,

//@Controller//注解方式
public class IndexController {
//public class IndexController implements Controller {
    //@RequestMapping("/index")//  忽略,这是注解方式映射路由,不同于xml方式
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mav = new ModelAndView("index");
        mav.addObject("message", "Hello Spring MVC4");
        return mav;
    }
}

4)后续数据流程 : 返回给DispatcherServlet,DispatcherServlet将逻辑视图与具体的视图匹配后,将数据注入到视图中,返回客户端进行渲染呈现。访问 http://127.0.0.1:8080/springmvc/index

3. 注解方式实现url映射

  • web.xml不变,与xml方式配置相同。
  • DispatcherServlet.xml文件中,将第二步代码注释,添加
<context:component-scan base-package = "controller"/>

指定组件扫描包,扫描的就是我们要用@Cotroller修饰的类。

  • 在控制类用@Controller修饰,方法用@requestMaping(“/index”)作为路由映射

4.视图定位

1)为什么需要视图定位?

假设我们在localhost/spring/下放一些jsp文件,那么用户可以直接访问url就能获取,比如说用户通过尝试一些url,造成数据泄露
解决方法:我们在WEB-INF目录下新增page文件夹,将所有的jsp文件都放置到page目录下,使用户在不改变url:http://localhost/spring/index.jsp路径,依然能访问到资源,这种方法就是通过视图定位实现的。
做法: 在DispatcherServlet.xml文件中,增加用来控制视图定位的bean,如下


<bean id= "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name = "prefix" value= "/WEB-INF/page/"></property>
        <property name = "suffix" value = ".jsp"> </property>
    </bean>

还记得上一步控制类组装视图与模型数据么?ModelAndView一开始获取到的只是逻辑视图,就是一个jsp 的name,此时并没有与模型数据组合,此时返回给DispatcherSevlet,它将逻辑视图与真正的视图进行映射数据的组合,最后返回给客户端。

5. 接受表单数据

1)表单访问页
WebContent一级目录下创建addProduct.jsp页

image.png

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
//action属性相当于跳转到的目标路由
<form  action = "addProduct" method = "post">
    <input  type = "text" name = "name" value = ""/>
    <input type = "text" name = "price"  value = ""/>
    <input type = "submit" value = "add product"/>
</form>

2)实体类 :src/pojo/下创建Product.java作为实体类

package pojo;

public class Product {
    private String name;
    private float price;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
}

3)控制类

image.png

上图为目录结构

package controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import pojo.Product;

@Controller
public class ProductController {
    @RequestMapping("/addProduct")
    public ModelAndView add(Product product) throws Exception{
        ModelAndView mov = new ModelAndView("showProduct");
        return mov;
    }
}

解释 : addProduct.jsp 提交的name和price会自动注入到参数 product里,参数product会默认被当做值加入到ModelAndView 中,相当于mav.addObject("product",product);

4)生成新视图
创建ShowProduct.jsp用来M

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
    
    name:${product.name}
    price:${product.price}odelAndView注入数据的新视图

6.客户端跳转

相当于url重定向,访问/jump会重定向到/index

    @RequestMapping("/jump")
    public ModelAndView jump() {
        ModelAndView moa = new ModelAndView("redirect:/index");
        return moa;
    }

7.用session记录回话访问次数

    @RequestMapping("/check")
    public ModelAndView getSession(HttpSession session) {
        Integer count = (Integer)session.getAttribute("count");
        if(count == null) {
            count = 0;
        }
        count++;
        session.setAttribute("count", count);
        ModelAndView moa = new ModelAndView("check");
        return moa;
    }
        
  • 在page下新建check.jsp视图
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
    
session中记录访问次数:${count}

  • 访问下图url
    image.png

8. 中文编码配置

在web.xml中添加如下

<!-- 中文乱码  -->
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
       <!--  设置编码格式 -->
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

9. 上传文件

1)配置允许访问jpg文件,在web.xml中增加

<servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.jpg</url-pattern>
    </servlet-mapping>

2)DispatcherSevlet.xml中配置上传功能需要的 java bean

<!--  上传功能支持 --> 
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
 <mvc:interceptors>

3)上传页面
WebContent下添加upload.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
    
<form  action = "uploadImage" method = "post" enctype = "multipart/form-data">
    <input type = "file" name = "image" accept = "image/*">
    <input type = "submit" value = 上传>

</form>

4)接受图片类
pojo下新建UploadedImageFile,文件目录如下

image.png

加入如下代码

package pojo;

import org.springframework.web.multipart.MultipartFile;

public class UploadedImageFile {
    MultipartFile image;

    public MultipartFile getImage() {
        return image;
    }

    public void setImage(MultipartFile image) {
        this.image = image;
    }
}

5)控制类 UploadController

//上传没问题,路径显示有问题
@Controller
public class UploadController {
    @RequestMapping("/uploadImage")
    public ModelAndView upload(HttpServletRequest request,UploadedImageFile file) 
            throws IllegalStateException, IOException{
        String name = RandomStringUtils.randomAlphanumeric(10);
        String newFileName = name + ".jpg";
        File newFile = new File(request.getServletContext().getRealPath("/image"), newFileName);
        newFile.getParentFile().mkdirs();
        file.getImage().transferTo(newFile);
        System.out.println(request.getServletContext().getRealPath("/image"));
        ModelAndView mav = new ModelAndView("showUploadedFile");
        mav.addObject("imageName", newFile);
        return mav;
    }
}

6) page下新建showUploadFile.jsp接受图片视图

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>

<image src = "${imageName}}"/>

7)访问http://127.0.0.1:8080/springmvc/upload.jsp

10. 拦截器

目的:拦截器的作用是访问某个url时,被映射的控制器会在被调用前访问指定方法,调用时访问指定方法,调用结束后访问指定方法。
1)DispatcherServlet.xml中配置添加拦截器bean

 <mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path = "/index"/> //需要拦截器的路由
        <bean class = "interceptor.IndexInterceptor"/>
    </mvc:interceptor>
 </mvc:interceptors>

2)配置拦截器类
src/interceport包下新建拦截器类

package interceptor;

public class IndexInterceptor extends HandlerInterceptorAdapter{
    public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object Handler) throws Exception{
        System.out.println("拦截处理器被调用");
        
        return true;
    }
    
    public void postHandle(HttpServletRequest request,HttpServletResponse response,
            Object handler, ModelAndView mav) throws Exception{
        mav.addObject("date",new Date());
        System.out.println("postHandle(),访问路由对应控制器后,视图访问前,添加一个时间对象到视图中,拦截处理器被调用");
    }
    
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
            Object obj, Exception exp)throws Exception{
        System.out.println("aftercompletion()拦截处理器被调用完后执行");
    }
}

3)访问配置了拦截器的地址:http://localhost:8080/springmvc/ndex

image.png

总结:直白些,spring mvc就是将所有的请求都交给了DispatcherServlet,它来调配具体url与控制类的映射,控制类调用其他java类与方法在逻辑处理后,控制类将视图与模型数据再返回给DispatcherServlet,进行视图与数据真正组合,再返回前端渲染。欢迎留言指导!!

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

推荐阅读更多精彩内容