SpringMVC初识

MVC的核心思想就是业务数据抽取同业务数据呈现相分离

view:是视图层,为用户提供UI,重点关注数据的呈现。
model:模型层,是业务数据的信息表示,关注支撑业务的信息构成,通常是多个业务实体的组合。
controller:是控制层,通过调用业务逻辑产生合适的数据(model),同时将数据传递给视图层用于呈现。

  1. MVC是一种架构模式,是程序分成,分工合作,既相互独立,有协同工作。
  2. MVC是一种思考方式,模型层思考为用户展现什么,在视图层思考如何布局,在控制层思考调用那些业务逻辑。

这里写图片描述
控制器:负责业务数据的抽取
视图模板:负责页面呈现
前端控制器:负责分发调度

用户通过http协议发送请求到前端控制器,前端控制器根据用户的请求到controller处理数据,返回处理结果到前端控制器,前端控制器将数据分发给业务视图,由业务视图呈现最终的用户页面,返回给前端控制器,在呈现给用户。

SpringMVC的基本概念

这里写图片描述

这里写图片描述

名称作用
DispatcherServlet前端控制器,分发到合适的controller来生产我们需要的model model通过DispatcherServlet来传递给我们的View
Controller就是MVC中的C,调用业务逻辑生成model的地方
HandlerAdapter是DispatcherServlet中得一个类,是Controller的一个表现形式 DispatcherServlet实际调用的Controller其实是以handler(Handler是DispatcherServlet调用Controller的中间过渡对象)形式出现的HandlerAdapter(适配器模式),就是把各种不同的Handler适配成DispatcherServlet可以使用的Handler
HandlerInterceptor拦截器,该接口提供after、postHandle、preHandle三个方法,调用controller前后使用
HandlerMapping前端控制器与controller映射关系的类
HandlerExecutionChainpreHandle->Controller method->postHandle->afterCompletion的执行链
ModelAndViewmodel的具体表现,有model和map两种处理方式
viewResolver视图解析器,决定需要用哪个视图来进行视图的呈现
view响应页面的呈现

SpringMVC的动态概念
1.用户发送请求request
2.DispatcherServlet拦截request 就需要找到一个Controller 如何找?
3.DispatcherServlet就把功能代理给了HandlerMapping
4.HandlerMapping根据配置 通过annotation找到Controller也找到了HandlerInterceptor
形成了一个HandlerExcutionChain 作为一个Handler或者是HandlerAdapter返回给DispatcherServlet
5.DispatcherServlet调用这个Handler或者是HandlerAdapter(找到Controller,Controller目的:生成ModelAndView) 生成ModelAndView 并返回给DispatcherServlet
6.DispatcherServlet调用ViewResolver(视图解析器)方法 返回View对象给DispatcherServlet
7.DispatcherServlet调用ModelAndView作为模型数据传递给我们的View完成了呈现 返回给DispatcherServlet
8.DispatcherServlet再把视图响应给用户

注意事项
1.DispatcherServlet,HandlerMaping 只需要配置
2.Handler/HandlerAdapter忽略掉
3.Controller需要自己写
4.HandlerInterceptor(Controller调用前后干点啥)是一个接口,需要就写不需要就不用实现
5.ModelAndView:只是一个类,也可以使用Map把需要的放进去就好了
6.ViewResolver和HandlerMapping差不多只需要知道使用那种类型就可以了
7.view:不需要管具体的呈现。只需要管是哪一个就好了

eg:一个简单的登录页面,服务器使用jetty

maven配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.lmr.springmvc</groupId>
    <artifactId>SpringMVC</artifactId>
    <packaging>jar</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringMVC</name>
    <url>http://maven.apache.org</url>

    <properties>
        <commons-lang.version>2.6</commons-lang.version>
        <slf4j.version>1.7.6</slf4j.version>
        <spring.version>4.1.3.RELEASE</spring.version>
        <jackson.version>2.5.4</jackson.version>
    </properties>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>${spring.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>${commons-lang.version}</version>
        </dependency>


        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.2.2.v20140723</version>

                <configuration>
                    <httpConnector>
                        <port>9090</port>
                    </httpConnector>
                    <webAppConfig>
                        <!--浏览器网址是否需要输入包名-->
                        <contextPath>/${project.artifactId}</contextPath>
                        <!-- <contextPath>/</contextPath> -->
                    </webAppConfig>
                </configuration>

            </plugin>
        </plugins>
    </build>

</project>

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Spring MVC</display-name>

    <!-- 配置Spring框架配置的XML -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext*.xml</param-value>
    </context-param>

    <!-- DispatcherServlet, Spring MVC的核心 -->
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- DispatcherServlet对应的上下文配置, 默认为/WEB-INF/$servlet-name$-servlet.xml -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:mvc-dispatcher-servlet.xml</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>

    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <!-- mvc-dispatcher拦截所有的请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

mvc-dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:annotation-config />

    <!-- DispatcherServlet上下文, 只管理@Controller类型的bean, 忽略其他型的bean, 如@Service -->
    <context:component-scan base-package="com.lmr.springmvc">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!-- HandlerMapping, 无需配置, Spring MVC可以默认启动。 DefaultAnnotationHandlerMapping annotation-driven HandlerMapping -->

    <!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 -->
    <mvc:annotation-driven />

    <!-- 配置ViewResolver。 可以用多个ViewResolver。 使用order属性排序。InternalResourceViewResolver放在最后。 -->
    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="order" value="1" />
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
                <entry key="xml" value="application/xml" />
                <entry key="htm" value="text/html" />
            </map>
        </property>

        <property name="ignoreAcceptHeader" value="true" />
    </bean>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <!-- 视图渲染,并给返回的路径添加前缀和后缀 -->
        <property name="prefix" value="/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:annotation-config></context:annotation-config>

    <context:component-scan base-package="com.lmr.springmvc">
        <context:exclude-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

</beans>

Controller

1.基本配置
如果不基于注解:该类需要继承 CommandController
如果基于注解:在类名前加上 @controller
并使用@RequestMapping(”/xxxxx请求路径”)来指定请求路径

@Controller
@RequestMapping("/login")
public class LoginController {

    //方法级别的RequestMapping, 限制并缩小了URL路径匹配,同类级别的标签协同工作,最终确定拦截到的URL由那个方法处理
    @RequestMapping("/view")
    public String login() {

        //视图渲染,根目录下/login.jsp
        return "login";
    }

}

2.含有请求参数,使用Model传递参数到前台页面,处理/login/result1?id=123&pw=456 形式的URL

@RequestMapping(value = "/result1", method = RequestMethod.GET)
public String login1(@RequestParam("id") String id, @RequestParam("pw") String pw, Model model) {

    System.out.println("login1 " + id + " - - " + pw);

    LoginBean loginbean = new LoginBean(id, pw);
    // model.addAttribute("loginbean", loginbean);

    // 生成名字的规则是使用对象的类名的小写模式来作model名字。当这个model是集合或数组的时候,使用集合的第一个元素的类名加s来作model的名字。
    model.addAttribute(loginbean);

    return "loginsuccess";
}

3.含有请求参数,使用Map传递参数到前台页面

@RequestMapping(value = "/result2", method = RequestMethod.GET)
public String login2(@RequestParam("id") String id, @RequestParam("pw") String pw, Map<String, Object> model) {

    System.out.println("login2 " + id + " - - " + pw);

    LoginBean loginbean = new LoginBean(id, pw);
    model.put("loginbean", loginbean);

    return "loginsuccess";
}

4.使用Restful风格的URL ,须使用@PathVariable注解获取参数,处理/login/result3/123 形式的URL

@RequestMapping(value = "/result3/{id}/", method = RequestMethod.GET)
public String login3(@PathVariable("id") String id, Map<String, Object> model) {

    System.out.println("login3 " + id);

    LoginBean loginbean = new LoginBean(id, "159258357456");
    model.put("loginbean", loginbean);

    return "loginsuccess";
}

5.使用传统的HttpServletRequest,并用其获取参数,写入资源

@RequestMapping(value = "/result4")
public String login4(HttpServletRequest request) throws UnsupportedEncodingException {

    String id = request.getParameter("id");
    String pw = request.getParameter("pw");

    System.out.println("login4 " + id + " - - " + pw);

    LoginBean loginbean = new LoginBean(id, pw);

    request.setAttribute("loginbean", loginbean);
    request.setAttribute("msg", "这是Controller的msg");
    request.getSession().setAttribute("user", id);

    return "loginsuccess";
}

6.使用ModelAndView作为返回值,在ModelAndView中可配置参数,视图等

@RequestMapping(value = "/result5")
public ModelAndView login5(@RequestParam("id") String id, @RequestParam("pw") String pw) {

    System.out.println("login5 " + id + " - - " + pw);

    LoginBean loginbean = new LoginBean(id, pw);

    ModelAndView mv=new ModelAndView();
    mv.addObject(loginbean);
    mv.setViewName("loginsuccess");

    return mv;

}

7.value值可为空,可附加params属性,处理/score?add 形式的URL

@Controller
@RequestMapping("/score")
public class ScoreController {

    @RequestMapping(value="", method=RequestMethod.GET, params="add" )
    public String edit(){

        return "score/add";
    }

}

8.使用Bean类来获取前台页面提交的参数,前提是要配置相应的Bean类,而且Bean类中的参数名要与前台页面标签中name属性的相同

//SoreBean类
public class ScoreBean {

    private String sname;
    private String sid;
    private String sgrade;
    private int chinese;
    private int math;
    private int english;

    public ScoreBean() {
        super();
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getSgrade() {
        return sgrade;
    }

    public void setSgrade(String sgrade) {
        this.sgrade = sgrade;
    }

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getEnglish() {
        return english;
    }

    public void setEnglish(int english) {
        this.english = english;
    }

    @Override
    public String toString() {
        return "ScoreBean [sname=" + sname + ", sid=" + sid + ", sgrade=" + sgrade + ", chinese=" + chinese + ", math="
                + math + ", english=" + english + "]";
    }

}
<!--前台页面-->
<body>
    <form action="<%= request.getContextPath()%>/score/save1" method="post">
        姓名:<input id="sname" name="sname" type="text"> <br> <br>
        学号:<input id="sid" name="sid" type="text"> <br> <br>
        班级:<input id="sgrade" name="sgrade" type="text"> <br> <br>
        语文:<input id="chinese" name="chinese" type="text"> <br> <br>
        数学:<input id="math" name="math" type="text"> <br> <br>
        英语:<input id="english" name="english" type="text"> <br> <br>
        <button type="submit">添加</button>
        <button type="reset">重置</button>
    </form>
</body>
@RequestMapping(value="/save", method=RequestMethod.POST)
public String save(ScoreBean scoreBean,Model model){

    System.out.println(scoreBean.toString());

    model.addAttribute(scoreBean);

    return "score/result";
}

9.也可使用变量名直接获取前台页面的值,前提是该变量名要与前台页面标签中name属性的相同

@RequestMapping(value="/save1", method=RequestMethod.POST)
public String save1(Map<String, Object> model,String sname, String sid, String sgrade, int chinese, int math, int english){

    System.out.println(sname+" - - "+sid+" - - "+sgrade+" - - "+chinese+" - - "+math+" - - "+english);

    model.put("sname", sname);
    model.put("sid", sid);
    model.put("sgrade", sgrade);
    model.put("chinese", chinese);
    model.put("math", math);
    model.put("english", english);

//      return "score/result";
    //转发forward 重定向redirect
    return "forward:/score/save2";
}

SpringMVC使用ViewResovler来处理含义相同格式不同(json、xml、html)的数据,ViewResolver将最终数据格式根据需要转化为JSPView或者JsonView

在mvc-dispatcher-servlet.xml中配置ViewResolver,引入org.springframework.web.servlet.view.json.MappingJackson2JsonView

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="order" value="1" />
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
            <entry key="xml" value="application/xml" />
            <entry key="htm" value="text/html" />
        </map>
    </property>

    <property name="defaultViews">
        <list>
            <!-- JSON View -->
            <bean
                class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
            </bean>
        </list>
    </property>
    <property name="ignoreAcceptHeader" value="true" />
</bean>

1.使用@ResponseBody方式返回JSON数据

@RequestMapping(value="/json1", method=RequestMethod.GET)
public @ResponseBody List<ScoreBean> list1(){
    return scoreService.query();
}
@Service("scoreService")
public class ScoreService {

    public List<ScoreBean> query(){

        List<ScoreBean> scorelist=new ArrayList<>();
        for(int i=0;i<10;i++){
            ScoreBean scoreBean=new ScoreBean();
            Random rand=new Random();

            scoreBean.setSid((char)(rand.nextInt(26)+97)+"");
            scoreBean.setSname((char)(rand.nextInt(26)+97)+"");
            scoreBean.setSgrade((char)(rand.nextInt(26)+97)+"");
            scoreBean.setChinese(rand.nextInt(100));
            scoreBean.setMath(rand.nextInt(100));
            scoreBean.setEnglish(rand.nextInt(100));

            scorelist.add(scoreBean);

        }

        return scorelist;
    }

}

结果:返回一组随机生成的scorelist的JSON数据

[{"sname":"r","sid":"h","sgrade":"q","chinese":14,"math":39,"english":41},
{"sname":"l","sid":"i","sgrade":"i","chinese":68,"math":26,"english":14},
{"sname":"s","sid":"v","sgrade":"p","chinese":4,"math":19,"english":46},
{"sname":"k","sid":"r","sgrade":"x","chinese":90,"math":74,"english":21},
{"sname":"e","sid":"c","sgrade":"x","chinese":32,"math":47,"english":9},
{"sname":"b","sid":"r","sgrade":"s","chinese":91,"math":97,"english":78},
{"sname":"y","sid":"w","sgrade":"q","chinese":81,"math":76,"english":77},
{"sname":"q","sid":"z","sgrade":"c","chinese":38,"math":39,"english":78},
{"sname":"j","sid":"i","sgrade":"n","chinese":47,"math":97,"english":87},
{"sname":"x","sid":"x","sgrade":"l","chinese":46,"math":22,"english":47}]

2.使用ResponseEntity方式返回JSON数据

@RequestMapping(value="/json2", method=RequestMethod.GET)
public ResponseEntity<List<ScoreBean>> list2(){

    return new ResponseEntity<List<ScoreBean>>(scoreService.query(), HttpStatus.OK);
}

文件上传

在mvc-dispatcher-servlet.xml中配置multipartResolver

<!-- maxUploadSize:最大上传大小(200*1024*1024即200M);defaultEncoding:默认编码;resolveLazily:是否延迟加载文件解析(若启用可推迟文件解析,以便捕获文件大小异常) -->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="209715200" />
    <property name="defaultEncoding" value="UTF-8" />
    <property name="resolveLazily" value="true" />
</bean>

前端页面中文件上传的form表单必须的属性:enctype=”multipart/form-data”

<body>
    <center>
        <form action="<%=request.getContextPath() %>/file/load1" method="post" enctype="multipart/form-data">
            <input type="file" id="fileload" name="fileload">
            <input type="submit" value="上传">
        </form>
    </center>
</body>

1.使用@RequestParam(“fileload”)MultipartFile file 请求参数,获取前端页面传来的文件

@RequestMapping(value="/load", method=RequestMethod.POST)
public String load(@RequestParam("fileload")MultipartFile file,Model model) throws IOException{

    System.out.println(file.getOriginalFilename());
    FileUtils.copyInputStreamToFile(file.getInputStream(), new File("D:\\Text\\", System.currentTimeMillis()+ file.getOriginalFilename()));

    model.addAttribute("filename", file.getOriginalFilename());

    return "file/result";
}

2.使用MultipartHttpServletRequest获取前端页面传来的文件

@RequestMapping(value="/load1", method=RequestMethod.POST)
public String load1(MultipartHttpServletRequest multipartRequest,Model model) throws IOException{

    Map<String,MultipartFile> filemap=multipartRequest.getFileMap();

    for(Entry<String, MultipartFile> en:filemap.entrySet()){
        System.out.println(en.getKey()+" - - "+en.getValue().getOriginalFilename());
        FileUtils.copyInputStreamToFile(en.getValue().getInputStream(), new File("D:\\Text\\", System.currentTimeMillis()+ en.getValue().getOriginalFilename()));
    }

    return "file/result";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值