您的位置:首页 > 编程语言 > Java开发

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

2016-12-03 17:36 585 查看
说明:本文章的内容转载至: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.
17bf4
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;

@Service
public 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.ConsoleAppender
log4j.appender.Cons.layout=org.apache.log4j.PatternLayout
log4j.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, Cons
log4j.logger.org.springframework=debug, Cons
log4j.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>-->
<!--<!– JSON View –>-->
<!--<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文件,这个不细说。



最后请求的结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring mvc mvc