ssm整合

1、父工程依赖管理
  • 版本声明
 <properties>
        <!-- 声明属性,对 Spring 的版本进行统一管理 -->
        <atguigu.spring.version>4.3.20.RELEASE</atguigu.spring.version>
        <!-- 声明属性,对 SpringSecurity 的版本进行统一管理 -->
        <atguigu.spring.security.version>4.2.10.RELEASE</atguigu.spring.security.version>
 </properties>
  • 依赖管理
 <dependencyManagement>
      <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>${atguigu.spring.version}</version>
            </dependency>
 </dependencyManagement>
2、Mybatis逆向工程
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.crowd</groupId>
    <artifactId>atcrowdfunding06-common-reverse</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
    </dependencies>
    <!-- 控制 Maven 在构建过程中相关配置 -->
    <build>
        <!-- 构建过程中用到的插件 -->
        <plugins>
            <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.0</version>
                <!-- 插件的依赖 -->
                <dependencies>
                    <!-- 逆向工程的核心依赖 -->
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.2</version>
                    </dependency>
                    <!-- 数据库连接池 -->
                    <dependency>
                        <groupId>com.mchange</groupId>
                        <artifactId>c3p0</artifactId>
                        <version>0.9.2</version>
                    </dependency>
                    <!--MySQL 驱动 -->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.11</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

配置文件 generatorConfig.xml

<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!-- mybatis-generator:generate -->
    <context id="atguiguTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是;false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--数据库连接的信息: 驱动类、 连接地址、 用户名、 密码 -->
        <jdbcConnection
                driverClass="com.mysql.cj.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/project_crowd?serverTimezone=GMT"
                userId="root"
                password="136414">
        </jdbcConnection>
        <!-- 默认 false, 把 JDBC DECIMAL 和 NUMERIC 类型解析为 Integer, 为 true 时把
        JDBC DECIMAL
        和 NUMERIC 类型解析为 java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- targetProject:生成 Entity 类的路径 -->
        <javaModelGenerator targetProject=".\src\main\java"
                            targetPackage="com.atguigu.crowd.entity">
            <!-- enableSubPackages:是否让 schema 作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- targetProject:XxxMapper.xml 映射文件生成的路径 -->
        <sqlMapGenerator targetProject=".\src\main\java"
                         targetPackage="com.atguigu.crowd.mapper">
            <!-- enableSubPackages:是否让 schema 作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>
        <!-- targetPackage: Mapper 接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetProject=".\src\main\java"
                             targetPackage="com.atguigu.crowd.mapper">
            <!-- enableSubPackages:是否让 schema 作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>
        <!-- 数据库表名字和我们的 entity 类对应的映射指定 -->
        <table tableName="t_admin" domainObjectName="Admin"/>
    </context>
</generatorConfiguration>
3、Spring整合Mybatis
  • 目标:adminMapper 通过 IOC 容器装配到当前组件中后,就可以直接调用它的方法,享受 到框架给我们提供的方便
image-20200516144136253
  • 思路
image-20200516144305498
  • 代码

在子工程中加入搭建环境所需要的具体依赖

<!--MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--MyBatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<!--MyBatis 与 Spring 整合 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>

准备 jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver 
jdbc.url=jdbc:mysql://localhost:3306/project_crowd?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT
jdbc.username=root
jdbc.password=136414

创建 Spring 配置文件专门配置 Spring 和 MyBatis 整合相关

spring-persist-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-4.3.xsd">

    <!-- 加载外部属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
    </bean>

    <!-- 配置SqlSessionFactoryBean整合MyBatis -->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 指定MyBatis全局配置文件位置 -->
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
        <!-- 指定Mapper.xml配置文件位置 -->
        <property name="mapperLocations" value="classpath:mybatis/mapper/*Mapper.xml"/>
        <!-- 装配数据源 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 配置MapperScannerConfigurer来扫描Mapper接口所在的包 -->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.atguigu.crowd.mapper"/>
    </bean>
</beans>
4、Spring整合SpringMVC
  • 启动过程
image-20200516160517460
  • 环境搭建

加入依赖

<dependency>
    <groupId>org.springframework</groupId> 
    <artifactId>spring-webmvc</artifactId> 
</dependency>

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app
        version="4.0"
        xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
        	 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
    <!-- 配置 ContextLoaderListener 加载 Spring 配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-persist-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 配置 CharacterEncodingFilter 解决 POST 请求的字符乱码问题 -->
    <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>
        <!-- 强制请求进行编码 -->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!-- 强制响应进行编码 -->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- 配置 SpringMVC 的前端控制器 -->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 以初始化参数的形式指定 SpringMVC 配置文件的位置 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-web-mvc.xml</param-value>
        </init-param>
        <!-- 让 DispatcherServlet 在 Web 应用启动时创建对象、初始化 -->
      <!-- 默认情况:Servlet 在第一次请求的时候创建对象、初始化 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--MapallrequeststotheDispatcherServletforhandling-->
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <!--DispatcherServlet 映射的 URL 地址 --> 
        <!-- 大白话:什么样的访问地址会交给 SpringMVC 来处理 --> 
        <!-- 配置方式一:符合 RESTFUL 风格使用“/”-->
        <!--<url-pattern>/</url-pattern>-->
        <!-- 配置方式二:请求扩展名 -->
        <url-pattern>*.html</url-pattern>
        <url-pattern>*.json</url-pattern>
    </servlet-mapping>
</web-app>
  • 异常映射
  1. 作用

    统一管理项目中的异常

    抛出异常

    显示异常信息

    • 普通请求:在页面上显示异常信息

    • Ajax 请求:返回 JSON 数据

  2. 异常映射的工作机制

image-20200516163629418

创建异常处理器类、异常处理器类代码(优化后)

package com.atguigu.crowd.mvc.config;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import com.atguigu.crowd.constant.CrowdConstant;
import com.atguigu.crowd.exception.AccessForbiddenException;
import com.atguigu.crowd.exception.LoginFailedException;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import com.google.gson.Gson;
// @ControllerAdvice表示当前类是一个基于注解的异常处理器类
@ControllerAdvice
public class CrowdExceptionResolver {
	// @ExceptionHandler将一个具体的异常类型和一个方法关联起来
	private ModelAndView commonResolve(	
			// 异常处理完成后要去的页面
			String viewName, 
			
			// 实际捕获到的异常类型
			Exception exception, 
			
			// 当前请求对象
			HttpServletRequest request, 
			
			// 当前响应对象
			HttpServletResponse response) throws IOException {
		
		// 1.判断当前请求类型
		boolean judgeResult = CrowdUtil.judgeRequestType(request);
		
		// 2.如果是Ajax请求
		if(judgeResult) {
			
			// 3.创建ResultEntity对象
			ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
			
			// 4.创建Gson对象
			Gson gson = new Gson();
			
			// 5.将ResultEntity对象转换为JSON字符串
			String json = gson.toJson(resultEntity);
			
			// 6.将JSON字符串作为响应体返回给浏览器
			response.getWriter().write(json);
			
			// 7.由于上面已经通过原生的response对象返回了响应,所以不提供ModelAndView对象
			return null;
		}
		
		// 8.如果不是Ajax请求则创建ModelAndView对象
		ModelAndView modelAndView = new ModelAndView();
		
		// 9.将Exception对象存入模型
		modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);
		
		// 10.设置对应的视图名称
		modelAndView.setViewName(viewName);
		
		// 11.返回modelAndView对象
		return modelAndView;
	}

}

基于注解的异常映射配置

<!-- 配置基于XML的异常映射 -->
	<bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<!-- 配置异常类型和具体视图页面的对应关系 -->
		<property name="exceptionMappings">
			<props>
				<!-- key属性指定异常全类名 -->
				<!-- 标签体中写对应的视图(这个值要拼前后缀得到具体路径) -->
				<prop key="java.lang.Exception">system-error</prop>
				<prop key="com.atguigu.crowd.exception.AccessForbiddenException">admin-login</prop>
			</props>
		</property>
	</bean>
	
	<!-- 配置view-controller,直接把请求地址和视图名称关联起来,不必写handler方法了 -->
	<!-- 
		@RequestMapping("/admin/to/login/page.html")
		public String toLoginPage(){
			return "admin-login";
		}
	 -->
	<mvc:view-controller path="/admin/to/login/page.html" view-name="admin-login"/>
	<mvc:view-controller path="/admin/to/main/page.html" view-name="admin-main"/>

  • 拦截器

拦截器配置

	<!-- 注册拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<!-- mvc:mapping配置要拦截的资源 -->
			<!-- /*对应一层路径,比如:/aaa -->
			<!-- /**对应多层路径,比如:/aaa/bbb或/aaa/bbb/ccc或/aaa/bbb/ccc/ddd -->
			<mvc:mapping path="/**"/>
			
			<!-- mvc:exclude-mapping配置不拦截的资源 -->
			<mvc:exclude-mapping path="/admin/to/login/page.html"/>
			<mvc:exclude-mapping path="/admin/do/login.html"/>
			<mvc:exclude-mapping path="/admin/do/logout.html"/>
			
			<!-- 配置拦截器类 -->
			<bean class="com.atguigu.crowd.mvc.interceptor.LoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>

拦截器类

public class LoginInterceptor extends HandlerInterceptorAdapter {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
	}

}
5、日志系统
  • 重要意义:系统在运行过程中出了问题就需要通过日志来进行排查,所以我们在上手任何新技 术的时候,都要习惯性的关注一下它是如何打印日志的。
  • 技术选型
image-20200516154147654
  • 不同日志系统的整合

img

img

  • 更换框架的日志系统

第一步:排除 commons-logging

<dependecies>  
		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
</dependecies>

第二步:加入转换包

<dependecies>      
       <!-- 日志 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </dependency>
        <!-- 其他日志框架的中间转换包 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
        </dependency> 
</dependecies>  

第三步:logback 配置文件

<configuration debug="true"> <!-- 指定日志输出的位置 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式 -->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体 内容、换行 -->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
        </encoder>
    </appender>
    <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR-->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
    <root level="INFO">
        <!-- 指定打印日志的 appender,这里通过“STDOUT”引用了前面配置的 appender-->
        <appender-ref ref="STDOUT"/>
    </root>
    <!-- 根据特殊需求指定局部日志级别 -->
    <logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
</configuration>
6、统一规范
  1. test范围是指测试范围有效,在编译和打包时都不会使用这个依赖
  2. compile范围是指编译范围内有效,在编译和打包时都会将依赖存储进去
  3. provided依赖,在编译和测试过程中有效,最后生成的war包时不会加入 例如: servlet-api,因为servlet-api tomcat服务器已经存在了,如果再打包会冲突
  4. runtime在运行时候依赖,在编译时候不依赖
  5. 默认依赖范围是compile
  • 封装Ajax同意返回数据
package com.atguigu.crowd.util;

/**
 * 统一整个项目中Ajax请求返回的结果(未来也可以用于分布式架构各个模块间调用时返回统一类型)
 * @author Lenovo
 *
 * @param <T>
 */
public class ResultEntity<T> {
	
	public static final String SUCCESS = "SUCCESS";
	public static final String FAILED = "FAILED";
	
	// 用来封装当前请求处理的结果是成功还是失败
	private String result;
	
	// 请求处理失败时返回的错误消息
	private String message;
	
	// 要返回的数据
	private T data;
	
	/**
	 * 请求处理成功且不需要返回数据时使用的工具方法
	 * @return
	 */
	public static <Type> ResultEntity<Type> successWithoutData() {
		return new ResultEntity<Type>(SUCCESS, null, null);
	}
	
	/**
	 * 请求处理成功且需要返回数据时使用的工具方法
	 * @param data 要返回的数据
	 * @return
	 */
	public static <Type> ResultEntity<Type> successWithData(Type data) {
		return new ResultEntity<Type>(SUCCESS, null, data);
	}
	
	/**
	 * 请求处理失败后使用的工具方法
	 * @param message 失败的错误消息
	 * @return
	 */
	public static <Type> ResultEntity<Type> failed(String message) {
		return new ResultEntity<Type>(FAILED, message, null);
	}
	
	public ResultEntity() {
		
	}

	public ResultEntity(String result, String message, T data) {
		super();
		this.result = result;
		this.message = message;
		this.data = data;
	}

	@Override
	public String toString() {
		return "ResultEntity [result=" + result + ", message=" + message + ", data=" + data + "]";
	}

	public String getResult() {
		return result;
	}

	public void setResult(String result) {
		this.result = result;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

}

  • 判断是否Ajax请求
public static boolean judgeRequestType(HttpServletRequest request) {
		
		// 1.获取请求消息头
		String acceptHeader = request.getHeader("Accept");
		String xRequestHeader = request.getHeader("X-Requested-With");
		
		// 2.判断
		return (acceptHeader != null && acceptHeader.contains("application/json"))
				
				||
				
				(xRequestHeader != null && xRequestHeader.equals("XMLHttpRequest"));
	}

essage() {
return message;
}

public void setMessage(String message) {
	this.message = message;
}

public T getData() {
	return data;
}

public void setData(T data) {
	this.data = data;
}

}


* 判断是否Ajax请求

```java
public static boolean judgeRequestType(HttpServletRequest request) {
		
		// 1.获取请求消息头
		String acceptHeader = request.getHeader("Accept");
		String xRequestHeader = request.getHeader("X-Requested-With");
		
		// 2.判断
		return (acceptHeader != null && acceptHeader.contains("application/json"))
				
				||
				
				(xRequestHeader != null && xRequestHeader.equals("XMLHttpRequest"));
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值