Spring MVC前后端交互原理及实现(附实例代码)

   前后端交互主要目的

               个人觉得,前后端交互的目的无非就是为了实现视图和业务逻辑的转换,前端发出请求,后端根据前端请求进行相应的数据处理然后给出不同响应

              先以Servlet为基础的Model工作流程了解一下前后端交互流程

              

  主要实现

          前后端交互有许多种实现方式,但都是围绕MVC编程模式来实现的,MVC编程模式。MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:

  •    Model(模型)表示应用程序核心(比如数据库记录列表)
  •    View(视图)显示数据(数据库记录)
  •    Controller(控制器)处理输入(写入数据库记录) 

         针对MVC编程又产生了一些框架中最出名即SpringMVC了,SpringMVC是基于Model2实现的技术框架;Spring MVC 分离了控制器、模型对象、过滤器以及处理程序对象的角色,这种分离让它们更容易进行定制。在SpringMVC中,Action不叫Actin,而被成为Controller;Controller接受参数request和response,并返回ModelAndView。这就是MVC编程的核心流程,通过对response和request对象进行一些操作再返回ModelAndView不正是V和M的转换吗。

          而SpringMVC的实现步骤分为6步:

 

  1. 客户端向Spring容器发起HTTP请求。
  2. 发起的请求被前端控制器(DispatcherServlet)所拦截,前端控制器回去寻找恰当的映射处理器来完成这次请求。
  3. DispatcherServlet根据处理器映射(HandlerMapping)来选择并决定将请求发送给哪一个控制器。
  4. 选定控制器之后,Dispatcher便将请求发送给它,在控制器中处理所发送的请求,并以ModelAndView(属性值和返回的页面)的形式返回给前端控制器DispatcherServlet,典型情况下是以JSP页面的形式返回。
  5. 返回给前端控制器的未必都是JSP页面,可能仅仅是一个逻辑视图名,通过逻辑视图名可以查找到实际的视图。前端控制器正式通过查询viewResolver对象将从控制器返回的逻辑视图名解析为一个具体的试图实现。
  6. 如果前端控制器找到相应的视图,则将视图返回给客户端,否则就抛出异常。

          以上是SpringMVC的实现基本实现原理,下面我们通过一个SSM框架的简单登录小实例来了解一下实现过程

 

首先看一下项目架构图:

 

数据库表结构图:

 

基本配置文档spring-mybatis.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"
	   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">
	<!-- 配置c3p0数据池作为数据源 -->
	<bean id="data" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"/>
		<property name="user" value="root"/>
		<property name="password" value="123456"/>
		<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/zyhs?useUnicode=true&characterEncoding=UTF-8&useSSL=false"/>

		<!--连接池中保留的最小连接数。-->
		<property name="minPoolSize" value="3"/>

		<!--连接池中保留的最大连接数。Default: 15 -->
		<property name="maxPoolSize" value="30"/>

		<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
		<property name="initialPoolSize" value="5"/>

		<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
		<property name="maxIdleTime" value="60"/>

		<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
		<property name="acquireIncrement" value="3"/>

		<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
         属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
         如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
		<property name="maxStatements" value="0"/>

		<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
		<property name="idleConnectionTestPeriod" value="10"/>

		<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
		<property name="acquireRetryAttempts" value="30"/>

		<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
         保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
         获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->
		<property name="breakAfterAcquireFailure" value="false"/>

		<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
         时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
         等方法来提升连接测试的性能。Default: false -->
		<property name="testConnectionOnCheckout" value="false"/>
	</bean>

	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 加载mybatis的核心配置文件 -->
		<!--<property name="configLocation" value="classpath:mybatis/sqlMapConfig.xml"/>-->
		<!-- 数据源 -->
		<property name="dataSource" ref="data"/>
	</bean>

	<!-- 配置mapper扫描器 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="cgl.xyhs.ssm.mapper"/>
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
	</bean>

</beans>

 

spring-mvc.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- 开启包扫描(扫描生成bean的注解) -->
    <context:component-scan base-package="cgl.xyhs"/>

	<!--使用mvc:annotation-driven标签替代上两个标签配置
		另外该标签会加载很多参数绑定的方法:例如json解析转换器
		实际开发使用该标签-->
    <mvc:annotation-driven conversion-service="conversionService" validator="validator"/> 

	<!-- 视图解析器 -->
	<!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">-->
        <!--<!–<property name="prefix" value="/WEB-INF"/>–>-->
		<!--<!– 后缀-->
		<!--<property name="suffix" value=".jsp"></property>–>-->
	<!--</bean>-->
</beans>

 

spring-transaction.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:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd">

	<!-- 事务管理器配置 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 数据源 -->
		<property name="dataSource" ref="data"/>
	</bean>
	<!-- 开启事务的注解配置,使用@Transactional声明 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <servlet>//注册HandlerMapping
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-*.xml</param-value>
    </init-param>
  </servlet>
 <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.action</url-pattern>
  </servlet-mapping>

  <filter>//配置过滤器
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>  //添加参数,为防止乱码将所有请求编码格式统一设为utf-8
      <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>

 

   数据持久化类Manager.java

package cgl.xyhs.ssm.pojo;

public class Manager {
	private String name;
	private String password;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	private String name;
	private String password;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}

ManagerMapper.java

package cgl.xyhs.ssm.mapper;

import org.springframework.stereotype.Repository;

import cgl.xyhs.ssm.pojo.Manager;


@Repository 
public interface ManagerMapper {
Manager selectByUserName(String name);   
}

 

ManagerMapper.xml  sql映射文件,文件中配置了操作数据库的sql语句

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cgl.xyhs.ssm.mapper.ManagerMapper">
    <resultMap id="BaseResultMap" type="cgl.xyhs.ssm.pojo.Manager">
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <result column="password" property="password" jdbcType="VARCHAR"/>
    </resultMap>
 //数据库匹配
 <select id="selectByUserName" resultMap="BaseResultMap" parameterType="java.lang.String">
        select *
        from manager
        where name = #{name ,jdbcType=INTEGER}
    </select>
</mapper>

ManagerMapper.java和ManagerMapper.xml文件都都要放在前面所配置的mapper扫描器所设置扫描的包下,不然会抛出异常找不到该注解。

现在写项目的服务层

ManagerService.java

package cgl.xyhs.web.service;


import cgl.xyhs.ssm.pojo.Manager;


public interface ManagerService {
	boolean login(Manager vo);

}
	boolean login(Manager vo);

}

服务实现层

UserServiceImpl.java


package cgl.xyhs.web.service.impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import cgl.xyhs.ssm.mapper.ManagerMapper;
import cgl.xyhs.ssm.pojo.Manager;
import cgl.xyhs.web.service.ManagerService;


@Service
public class ManagerServiceImp implements ManagerService {
	private final ManagerMapper mapper;


	@Autowired   //调用注解自动注入
	public ManagerServiceImp(ManagerMapper mapper) {
		this.mapper = mapper;
	}


	@Override    //验证用户名密码  也可在ManagerMapper写在接口中验证
	public boolean login(Manager vo) {
		Manager manager = mapper.selectByUserName(vo.getName());
		if (manager == null) return false;
		else if (manager.getPassword().equals(vo.getPassword())) {
			vo.setId(manager.getId());
			return true;
		} else return false;
	}
	private final ManagerMapper mapper;


	@Autowired   //调用注解自动注入
	public ManagerServiceImp(ManagerMapper mapper) {
		this.mapper = mapper;
	}


	@Override    //验证用户名密码  也可在ManagerMapper写在接口中验证
	public boolean login(Manager vo) {
		Manager manager = mapper.selectByUserName(vo.getName());
		if (manager == null) return false;
		else if (manager.getPassword().equals(vo.getPassword())) {
			vo.setId(manager.getId());
			return true;
		} else return false;
	}
}

 

最后编写相应的控制器ManagerController.java

 

package cgl.xyhs.web.controller;

import javax.servlet.http.HttpServletRequest;

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 cgl.xyhs.ssm.pojo.Manager;
import cgl.xyhs.web.service.ManagerService;

@Controller
public class ManagerSetController {
	private final ManagerService managerService;

	@Autowired
	public ManagerSetController(ManagerService managerService) {
		this.managerService = managerService;
	}

	@RequestMapping(value = "/login") //登录 
	public String skipPacks(Model model, HttpServletRequest request) {
		String error = request.getParameter("error");
		if (error != null) {
			model.addAttribute("error", "账号密码错误");
		}
		return "/backer/login.jsp";          
	}

	@RequestMapping(value = "/submitLogin")   //提交登录
	public String submitLogin(Model model, Manager vo, HttpServletRequest request) {
		if (managerService.login(vo)) {
			request.getSession().setAttribute("manager", vo);   //如果登陆成功则把用户信息放入session中 后面可以用来检测用户是否登录
			return "/backer/success.jsp";           //可直接返回方法、action、和jsp文件           
		} else {
			return "redirect:login.action?error=" + 1;       //如果验证不成功则继续返回登录界面
		}
	}
}

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>登录</title>
</head>

<body>
    <form  id="login" action="submitLogin.action" method="post">
        <div id="input">
            <br/>
            <h3>登录测试</h3>
            <hr/>
            <img src="static/icon/user.png" height="40px"/>   
            <input name="name" type="text"  placeholder="用户名" required><br/><br/>   //控制器中用的反射 所以这里属性名必须与持久化类中一样一样
            <img src="static/icon/password.png" height="40px"/>    
            <input name="password" type="password"  placeholder="密码" required><br/><br/>
        </div>
        <button type="submit" id="submit">登录</button>
    </form>

    <br/><br/>

</div>
</body>

<c:if test="${not empty error }">
    <script type="text/javascript">
        alert('${error}')                 //调用后端传过来的值 通过键值对的方式
    </script>
</c:if>
<script src="http://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</html>

success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>登录成功</title>
</head>

<body>
   <h3>登录成功</h3>
</body>

</html>

 这只是一个简单的登录测试,其余功能大家可以自由发挥

代码中的Model类是用来给前端JSP传递数据来生成前端html页面数据用的, 实为数据库在代码中的一种映射, 用来承载 如同数据表结构一般信息的存在,且用其在程序中传输 也就是说后端把值传到jsp页面可以用Model类

 

运行项目后登录流程为

       


                  

 

  • 11
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值