SpringMVC+Spring+Mybatis整合即ssm整合 ,简单的访问数据库登录查询书籍首页案例,2万字硬核干货,涉及整合当中的百分之90错误以及错误排查思路,小白新手必看

SSM整合 ,简单的登录查询案例

#前期准备和了解
1.简介:
本文为SSM即SpringMVC+Spring+Mybatis的组合本案例,本案例适合已经学了j2ee和mysql数据库以及以上3个框架的人员整合练习作为一个ssm入门整合案例,本人在学习开发此案例时用的spring4+mybatis3练习的。再开始前请记住一句话,spring框架是一站式的,它不局限于特定的某层,它几乎是无处不在的!核心就是IOC和AOP而springmvc则是controller层,负责视图交互这一块的框架,而mybatis则是dao层,负责数据操作增删改查这一块的框架。

本案例实践过程:通过利用mybatis框架连接数据库其通过spring容器来创建对象注入数据源和mybatis的实现依赖sqlSessionFactory的实例bean对象,来实现mybatis的正常使用,即控制反转,同时每层传递的实例对象也都是通过spring生成的,在service层处理数据,然后传给springmvc,通过视图交互,把数据封装,传递给jsp,同时springmvc处理对象和数据的方法中实际上调用的是servletAPI接口,其使用的http请求种携带session等参数,一并封装,客户端与服务器进行了交互,从而实现登录状态保持的。

本质就是通过spring创建对象串联起一切操作!!

理解了本案原理可做拓展进一步优化项目,以此为模型修改成一个有价值的网站,例如优化校验增加注册,增加一些其他的业务表,思考清楚表之间的关系,可做一个简易的博客网站,或者资讯网站等。

1.准备

1.1开发环境搭建:

①JDK8,配置环境变量JAVA_HOME,PATH和CLASSPATH
②安装eclipse,并在eclipse中集成Tomcat8
③安装Mysql5以上数据库,建议安装上sqlyog或navicat这样中可视化软件搭配使用

1.2准备所需要的jar:(jar下载在路径在文末)

1.Spring框架jar:spring-framework-4.2.0.RELEASE文件夹libs目录所有模块class文件的JAR包和Spring的核心容器必须依赖的common-	logging的JAR,共21个
2.Mybatis的jar包:mybatis-3.4.1和mybatis-3.4.1文件夹下的lib目录下所有jar包,共13个
3.MyBatis整合Spring中间Jar包:Mybatis-Spring-1.3.0.jar(作用:在Spring中配置MyBatis工厂类,在DAO层使用Spring注入的工具	Bean对数据进行操作)
4.Spring的AOP事务jar包
5.aspectj框架jar包:aspectjrt.jar、aspectjtools.jar、aspectweaver.jar和org.aspect.matcher.jar
6.aop联盟jar包:c3p0-0.9.2.1.jar、hebernate-c3p0-4.3.5.Final.jar和mchange-commons-java-0.2.3.4.jar
7.JSTL标签库jar包:javax.servlet.jsp.jstl-1.2.1.jar和javax.servlet.jsp.jstl-api-1.2.1.jar

1.3创建数据库:

在mysql数据库创建新的database即一个新的数据库:fkmybatis,在数据库里建两个表tb_user和tb_book(可手动视图引导创建也可用语句创建)

sql语句创建:
创建fkmybaits数据库:
CREATE DATABASE /!32312 IF NOT EXISTS/fkmybatis /*!40100 DEFAULT CHARACTER SET utf8 */;

USE fkmybatis;
创建tb_user表:
CREATE TABLE tb_user (
id int(11) NOT NULL AUTO_INCREMENT,
loginname varchar(50) DEFAULT NULL,
password varchar(18) DEFAULT NULL,
username varchar(18) DEFAULT NULL,
phone varchar(18) DEFAULT NULL,
address varchar(255) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY loginname (loginname)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
插入数据:
insert into tb_user(id,loginname,password,username,phone,address) values (1,‘jack’,‘123456’,‘杰克’,‘13920001234’,‘广州市天河区’);
创建tb_book表:
CREATE TABLE tb_book (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(54) DEFAULT NULL,
author varchar(54) DEFAULT NULL,
publicationdate date DEFAULT NULL,
publication varchar(150) DEFAULT NULL,
price double DEFAULT NULL,
image varchar(54) DEFAULT NULL,
remark varchar(600) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

插入数据:
insert into tb_book(id,name,author,publicationdate,publication,price,image,remark) values

(1,‘疯狂Java’,‘李刚’,‘2008-10-01’,‘电子工业出版社’,74.2,‘java.jpg’,‘java’),

(2,‘轻量级JavaEE企业应用实战’,‘李刚’,‘2008-11-01’,‘电子工业出版社’,59.2,‘ee.jpg’,‘javaee’),

(3,‘疯狂Android讲义’,‘李刚’,‘2011-07-01’,‘电子工业出版社’,60.6,‘android.jpg’,‘android’),

(4,‘疯狂Ajax讲义’,‘李刚’,‘2011-07-01’,‘电子工业出版社’,66.6,‘ajax.jpg’,‘异步连接’);
在这里插入图片描述
在这里插入图片描述

2.创建工程

在eclispe创建动态web项目(File=>new=>Dynamic web project),创建3.1版本的,项目名为fkbookapp,next,然后到看见generate web.xml deloyment descriptor,把它勾选上带有3.1版本的头文件的web.xml

2.1在lib包下,导入jar,build path

2.2完成配置文件

1.创建db.properties,fkbookapp/src/db.properties(创建的时候主要配置文件的值后面不要有空格,不然可能造成连接数据库失败,数据库名名字和密码根据实际填写,信息不能正确也会报连接失败,遇到这类问题注意看eclipse的错误信息提醒,尤其是cause by后面的就是重点)

2.2.1配置数据库相关文件:

dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql:///fkmybatis
dataSource.user=root
dataSource.password=root3306
dataSource.maxPoolSize=20
dataSource.maxIdleTime=1000
dataSource.minPoolSize=6
dataSource.initialPoolSize=5

2.2.2创建applicationContext.xml,在fkbookapp/WebContent/WEB-INF/applicationContext.xml(配置mybatis连接池等),代码如下:

	<?xml version="1.0" encoding="UTF-8"?>
	<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
			            http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
			            http://www.springframework.org/schema/context
			            http://www.springframework.org/schema/context/spring-context-4.2.xsd
			            http://www.springframework.org/schema/mvc
			            http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
			            http://www.springframework.org/schema/tx
			            http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
			            http://mybatis.org/schema/mybatis-spring 
			            http://mybatis.org/schema/mybatis-spring.xsd ">
			      
	 <!-- mybatis:scan会将org.fkit.mapper包里的所有接口当作mapper配置,之后可以自动引入mapper类-->  
    <mybatis:scan base-package="org.fkit.mapper"/>   
       
	 <!-- 扫描org.fkit包下面的java文件,有Spring的相关注解的类,则把这些类注册为Spring的bean -->
    <context:component-scan base-package="org.fkit"/>
    
	<!-- 使用PropertyOverrideConfigurer后处理器加载数据源参数 -->
	<context:property-override location="classpath:db.properties"/>

	<!-- 配置c3p0数据源 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"/>
	
	<!-- 配置SqlSessionFactory,org.mybatis.spring.SqlSessionFactoryBean是Mybatis社区开发用于整合Spring的bean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
	    p:dataSource-ref="dataSource"/>
	
	<!-- JDBC事务管理器 -->
	<bean id="transactionManager" 
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
		 p:dataSource-ref="dataSource"/>
	
	<!-- 启用支持annotation注解方式事务管理 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
	
</beans>

③创建springmvc-config.xml,在fkbookapp/WebContent/WEB-INF/springmvc-config.xml(此处为配置mvc和视图交互的配置)
代码:

<?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:mvc="http://www.springframework.org/schema/mvc"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="
	        http://www.springframework.org/schema/beans
	        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	        http://www.springframework.org/schema/mvc
	        http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd     
	        http://www.springframework.org/schema/context
	        http://www.springframework.org/schema/context/spring-context-4.2.xsd">
	        
	    <!-- 自动扫描该包,SpringMVC会将包下用了@controller注解的类注册为Spring的controller -->
	    <context:component-scan base-package="org.fkit.controller"/>
	    <!-- 设置默认配置方案 -->
	    <mvc:annotation-driven/>
	    <!-- 使用默认的Servlet来响应静态文件 -->
	    <mvc:default-servlet-handler/>
	    <!-- 视图解析器  -->
	    <bean id="viewResolver"
	          class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
	        <!-- 前缀 -->
	        <property name="prefix">
	            <value>/WEB-INF/content/</value>
	        </property>
	        <!-- 后缀 -->
	        <property name="suffix">
	            <value>.jsp</value>
	        </property>
	    </bean>
</beans>

④找到web.xml补充代码,在fkbookapp/WebContent/WEB-INF/web.xml,这里配置的是j2ee的文件配置,完整代码如下:

<?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">
	 <display-name>fkbookapp</display-name>
	 			 <!--配置Spring的监听器,默认只加载WEB-INF目录下的applicationContext.xml配置文件-->
	  			<listener>
	  			  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	  			</listener>
	  			<!-- contextConfigLocation参数用来指定Spring的配置文件 -->
				<context-param>
					<param-name>contextConfigLocation</param-name>
					<param-value>/WEB-INF/applicationContext*.xml</param-value>
				</context-param>
				<!-- 定义Spring MVC的前端控制器 -->
	  			<servlet>
		    			<servlet-name>springmvc</servlet-name>
		    		<servlet-class>
		        		org.springframework.web.servlet.DispatcherServlet
		    		</servlet-class>
	   				 	<init-param>
					      <param-name>contextConfigLocation</param-name>
					      <param-value>/WEB-INF/springmvc-config.xml</param-value>
					    </init-param>
	   					 <load-on-startup>1</load-on-startup>
	  				</servlet>
				  <!-- 让Spring MVC的前端控制器拦截所有请求 -->
				  <servlet-mapping>
				    <servlet-name>springmvc</servlet-name>
				    <url-pattern>/</url-pattern>
				  </servlet-mapping>
				  <!-- 编码过滤器 -->
				  <filter>
						<filter-name>characterEncodingFilter</filter-name>
						<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
						<init-param>
							<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>
				  
				  <welcome-file-list>
				    <welcome-file>index.html</welcome-file>
				    <welcome-file>index.htm</welcome-file>
				    <welcome-file>index.jsp</welcome-file>
				    <welcome-file>default.html</welcome-file>
				    <welcome-file>default.htm</welcome-file>
				    <welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>

2.3持久层实现

2.3.1领域对象层

在src下创org.fkit.domain包(领域对象层),下面创User和Book对象类,赋予私有属性,给出get,set方法(get,set方法必须给出,set方法是提供正常的传参对象封装以及spring框架注入对象使用的,同时注意此处的属性值要对应数据库里面的字段名,不然后面依赖spring的自动注入注解可能会报错,get方法是对外提供的一个方法,对象这个抽象的对象类的实体取值,都需要这个get方法)
代码如下:

package org.fkit.domain;

import java.io.Serializable;
			
public class User implements Serializable {
			private Integer id;//id
			private String loginname;//登录名
			private String password;//密码
			private String username;//用户名
			private String phone;//电话
			private String address;//地址
				//getter和setter
			    public Integer getId() {
					return id;
				}
				public void setId(Integer id) {
					this.id = id;
				}
				public String getLoginname() {
					return loginname;
				}
				public void setLoginname(String loginname) {
					this.loginname = loginname;
				}
				public String getPassword() {
					return password;
				}
				public void setPassword(String password) {
					this.password = password;
				}
				public String getUsername() {
					return username;
				}
				public void setUsername(String username) {
					this.username = username;
				}
				public String getPhone() {
					return phone;
				}
				public void setPhone(String phone) {
					this.phone = phone;
				}
				public String getAddress() {
					return address;
				}
				public void setAddress(String address) {
					this.address = address;
				}
				
			}
package org.fkit.domain;

import java.io.Serializable;
import java.sql.Date;
			
public class Book implements Serializable {
		private Integer id;//id
		private String name;//书名
		private String author;//作者
		private Date publicationdate;//出版日期
		private String publication;//出版社
		private Double price;//价格
		private String image;//封面图片
		private String remake;//详细描述
		
		    //getter和setter
		    public Integer getId() {
				return id;
			}
			public void setId(Integer id) {
				this.id = id;
			}
			public String getName() {
				return name;
			}
			public void setName(String name) {
				this.name = name;
			}
			public String getAuthor() {
				return author;
			}
			public void setAuthor(String author){
				this.author = author;
			}
			public Date getPublicationdate() {
				return publicationdate;
			}
			public void setPublicationdate(Date publicationdate) {
			    this.publicationdate = publicationdate;
			}
			public String getPublication() {
				return publication;
			}
			public void setPublication(String publication) {
			   this.publication = publication;
			}
			public Double getPrice() {
					return price;
			}
			public void setPrice(Double price) {
					this.price = price;
			}
			public String getImage() {
				  return image;
			}
			public void setImage(String image) {
					this.image = image;
			}
			public String getRemake() {
					return remake;
			}
			public void setRemake(String remake) {
					this.remake = remake;
			}
}

部分图示:
在这里插入图片描述

2.3.2DAO层数据访问对象层

此层是编写数据操作的接口(进行CRUD即增删改查)层,mybatis就是数据访问对象层的框架,而现在对于数据操作往往习惯于给一个数据访问操作的接口给到使用者,而使用者不需要了解其实现的原理,哈哈注意其实这是接口的概念,学习了mybtais应该有所体会,都是以接口的方式开发数据访问层,当然作为开发者,我们还是要知道原理的,而mybatis开发依赖的就是mapper中文意思是映射这种模式实现的,在开发模式设计中即是使用代理模式,我们往往把mapper接口作为代理对象,所以我们常常说mapper层和dao层可以默认是同样的层,或是细分,将mapper分至下一级 ,还是看需求来分级。

本案例使用了mybatis的注解映射对应SQL语句的方法实现了查询所有的书籍和查询User对象实例的登录名密码的操作,创建路径为src下org.fkit.mapper包下的UserMapper和BookMapper代码如下:

package org.fkit.mapper;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.fkit.domain.User;
			
		/**
	     * UserMapper接口
	     **/
  public interface UserMapper {
				
		/**
		* 根据登录名和密码查询用户
		* @param String loginname
		* @param String password
		* @return 找到返回User对象,没有找到返回null
		**/
		@Select("select * from tb_user where loginname = #{loginname} and password = #{password}")
		User findWithLoginnameAndPassword(@Param("loginname")String loginname,
		@Param("password") String password);
			
		}
package org.fkit.mapper;
			
import java.util.List;
import org.apache.ibatis.annotations.Select;
import org.fkit.domain.Book;
			
		/**
		 * 查询所有图书
		 * @return 图书对象集合
		 **/
		public interface BookMapper {
			@Select("select * from tb_book")
			List<Book> findAll();
		}

2.4服务层功能实现

编写service层即我们常说的三层架构中的业务逻辑层完成对用户的服务操作,我们常常在这创建数据访问对象层的实例并在此层完成实际业务需求
本案例在org.fkit.service层创建UserService和BookService接口,和在org.fkit.serive.impl层下创建UserServiceImpl和BookServiceImpl实现类加不加这层包是习惯,有这一层是方便运维和统一看实现类,实现类也可以放service包里,不多说看代码:

package org.fkit.service;
				
import org.fkit.domain.User;
				
			/**
			 * User服务层接口
			 */
			public interface UserService {
				/**
			     * 判断用户登录
				 * @param String loginname
				 * @param String password
				 * @return 找到返回User对象,没有找到返回null
				 */
				User login(String loginname,String password);
			}
package org.fkit.service;

import java.util.List;
import org.fkit.domain.Book;
				
			/**
		      *  Book服务层接口
			 */
			public interface BookService {
				   /**
				    * 查找所有图书
				    * @return Book对象集合
				    */
					List<Book> getAll();
			}
org.fkit.service.Impl层下实现类代码:	
package org.fkit.service.impl;

import org.fkit.domain.User;
import org.fkit.mapper.UserMapper;
import org.fkit.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
				
				
			/**
		  	 * User服务层接口实现类
			 * @Service("userService")用于将当前类注释为一个Spring的bean,名为userService
			 */
			@Service("userService")
			public class UserServiceImpl implements UserService {
					/**
					 * 自动注入UserMapper
					 */
				@Autowired
				public UserMapper userMapper;
					
				 /**
				  * UserService接口login方法实现
				  * @see { UserService }
				 */
				@Override
				public User login(String loginname, String password) {
						return userMapper.findWithLoginnameAndPassword(loginname, password);
				     }
			   }	
 package org.fkit.service.impl;

import java.util.List;
import org.fkit.domain.Book;
import org.fkit.mapper.BookMapper;
import org.fkit.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
				/**
				 * Book服务层接口实现类
				 * @Service("bookService")用于将当前类注释为一个Spring的bean,名为bookService
				 **/
			 @Service("bookService")
		    public class BookSerivceImpl implements BookService {
				 /**
				 * 自动注入BookMapper
				  */
				 @Autowired
				  private BookMapper bookMapper;
				
					@Override
					public List<Book> getAll() {
						return  bookMapper.findAll();
					}
					
			}	

部分图解:在这里插入图片描述
在这里插入图片描述

2.5控制层功能实现

此处创建j2ee五层架构中控制层,即Controller,而springmvc框架则属于这一层通过在j2ee的配置文件web.xml配置前端控制器与handler处理器和处理器适配器交互,再同视图解析器交互,通过model对象与视图层交互,再通过渲染的方式生成我们看见的客户端的静态页面即html页面,话不多说就如Lunix创始人lunis所说show me the code!

上代码:

  • 在src路径下创org.fkit.controller包,再在包路径下创UserController、BookController、登录跳转控制器类FormController,详见下方:
    Book控制器:
		package org.fkit.controller;

		import org.fkit.service.BookService;
		import org.springframework.beans.factory.annotation.Autowired;
		import org.springframework.beans.factory.annotation.Qualifier;
		import org.springframework.stereotype.Controller;
		import org.springframework.ui.Model;
		import org.springframework.web.bind.annotation.RequestMapping;
		
		import java.util.List;
		
		import org.fkit.domain.Book;
		
		/**
		 * 获取书详情的控制器
		 */
		@Controller
		public class BookController {
			/**
			 *自动注入BookService
			 */
			@Autowired
			@Qualifier("bookService")
			private BookService bookService;
			/**
			 * 处理main请求
			 */
			@RequestMapping(value="main")
			public String main(Model model){
				//获取所有图书集合
				List<Book> book_list=bookService.getAll();
				//将图书集合添加到model当中
				model.addAttribute("book_list", book_list);
				//跳转到main页面
				return "main";
			}
		}

User控制器:

 
package org.fkit.controller;
import javax.servlet.http.HttpSession;
import org.fkit.domain.User;
import org.fkit.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
		
		/**
		 * 处理用户请求控制器
		 */
		@Controller
		public class UserController {
			/**
			 * 自动注入UserSerivce
			 */
			@Autowired
			@Qualifier("userService")
			private UserService userService;
			/**
			 * 处理/login请求
			 */
			@RequestMapping(value="/login")
			public ModelAndView login(String loginname,String password,
				ModelAndView mv,
				HttpSession session){
					//根据用户名和密码来查找用户,判断用户登录
					User user=userService.login(loginname, password);
					if(user!=null){
						//登录成功,将user对象设置到HttpSession作用域中
						session.setAttribute("user", user);
						//转发到main请求
						mv.setView(new RedirectView("/fkbookapp/main"));
					}else{
						//登录失败,设置失败提醒信息,并跳转到登录页面
						mv.addObject("message", "登录名或者密码错误,请重新输入!");
						mv.setViewName("loginForm");
					}
					return mv;
				
			}
			
		}

Form控制器:

package org.fkit.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
			
		/**
		 * 动态页面跳转控制器
		 */
		@Controller
		public class FormController {
				@RequestMapping(value="/{formName}")
				public String loginForm(@PathVariable String formName){
					//动态跳转页面
					return formName;
				}
		}

在这里插入图片描述

2.6书写jsp页面即三层架构里面的视图层

从我们上面的spring-mvc配置文件中,我们注明了我们的视图解析器会解析项目容器中前缀为/WEB-INF/content/,后缀为.jsp页面下的页面,具体页面由Controller层返回的值决定,就是我们的前端页面需要放置项目路径下的/WebContent/WEB-INF/content的jsp页面,而此处其它地方的配置文件有可能使用/WebContent/WEB-INF/pages,是一样的,只是由于习惯还有思维方面不同给出命名的不同,本案例使用/WebContent/WEB-INF/content,jsp页面获取值使用了el表达式,代码如下:

2.6.1登录页面:

 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!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>登录页面</title>
</head>
     <body>
			<h3>登录页面</h3>
			<form action="login" method="post">
				<font color="red">${requestScope.message }</font>
			     <table>
			         <tr>
			         	<td><label>登录名: </label></td>
			             <td><input type="text" id="loginname" name="loginname" ></td>
			         </tr>
			         <tr>
			         	<td><label>密码: </label></td>
			             <td><input type="password" id="password" name="password" ></td>
			         </tr>
			         <tr>
			             <td><input type="submit" value="登录"></td>
			         </tr>
			    </table>
		 </form>
	</body>
</html>

带有用户状态和书籍详情的主页面:

2.6.2用户状态和书籍详情的主页面

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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>首页</title>
  <style type="text/css">
		table{border-collapse:collapse;border-spacing:0;border-left:1px solid #888;border-top:1px solid #888;background:#efefef;}
		th,td{border-right:1px solid #888;border-bottom:1px solid #888;padding:5px 15px;}
		th{font-weight:bold;background:#ccc;}
	</style>
</head>
	<body>
	欢迎[${sessionScope.user.username }]访问
		<br>
		 <table border="1">
			<tr>
				<th>封面</th><th>书名</th><th>作者</th><th>价格</th>
				</tr>
					<c:forEach items="${requestScope.book_list }" var="book">
						<tr>
							<td><img src="images/${book.image }" height="60"></td>
							<td>${book.name }</td>
							<td>${book.author }</td>
							<td>${book.price }</td>
						</tr>
					</c:forEach>
			</table>
	</body>
</html>

部分jsp页面和目录结构如下图:在这里插入图片描述

2.7部署到已绑定的tomcat运行*

在这里插入图片描述
接下来:
在这里插入图片描述当然最好是先选next确定部署了项目进tomcat:
在这里插入图片描述

2.8开浏览器通过访问本地端口项目路径访问

第一步,使用本地端口号访问项目,看tomcat的setting设置里的设置,一般默认为8080,用错端口也会报错404错误说找不到服务器,具体看实际部署使用的tomcat开启时候使用的端口号,本案例是用8080端口,一开始用8080端口访问项目名进去,即http://localhost:8080/fkbookapp/,没加具体映射路径的话,肯定是404的,因为j2ee的web.xml配置,默认访问的首页名字是不在web-inf下的index页面,而加了loginForm之后则会访问登录页面,即http://localhost:8080/fkbookapp/loginForm。如果加了还报404看具体信息,一般是由于代码打错或者少了controller注解或者spring-config没有配置自动扫描,控制器名字和访问路径映射不一致,或者return的视图,名字和jsp页面不一致,大小写错误等等,细节问题又或者是spring-mvc配置文件没有注入视图解析器对象,又或者没有指定访问前缀后缀,导致没有找到解析页面,又或者是tomcat实际没有部署到项目,我们可以先在servers那个找到tomcat先停了,再右键选clean,再把部署项目移除,再右键open进入tomcat设置路径,把servce location从第一个变第二个,设置deploy path文件名,然后重新保存ctrl+s或者左上角图标,重新发布,即run项目和前面步骤一致,还不行进tomcat硬盘里的位置,找到和deploy path一样名字的文件夹,然后看有没有自己要运行的项目,项目里面是不是空的,排除问题,到这一步一般404的问题是什么都能找出来,并且排除掉解决掉。

第二步,正常显示登陆页面的时候输入数据库保存的username和password,不要输错,然后点击登陆,如果报500错误,说数据库连接错误,先排除db.properties里面的键和值是不是正确的,这一步重点关注账号密码是否正确,如果正确使用,小心值后面是不是留有空格,如果有空格也会加载配置文件错误导致错误500,先每个值后面都用鼠标删填写的值后面,不留空格,重新发布访问。此处如果不确定,是不是包名对应的url路径打错,建议先在桌面创建一个txt文本,复制粘贴,进去保存,先测试是否是空格导致,如果还不行先百度mysql版本的包url有没有打错,即url对应的值里三个/前面包名是否错,再检查斜杆是否反了,然后用sqlyog等这种可视化的处理数据库工具检查配置文件里,///后面填的mysql里面的数据库是否有,有无大小写不一致问题,总之细心查看,确保这里无误后运行,一般没有问题。当然还有其它的500错误出现的可能性,可能出现问题可能是在与mybatis框架的上使用上,具体看开发工具的控制台,报错什么,具体cause by后面写什么,常见错误有比如mapper层的mapper接口访问方法没配置,如果是用mapper包下面放xml映射,需保证xml和接口处于同级目录,即都mapper包下,本案例使用的是注解的方式,所有检查的是spring-config自动扫描是否开了,mapper接口的操作方法上面注解是否加了。排查即可解决,而具体到此案例FormController也会有错误出现500的情况,即映射路径和传参写的不一样,常见问题如本案例映射路径为@RequestMapping(value="/{formName}"),而参数写了formName,即public String loginForm(@PathVariable String formName1)这种错误很细微,可能不小心打错了出现(return和formName参数不一致的情况,编译不过,在运行前可排查出来)

此案例当出现校验失败,原因可能是你的用户名密码输入和数据库插入的不一致,或者就单单只是填了其中一个就点确认了,当然此案例还有一个可能出现错误的地方在UserMapper传username和password参数前忘记加了@Param,注解里面的是不是对应你要拿的东西的真正映射名字,即你的@Param是不是和jsp页面里面的input标签的name属性值一致,不一致会出现校验失败。例如UserController类里,你的login方法username,password是正常的,但是jsp页面里面input输入文本框的name属性不是出现了不一致,大小写错误,或者加多数字等问题,就会返回信息写登录失败。

第三步,前面都没错误之后,点击登录后正常显示页面后面附了图。如果欢迎用户名处出现乱码,排查原因检查你的jsp指定编码问题,是否是utf-8,因为浏览器编码默认是请求方式都是不同的有得是根据操作系统,有的是有特定的,所以检查不能单一检查和思考,所以确保所有都设置UTF-8是最稳妥的,当然有些utf-8写法也不一样,有的地方,中间不需要杠,所以请特殊情况特殊百度,当然还有j2ee的配置即web.xml是否有设置编码过滤,是否指定的语言也是utf-8。而出现jsp页面光有信息没有图片的情况,则排查先排查资源文件位置放哪了,是不是在webContent容器下忘记放资源图片啦,或者放了,名字和数据保存的封面属性的名字不一样,或者是不是目录所在的目录级别有问题导致加载不出来,因为本案例主要考察点是整合框架,而不在前端页面所以,本案例webContent下创建images,把资源文件放进去,名字对应数据库里存的名字即可显示相应的图片,而没有把资源文件放在web-inf里面,至于放不放,则在于想渲染快一点还是所谓的要求保证资源文件的安全。而当把资源文件放web-inf的时候就别忘了在springmvc配置里面配置资源指定放行了,又或者是在js样式上设置路径。

错误排查总结:
可以debug看看问题先看数据文件名称是否对应,快速扫过结构是否有问题,看配置文件,切记注解模式,一定要配置扫描!看代码导的包,看文件放的位置,之后才是看代码,看注解,看映射,具体看方法作用范围和参数等,再到环境版本问题,之后才是细节问题,百分之90的错都是打错。这样排查百分之90都能排查出来。

访问 流程图:
1.在这里插入图片描述2.在这里插入图片描述3.在这里插入图片描述4.在这里插入图片描述结语:
还是把基础到牢固,理解为什么要整合?
即使没能手撕框架,也应该对于框架特性,概括一句说应该是要做到应用层面的东西必须清晰,即用法,写了会影响到之后开发的什么东西。其注解或者配置了熟于心,有人会说现在都用maven项目了,但是maven也有它的错误,你怎么能说你解决了百分之90的错误呢,其实maven项目也不外乎jar包的版本,是否有冲突,环境版本特性,父子工程依赖关系,依赖是否正确配置,作用范围,即pom文件到底有没有真正意味上的配好配对,加载上,是否连接到仓库,有没有下载依赖成功。
而百分之10的问题在于上线环境和客户的环境是一个变量,但终究更多的也是版本特性问题。百分之90的问题在于我们的基础不扎实,到底配置文件怎么配,要用几个,配什么,怎么配,框架到底怎么用。

总结一下listener,servlet,filter是j2ee的三大组件,请配web工程的web.xml,这个web项目的核心,而框架整合的核心是什么?

  1. 是Spring框架,所以web应用想要框架请在web.xml的j2ee加载的配置文件里面配置Spring容器,请在这里配置加载spring配置文件的位置即一般我们说的全局变量配置文件applicationContext(即通过监听的方式),通过监听器监听srping容器是否创建,如果没有spring容器,则各个框架就是一盘散沙。

  2. 整合案例中需要将mybatis 交给Spring管理 ,Spring生产对象,那mybatis的配置自然是在Spring的全局变量里,service层是依赖于mapper层的,解决mapper的数据操作方法的,是一个算法的过渡层,或者说是处理逻辑,不直接参与数据连接,所以实际上service层没有什么配置的,其也是配置在spring, 由于此处service没有复杂逻辑和一些切入方式,所以可以和这个mybatis整合在一个xml中,也可以将二则分开,然后将mybatis的xml,配置进applicationContext.xml中,

  3. springmvc是spring家族的一个针对MVC交互层面使用的,配置往往是拿出来单独配置,因为它处理的是视图解析和前端页面交互的功能所以这样的配置设计逻辑。
    springmvc核心是前端控制器,调用的是ServletAPI,当然也是一个servlet,那它自然对应servlet配置。

就是mybatis主动去整合spring的,就是通过spring的依赖注入,实例SqlSessionFactoryBean和配置数据源以及数据库所需配置事务管理等即实现mybatis的数据库操作,最多配置事务切面,基本就配置完了。所以剩下的就是细节,注解用没用,用得对不对,有没有扫描,有没倒错同名包,前后端传递的对象或者属性对不对应,基本大的问题就没有了, 再回归到为什么mybatis和springmvc分开配置文件,其实这是为了更好的开发软件,数据操作配置数据操作,视图解析交互配置视图解析,大家彼此共存,互不干涉,出了问题好排查,不会那么乱,这就是为什么又框架存在的原因,同时对象全部由spring创建,利于维护和管理,这就是回到软件设计的初心,高扩展,高维护,降低开发部署的成本。也是spring为什么这么火的原因。充分体现了软件思维,就是分解,模式识别,模式概括和抽象,最后才是算法,所以不管以后到底有多少servlet,有多少配置文件,又或者有其他玩法,还是要回到本质有套路有分解有目标连续化解,这是数学的精髓也是软件开发的精髓。此文档和文件仅供学习,不做商用,由于本书没有配套视频,而且现在是疫情期间,本书也是学校购买的教材,除了问题也没有老师现场指导,耗费时间巨大,但也大大加深了自己的理解认知,书都是说怎么是对的,但是没有说怎么是错的,为什么出现这种错误,错误怎么解决,怎么排查,本文献给本书共同学习者参考也希望留于以后自己复习使用或是对于ssm整合有疑惑的人士参考,无意侵权,更无意误导。如本文有错误或者是本人理解知识点上的错误,请不抨击,不恶语相向,积极交流共同促进。感谢看到最后,万分感谢,如本书的作者或者书商认为有侵权行为,请联系下架!小小计算机学生留,致敬每位it追梦人!!!
源码资源下载地址:
点击跳转
https://pan.baidu.com/s/1FApbz3UneNKhXOUD6bdpDA,提取码为:h4yu
如果上面链接失效,这有原书的源码,里面有jar包,复制导入就可以,软件环境则自行下载,其余步骤跟着本博客指引即可http://www.broadview.com.cn/book/51
在此特别声明并无做推广,本人是普通在校大学生,只是学校的教材是这个,分享出来也是仅供有困惑的同学思考整合ssm参考

如有认可本文或者本人的在此在此表示感谢。。。希望每个追梦人悄悄拔尖,惊艳所有人。

想了解使用idea开发maven项目整合ssm父子工程项目请看以下我的另外一篇博客:
https://blog.csdn.net/xtho62/article/details/106941654

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页