springMVC笔记系列(19)——控制器实现详解(上)

来源:互联网 发布:linux如何开启ftp服务 编辑:程序博客网 时间:2024/05/23 20:13

说明:本文章的内容转载至:https://my.oschina.net/happyBKs/blog/420310
如有侵权的地方,请联系本人,本人将会立即删除!

本文我们在前文基础上引入一个例子,边做边聊控制器。

我们想实现一个课程查询的功能。

首先大脑应该条件反射——如何定义MVC。

M:课程(包含章节)——Course(包含Chapter)

V:课程页面——course_overview.jsp

C:编写一个控制器接收springMVC前端控制器dispatcherServlet的请求转发——CourseController

另外,Service——一些业务逻辑调用——业务接口CourseService,业务实现CourseServiceImpl

然后,在思考如何在springMVC下组织上述各个部分。

C控制器是M、V、Service的中间桥梁,如何组织都是围绕着C展开的。

请求URL由springMVC前端控制器dispatcherServlet转发给控制器C——在web.xml配置dispatcherServlet,给出前端控制器配置文件路径

如何标记控制器C——配置前端控制器配置文件,定义搜索包范围空间、激活注解;在类定义的地方为类添加控制器注解

如何将URL请求与控制器之间建立映射——RequestMapping注解控制器类和方法

控制器C调用Service业务逻辑——在控制器类相应方法中调用Service接口方法;Service被控制器C所关联,控制器C中的Service属性引用需要用spring的依赖注入的方式完成初始化,所以要配置spring容器(一是要在web.xml配置spring,指明spring容器配置文件路径;二是在spring容器配置文件中配置好这些bean,本文的示例采用注解方法)

控制器C与视图V建立映射——前端控制器配置文件配置ViewResolver(定义前缀和后缀);控制器类的对应的接收请求的方法返回字符串;拼接出webapp下的资源路径字符串。

以上我通过两两关系描述了几部分是如何组织起来的,各种配置分别解决哪一个两两关系。好,我们直接进入项目来看。

首先是定义M、V、C、Service几个部分:
这里写图片描述

M部分:

Course:

package com.happyBKs.model;import java.util.List;public class Course {    // 课程Id    private Integer courseId;    // 课程名称    private String title;    // 图片路径    private String imgPath;    // 学习人数    private Integer learningNum;    // 课程时长    private Long duration;    // 课程难度    private Integer level;    // 课程难度描述    private String levelDesc;    // 课程介绍    private String descr;    // 课程提纲    private List chapterList;    public Integer getCourseId() {        return courseId;    }    public void setCourseId(Integer courseId) {        this.courseId = courseId;    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public Integer getLearningNum() {        return learningNum;    }    public void setLearningNum(Integer learningNum) {        this.learningNum = learningNum;    }    public Integer getLevel() {        return level;    }    public void setLevel(Integer level) {        this.level = level;    }    public String getImgPath() {        return imgPath;    }    public void setImgPath(String imgPath) {        this.imgPath = imgPath;    }    public List getChapterList() {        return chapterList;    }    public void setChapterList(List chapterList) {        this.chapterList = chapterList;    }    public Long getDuration() {        return duration;    }    public void setDuration(Long duration) {        this.duration = duration;    }    public String getDescr() {        return descr;    }    public void setDescr(String descr) {        this.descr = descr;    }    public String getLevelDesc() {        return levelDesc;    }    public void setLevelDesc(String levelDesc) {        this.levelDesc = levelDesc;    }}

Chapter:

package com.happyBKs.model;public class Chapter {    private Integer id;    private Integer courseId;    private Integer order;    private String title;    private String descr;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public Integer getCourseId() {        return courseId;    }    public void setCourseId(Integer courseId) {        this.courseId = courseId;    }    public Integer getOrder() {        return order;    }    public void setOrder(Integer order) {        this.order = order;    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public String getDescr() {        return descr;    }    public void setDescr(String descr) {        this.descr = descr;    }}

V:

\src\main\webapp\WEB-INF\jsps\course_overview.jsp

<%@ page language="java"     contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>HappyBKs喜欢原先的osc博客页面</title><link rel="stylesheet"    href="<%=request.getContextPath()%>/resources/css/main.css"    type="text/css" /></head><body>    <div id="main">        <div class="newcontainer" id="course_intro">            <div class="course-title">${course.title}</div>            <div class="course_info">                <div class="course-embed l">                    <div id="js-course-img" class="img-wrap">                        <img width="600" height="340" alt=""                            src="<%=request.getContextPath()%>/${course.imgPath}"                            class="course_video" />                    </div>                    <div id="js-video-wrap" class="video" style="display: none">                        <div class="video_box" id="js-video"></div>                    </div>                </div>                <div class="course_state">                    <ul>                        <li><span>学习人数</span> <em>${course.learningNum }</em></li>                        <li class="course_hour"><span>课程时长</span> <em                            class="ft-adjust"><span>${course.duration }</span></em></li>                        <li><span>课程难度</span> <em>${course.levelDesc }</em></li>                    </ul>                </div>            </div>            <div class="course_list">                <div class="outline">                    <h3 class="chapter_introduces">课程介绍</h3>                    <div class="course_shortdecription">${course.descr}</div>                    <h3 class="chapter_catalog">课程提纲</h3>                    <ul id="couList">                        <c:forEach items="${course.chapterList}" var="chapter">                            <li class="clearfix open"><a href="#">                                    <div class="openicon"></div>                                    <div class="outline_list l">                                        <!-- <em class="outline_zt"></em> -->                                        <h5 class="outline_name">${chapter.title }</h5>                                        <p class="outline_descr">${chapter.descr }</p>                                    </div>                            </a></li>                        </c:forEach>                    </ul>                </div>            </div>        </div>    </div></body></html>

值得注意的是,这里的href=”<%=request.getContextPath()%>/resources/css/main.css”这里url资源路径中的resources/**会在前端控制器配置文件中被配置映射到webapp项目资源路径。

这个后面会有详细的配置文件。

另外,jsp页面中的EL表达式中course,其名称也与控制器类中的相关参数和配置相对应。

Service:

业务模块部分都是讲接口调用和业务实现分类的。一个接口对应一个实现。
这里写图片描述
CourseService

package com.happyBKs.service;import com.happyBKs.model.Course;import org.springframework.stereotype.Service;@Servicepublic interface CourseService {    Course getCoursebyId(Integer courseId);}

CourseServiceImpl

package com.happyBKs.service.impl;import java.util.ArrayList;import java.util.List;import com.happyBKs.model.Chapter;import com.happyBKs.model.Course;import com.happyBKs.service.CourseService;import org.springframework.stereotype.Service;@Service("courseService")public class CourseServiceImpl implements CourseService {    public Course getCoursebyId(Integer courseId) {        Course course = new Course();        course.setCourseId(courseId);        course.setTitle("springMVC笔记系列");        course.setImgPath("resources/imgs/course-img.jpg");        course.setLearningNum(12345);        course.setLevel(2);        course.setLevelDesc("中级");        course.setDuration(7200l);        course.setDescr("springMVC哈哈哈哈。");        List<Chapter> chapterList = new ArrayList<Chapter>();        warpChapterList(courseId,chapterList);        course.setChapterList(chapterList);        return course;    }    private void warpChapterList(Integer courseId,List<Chapter> chapterList) {        Chapter chapter = new Chapter();        chapter.setId(1);        chapter.setCourseId(courseId);        chapter.setOrder(1);        chapter.setTitle("第1章 什么springMVC");        chapter.setDescr("此处略去1个字");        chapterList.add(chapter);        chapter = new Chapter();        chapter.setId(2);        chapter.setCourseId(courseId);        chapter.setOrder(2);        chapter.setTitle("第2章 环境搭建");        chapter.setDescr("此处略去2个字");        chapterList.add(chapter);        chapter = new Chapter();        chapter.setId(3);        chapter.setCourseId(courseId);        chapter.setOrder(3);        chapter.setTitle("第3章 前端控制器");        chapter.setDescr("此处略去3个字");        chapterList.add(chapter);        chapter = new Chapter();        chapter.setId(4);        chapter.setCourseId(courseId);        chapter.setOrder(4);        chapter.setTitle("第4章 spring上下文环境配置");        chapter.setDescr("此处略去4个字");        chapterList.add(chapter);        chapter = new Chapter();        chapter.setId(5);        chapter.setCourseId(courseId);        chapter.setOrder(5);        chapter.setTitle("第5章 示例");        chapter.setDescr("此处略去5个字");        chapterList.add(chapter);    }}

控制器C:

好好好,终归到了几个部分的中心环节了。CourseController类是控制器类,用@Controller注解。其类和方法注解@RequestMapping,实现请求url到控制器类的映射。当然控制器类的相应方法会返回相关字符串,与前端控制器配置文件\WEB-INF\configs\spring\mvc-dispatcher-servlet.xml中的项目视图资源映射,即这里映射到\WEB-INF\jsps\course_overview.jsp

CourseController

package com.happyBKs.controller;import com.happyBKs.model.Course;import com.happyBKs.service.CourseService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;/** * Created by happyBKs on 2016/6/15. */@Controller@RequestMapping("/courses")// /courses/**public class CourseController {    //完成日志信息    private static Logger log= LoggerFactory.getLogger(CourseController.class);    private CourseService courseService;    //使用spring容器管理里了对应的依赖关系    @Autowired    public void setCourseService(CourseService courseService) {        this.courseService = courseService;    }    //提供完成一个业务的方法:根据课程ID查询课程内容。    //本方法将处理 /courses/view?courseId=123 形式的URL    @RequestMapping(value="/view", method= RequestMethod.GET)    public String viewCourse(@RequestParam("courseId") Integer courseId,                             Model model) {        //日志输出,查看请求的courseId是不是我们的courseId        log.debug("In viewCourse, courseId = {}", courseId);        Course course = courseService.getCoursebyId(courseId);        model.addAttribute(course);        return "course_overview";    }}

在这个控制器类中,我们注入了一个Service。Service和控制器C之间存在依赖,我们使用spring依赖注入Service的实现类对象,使用的自动化注入成员变量引用某个具体的bean,用@Autowired注解,相应的被注解的业务实现类需要标注@Service,并且,spring配置文件的搜索包空间必须包含它。

另外,本控制器类中增加了一个日志工具,帮助我们记录下执行步骤和信息。因为需要用slf4j中的log相关类型。所以我们需要重新对pom.xml增加一些jar的依赖坐标。

pom.xml

<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>testIdea.happBKs.mvc</groupId>  <artifactId>springMVC</artifactId>  <packaging>war</packaging>  <version>1.0-SNAPSHOT</version>  <name>springMVC Maven Webapp</name>  <url>http://maven.apache.org</url>  <properties>    <commons-lang.version>2.6</commons-lang.version>    <slf4j.version>1.7.21</slf4j.version>    <spring.version>4.2.6.RELEASE</spring.version>    <jackson.version>2.7.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>4.10</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>com.fasterxml.jackson.core</groupId>      <artifactId>jackson-databind</artifactId>      <version>${jackson.version}</version>    </dependency>    <dependency>      <groupId>jstl</groupId>      <artifactId>jstl</artifactId>      <version>1.2</version>    </dependency>  </dependencies>  <build>    <finalName>springMVC</finalName>  </build></project>

还需要一log的配置文件:
这里写图片描述
注意,这个配置文件属于源代码的配置文件,与webapp的配置文件不同,所以这里所处的resouces文件夹其实不同的一个,特别注意!!

log4j.appender.Cons=org.apache.log4j.ConsoleAppenderlog4j.appender.Cons.layout=org.apache.log4j.PatternLayoutlog4j.appender.Cons.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n# Root logger set to DEBUG using the A2 appender defined above.log4j.rootLogger=info, Cons log4j.additivity=false#Application Logger+log4j.logger.com.imooc.mvcdemo=debug, Conslog4j.logger.org.springframework=debug, Conslog4j.additivity.com=false

springMVC的配置文件\WEB-INF\configs\spring\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">    <!-- 本配置文件是工名为mvc-dispatcher的DispatcherServlet使用, 提供其相关的Spring MVC配置 -->    <!-- 启用Spring基于annotation的DI, 使用户可以在Spring MVC中使用Spring的强大功能。 激活 @Required        @Autowired,JSR 250's @PostConstruct, @PreDestroy and @Resource 等标注 -->    <context:annotation-config />    <!-- DispatcherServlet上下文, 只管理@Controller类型的bean, 忽略其他型的bean, 如@Service -->    <context:component-scan base-package="com.happyBKs.controller">        <context:include-filter type="annotation"  expression="org.springframework.stereotype.Controller" />    </context:component-scan>    <!-- HandlerMapping, 无需配置, Spring MVC可以默认启动。 DefaultAnnotationHandlerMapping        annotation-driven HandlerMapping -->    <!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 -->    <mvc:annotation-driven />    <!-- 静态资源处理, css, js, imgs -->    <mvc:resources mapping="/resources/**" location="/resources/" />    <!-- 配置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="defaultViews">-->    <!--<list>-->    <!--&lt;!&ndash; JSON View &ndash;&gt;-->    <!--<bean-->    <!--class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">-->    <!--</bean>-->    <!--</list>-->    <!--</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="/WEB-INF/jsps/" />        <property name="suffix" value=".jsp" />    </bean>    <!--200*1024*1024即200M 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>--></beans>

spring容器配置文件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:component-scan base-package="com.happyBKs">        <context:exclude-filter type="annotation"            expression="org.springframework.stereotype.Controller" />    </context:component-scan></beans>

这里写图片描述

另外需要一些css文件和js文件,这个不细说。
这里写图片描述
最后请求的结果如下:
这里写图片描述

0 0
原创粉丝点击