1. 思路理清
○ src/bean.xml: 是Spring的配置文件(< bean …>),bean管理,一定有该xml文件(可改名,如springmvc.xml)。在生产对象时加载此路径文件。 |
○ WebRoot/WEB_INF/web.xml: web应用时才会有该文件,配置servlet等信息。会指向上述的bean.xml。 |
2. MVC简介
既然MVC是一个设计模式,当然既可以在C/S(客户端服务器)模式下使用,也可以在B/S(浏览器服务器)模式下使用。下面我们介绍在B/S模式下的应用,如下所示: |
用户发起Request请求至控制器(Controller),控制器接收用户的请求,并将请求委托给模型进行处理。
控制器请求模型(Model),模型处理业务数据并得到处理结果,模型通常是指业务逻辑,包括Pojo、Service、Dao等三层
模型将处理结果返回给控制器
控制器将模型数据在视图(View)中展示
说明:web中模型无法将数据直接在视图上显示,需要通过控制器完成。如果在C/S应用中模型是可以将数据在视图中展示的。
控制器将视图响应结果,Response响应给用户,通过视图展示给用户数据或者处理结果。
Controller的作用
封装web请求为一个数据对象、调用业务逻辑层来处理数据对象、返回处理数据结果及相应的视图给用户。
Model的作用
处理业务数据,并返回处理结果
View的作用
渲染视图,并将数据或处理结果展示给用户
2. 流程
①部署web.xml |
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>----①
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>----②
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>----③
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
②< servlet> 标签指出使用springMVC的Dispatcher Servlet |
① < init-param> 属性指出springMVC配置文件的路径。文中写法表示src/.xml。如不写该属性,默认和web.xml同目录,即/WEB_INF/ |
③ < servlet-mapping> 指出哪些url映射到该servlet。若为 / ,表示所有url。 |
②配置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:util="http://www.springframework.org/schema/util"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<bean id="dbcp" class="org.apache.commons.dbcp.BasicDataSource">
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver">
</property>
<property name="url"
value="jdbc:mysql:///cloud_note?useUnicode=true&characterEncoding=utf8">
</property>
</bean>
<bean id="ssf"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dbcp"></property>
<property name="mapperLocations"
value="classpath:cn/whbing/note/sql/*.xml">
</property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.whbing.note.dao">
</property>
<!-- 自动注入sqlsessionfactory -->
</bean>
<!-- 开启扫描,扫描Controller,Service组件 -->
<context:component-scan base-package="cn.whbing.note"/>
<!-- handlermapping,支持@RequestMapping,@ResponseBody,@Exceptionhanlder -->
<mvc:annotation-driven />
</beans>
该配置详解见下文。
3. 代码及原理
①Controller |
package cn.whbing.note.controller.notebook;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.whbing.note.entity.NoteResult;
import cn.whbing.note.service.NoteBookService;
@Controller
@RequestMapping("/notebook")
public class addNoteBookController {
@Resource
private NoteBookService noteBookService;
@RequestMapping("/add.do")
@ResponseBody
public NoteResult excute(String noteBookName,String userId) {
NoteResult result=noteBookService.addNoteBook(noteBookName, userId);
return result;
}
}
②Service |
接口
package cn.whbing.note.service;
import cn.whbing.note.entity.NoteBook;
import cn.whbing.note.entity.NoteResult;
public interface NoteBookService {
NoteResult loadNoteBooks(String userId);
NoteResult addNoteBook(String noteBookName,String userId);
}
实现类
package cn.whbing.note.service;
import java.sql.Timestamp;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import cn.whbing.note.dao.NoteBookDao;
import cn.whbing.note.entity.NoteBook;
import cn.whbing.note.entity.NoteResult;
import cn.whbing.note.util.NoteUtil;
@Service
public class NoteBookServiceImp1 implements NoteBookService{
@Resource
private NoteBookDao noteBookDao;
@Override
public NoteResult loadNoteBooks(String userId) {
List<NoteBook> list=noteBookDao.findByUser(userId);
NoteResult result=new NoteResult();
result.setStatus(0);
result.setMsg("查询笔记本成功");
result.setData(list);
return result;
}
@Override
public NoteResult addNoteBook(String noteBookName,String userId) {
//用户传入的noteBookName及userId将赋给新建的笔记本
//新建笔记本
NoteBook noteBook=new NoteBook();
noteBook.setCn_notebook_name(noteBookName);
noteBook.setCn_user_id(userId);
noteBook.setCn_notebook_type_id("1");//默认类型
noteBook.setCn_notebook_id(NoteUtil.createId());
//desc字段先为空
//创建时间为Timestamp类型
Timestamp nowTime=new Timestamp(System.currentTimeMillis());
noteBook.setCn_notebook_createtime(nowTime);
noteBookDao.save(noteBook);;
NoteResult result=new NoteResult();
result.setStatus(0);
result.setMsg("添加笔记本成功");
result.setData(noteBook.getCn_notebook_id());//返回noteId是为了后面工作
return result;
}
}
原理解析 |
1. Dispatcherservlet
DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring MVC的第一步。 |
注解 |
1. SpringMVC的四个基本注解annotation
@Component、@Repository @Service、@Controller
其实,这四个注解的效果都是一样的,(作用)spring都会把它们当做需要注入的Bean加载在上下文中;而@Component (字面意思就是组件),它在你确定不了事哪一个层的时候使用。 |
但是在项目中,却建议你严格按照除Componen的其余三个注解的含义使用在项目中。这对分层结构的web架构很有好处!!
① 控制层
@Controller // 控制层,就是我们的action层
@RequestMapping(“/notebook”)
public class addNoteBookController {
@Resource
private NoteBookService noteBookService;
@RequestMapping(“/add.do”)
@ResponseBody
public NoteResult excute(String noteBookName,String userId) {
NoteResult result=noteBookService.addNoteBook(noteBookName, userId);
return result;
}
}
② 业务逻辑层
@Service(“userService”)
public class UserServiceImpl implements IUserService {
@Autowired
@Qualifier(“userDao”)
private IUserDao userDao;
… …
③ 持久层 ( 即dao层 )
@Repository(“userDao”)
public class UserDaoImpl implements IUserDao {
… …
2. @RequestMapping
RequestMapping是一个用来处理请求地址映射的注解(将请求映射到对应的控制器方法中),可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径 |
3. @Resource 或@Autowired @Qualifier(“userDao”)
@Resource
或
@Autowired
@Qualifier(“userDao”)
都表示注入对象,前者按名称,后者按类型。
4. @ResponseBody
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区 |
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用; |
实体类entity |
笔记本类
package cn.whbing.note.entity;
import java.io.Serializable;
import java.sql.Timestamp;
public class NoteBook implements Serializable{
private String cn_notebook_id;
private String cn_user_id;
private String cn_notebook_type_id;
private String cn_notebook_name;
private String cn_notebook_desc;
private Timestamp cn_notebook_createtime; //java sql下有这个类型
... ...
结果类
将操作结果的状态及数据存在结果类中,返回前台的也是这个结果类。通过@responseBody解析成json即可。 |
package cn.whbing.note.entity;
import java.io.Serializable;
public class NoteResult implements Serializable {
private int status; //状态
private String msg; //消息
private Object data=null; //数据
Ajax交互 |
$.ajax({
url:"note/add.do",
type:"post",
data:{"noteName":noteName,"bookId":bookId,"userId":userId},
dataType:"json",
success:function(result){
if(result.status==0){
hideAddNoteAlert();//关闭对话框
var noteId = result.data;//获取笔记ID
... ...
说明 |
1.service层调用dao操作数据库的方法,见后文的mybatis。
2.关于Controller中的ModelAndView,是Controller结果的一种返回方式,一般与jsp结合,渲染的时候可用,常见的返回方式如下。
1、返回ModelAndView 返回ModelAndView时最常见的一种返回结果。需要在方法结束的时候定义一个ModelAndView对象,并对Model和View分别进行设置。 |
@Controller
@RequestMapping("/MVCReturn")
public class SpringMVCReturnController {
@RequestMapping(value="/index1",method=RequestMethod.GET)
public ModelAndView index(){
ModelAndView modelAndView = new ModelAndView("/user/index");
modelAndView.addObject("name", "xxx");
return modelAndView;
}
//对于ModelAndView构造函数可以指定返回页面的名称,也可以通过setViewName方法来设置所需要跳转的页面;
//采用传统继承的方式:
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mav =new ModelAndView();
mav.setViewName("hello");
//**设置视图名,对应View中jsp文件名(去掉jsp)
mav.getModel().put("msg", "模型数据");
//**等价于request.setAttribute("msg","模型数据");底层还是调用这个
return mav;
}
}
2.:代表redirect重定向 redirect的特点和servlet一样,使用redirect进行重定向那么地址栏中的URL会发生变化,同时不会携带上一次的request 案例: |
public String testController(Model model){
return "redirect:path";//path代表重定向的地址,如"redirect:hello";
}
3.:代表forward转发 通过forward进行转发,地址栏中的URL不会发生改变,同时会将上一次的request携带到写一次请求中去 案例: |
public String testController(Model model){
return "forward:path";//path代表转发的地址
}