A01 互联网O2O平台开发.txt

UP 返回
该项目为互联网O2O平台开发,视频地址:D:\实战JAVA项目20套\Java互联网项目教学\互联网O2O平台开发
					经过去重路径变为:H:\视频教程\53套JAVA技术提升及架构精华课\46.第四十六套 ssm到spring boot开发校园商铺平台(2021/8/14)
								 项目地址:D:\ProjectCodes\eclipse2019\o2o

A 项目初步搭建(视频01-04章)
1 eclipse创建maven项目
	首先需要在eclipse中配好jdk,maven和tomcat。在server窗口下右键新增server,然后选择对应的tomcat版本及目录即可
	
	File → MavenProject → 修改一下工作空间(这里用的D:\ProjectCodes) → maven-archetype-webapp→ 输入两个id(com.imooc o2o) → 完成
	
	项目此时是报错的,需要添加一个tomcat下的一个jar:项目右键属性 → java build path → libraries → add library → server runtime → 选择对应的tomcat → OK,不报错了
	
	此时项目还有一个警告,jre版本不匹配:去jar网页搜索maven-compile-plugin,复制dependency 放到pom.xml中(pom里添加plugins):
		<build>
		    <finalName>o2o</finalName>
		    		<plugins>
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>				这里去掉dependency标签,因为放在了插件里,与pom上面的依赖有区别
						<artifactId>maven-compiler-plugin</artifactId>
						<version>3.6.0</version>
						<configuration>
							<source>1.8</source>										configuration指明这个插件和jdk1.8联系在一起的
							<target>1.8</target>
							<encoding>UTF8</encoding>								指明编码
						</configuration>
					</plugin>
				</plugins>
		  </build>
	添加后maven update一下项目,就不报错了,同时会多出两个source目录
	
	手动添加source folder,src/test/resources,,右键项目属性,在java build path的source下,会发现每一个source folder都有对应的output folder,新加的只有一个default,他应该是target/test-classes
	记得先双击修改一下下面的contains test sources,将其从no改为yes,,然后双击output folder修改值保存(这个文件夹只是为了符合maven的规范而创建的)

	右键项目属性,选择project facets,设置Dynamic Web Module(版本越高解析js和页面的能力越强,但是高版本需要的jdk要求也更高),这里可以选择4.0
	实际测试发现选择了高版本以后无法再回到低版本,视频上演示的则是无论如何都无法切换(演示的eclipse有bug),此时可以进入项目路径的目录下:D:\ProjectCodes\eclipse2019\o2o\o2o\.settings
	里面有个文件org.eclipse.wst.common.project.facet.core.xml,通过手动修改<installed facet="jst.web" version="4.0"/>的value也可以实现修改,修改后refresh一下项目
	修改以后web.xml上的规范也需要修改:
		<web-app 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_3_1.xsd"
			version="3.1" metadata-complete="true">
		  <display-name>Archetype Created Web Application</display-name>
		</web-app>

	项目的webapp下有一个index.jsp,就是默认的首页。在server面板中选中对应的tomcat,右键选择Add and Remove,将当前项目添加进去,clean工程,再右键start服务器启

	此时即可通过 http://localhost:8080/o2o/index.jsp 访问默认的页面index.jsp
	http://localhost:8080/o2o 也可以访问到该页面。可以在web.xml中设置默认访问的页面,如果不设置就会默认去访问根路径下的index.jsp;如果设置了却找不到对应页面,就会报404错误
		<web-app 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_3_1.xsd"
			version="3.1" metadata-complete="true">
		  <display-name>Archetype Created Web Application</display-name>
		  <welcome-file-list>
		  	<!-- ▶▶▶ 设置默认的访问页面,从上往下依次找 -->
		  	<welcome-file>aa.jsp</welcome-file>
		  	<welcome-file>index.jsp</welcome-file>
		  </welcome-file-list>
		</web-app>

2 项目完善
	在src/mian/resources下右键创建两个source文件夹,命名为src/mian/resources/spring和src/mian/resources/mapper
	在下面的页面文件夹中,src/main/webapp下创建文件夹resources,用来存放静态文件(js, css, 图片等)。WEB-INF中的页面是无法从浏览器直接访问到的

	准备好数据库,并创建所有的实体类,接下来引入项目需要的jar,初步的pom文件内容如下:
			<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>com.dm</groupId>
			  <artifactId>o2o</artifactId>
			  <packaging>war</packaging>
			  <version>0.0.1-SNAPSHOT</version>
			  <name>o2o Maven Webapp</name>
			  <url>http://maven.apache.org</url>
			  	<properties>
					<spring.version>4.3.7.RELEASE</spring.version>		补上${spring.version}定义的值,用于和下面的spring版本对应
				</properties>
			  
			  <dependencies>
			    <dependency>
			      <groupId>junit</groupId>
			      <artifactId>junit</artifactId>
			      <version>4.12</version>
			      <scope>test</scope>						test表示只希望出现在测试环境中,这个项不填则默认为compile
			    </dependency>
			    	<!-- 日志 -->
					<!-- 实现slf4j接口并整合 -->
					<dependency>
						<groupId>ch.qos.logback</groupId>
						<artifactId>logback-classic</artifactId>
						<version>1.2.3</version>
					</dependency>
					<!-- Spring -->
					<!-- 1)包含Spring框架基本的核心工具类。Spring其他组件都要使用到这个包里的类,是其他组件的基本核心 -->
					<dependency>
						<groupId>org.springframework</groupId>
						<artifactId>spring-core</artifactId>
						<version>${spring.version}</version>
					</dependency>
					<!-- 2)这个jar文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行IOC/DI操作相关的所有类。如果应用只需要基本的IOC/DI支持,引入spring-core及spring-beans.jar文件就可以了 -->
					<dependency>
						<groupId>org.springframework</groupId>
						<artifactId>spring-beans</artifactId>
						<version>${spring.version}</version>
					</dependency>
					<!-- 3)这个jar文件为Spring核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,instrumentation组件以及校验Validation方面的相关类 -->
					<dependency>
						<groupId>org.springframework</groupId>
						<artifactId>spring-context</artifactId>
						<version>${spring.version}</version>
					</dependency>
					<!-- 4)这个jar文件包含Spring对.数据访问进行封装的所有类 -->
					<dependency>
						<groupId>org.springframework</groupId>
						<artifactId>spring-jdbc</artifactId>
						<version>${spring.version}</version>
					</dependency>
					<!-- 5)为JDBC、Hibernate、JDO、JPA等提供一致的声明式和编程式事务管理 -->
					<dependency>
						<groupId>org.springframework</groupId>
						<artifactId>spring-tx</artifactId>
						<version>${spring.version}</version>
					</dependency>
					<!-- 6)Spring web包含web应用开发时用到的核心类,包括自动载入WebApplicationContext特性的类,文件上传的类等-->
					<dependency>
						<groupId>org.springframework</groupId>
						<artifactId>spring-web</artifactId>
						<version>${spring.version}</version>
					</dependency>
					<!-- 7)SpringMVC的核心,包括DispatcherServlet等 -->
					<dependency>
						<groupId>org.springframework</groupId>
						<artifactId>spring-webmvc</artifactId>
						<version>${spring.version}</version>
					</dependency>
					<!-- 8)Spring test对JUNIT等测试框架的简单封装。这个依赖使用test,只希望在测试环境出现 -->
					<dependency>
						<groupId>org.springframework</groupId>
						<artifactId>spring-test</artifactId>
						<version>${spring.version}</version>
						<scope>test</scope>
					</dependency>
					
					<!-- Spring web,提供servlet服务-->
					<dependency>
						<groupId>javax.servlet</groupId>
						<artifactId>javax.servlet-api</artifactId>
						<version>3.1.0</version>
					</dependency> 
					<!-- json解析 -->
					<dependency>
						<groupId>com.fasterxml.jackson.core</groupId>
						<artifactId>jackson-databind</artifactId>
						<version>2.8.7</version>
					</dependency>
					<!-- Map工具类 对标准java Collection的扩展 spring-core.jar需commons-collections.jar -->
					<dependency>
						<groupId>commons-collections</groupId>
						<artifactId>commons-collections</artifactId>
						<version>3.2</version>
					</dependency>
					<!-- DAO: MyBatis -->
					<dependency>
						<groupId>org.mybatis</groupId>
						<artifactId>mybatis</artifactId>
						<version>3.4.2</version>
					</dependency>
					<dependency>
						<groupId>org.mybatis</groupId>
						<artifactId>mybatis-spring</artifactId>
						<version>1.3.1</version>
					</dependency>
					<!-- 数据库 -->
					<dependency>
						<groupId>mysql</groupId>
						<artifactId>mysql-connector-java</artifactId
						<version>5.1.37</version>
						<!-- <scope>runtime</scope> -->
					</dependency>
					<dependency>
						<groupId>c3p0</groupId>
						<artifactId>c3p0</artifactId>
						<version>0.9.1.2</version>
					</dependency>
			  </dependencies>
			  <build>
			    <finalName>o2o</finalName>
			    <plugins>
						<plugin>
							<groupId>org.apache.maven.plugins</groupId>
							<artifactId>maven-compiler-plugin</artifactId>
							<version>3.6.0</version>
							<configuration>
								<source>1.8</source>
								<target>1.8</target>
								<encoding>UTF8</encoding>
							</configuration>
						</plugin>
					</plugins>
			  </build>
			</project>

	其他配置文件参项目代码(视频2-6)
	2.1 在resources目录下创建jdbc.properties,内容为
		jdbc.driver=com.mysql.jdbc.Driver
		jdbc.url=jdbc:mysql://localhost:3306/o2o?useUnicode=true&characterEncoding=utf8
		jdbc.username=root
		jdbc.password=123654
	2.2 在resources目录下创建mybatis-config.xml,用于配置mybatis,内容为
		<?xml version="1.0" encoding="UTF-8" ?>
		<!DOCTYPE configuration
		  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
		  "http://mybatis.org/dtd/mybatis-3-config.dtd">
		<configuration>
			<!-- 配置全局属性 -->
			<settings>
				<!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
				<setting name="useGeneratedKeys" value="true" />
		
				<!-- 使用列标签替换列别名  默认:true -->
				<setting name="useColumnLabel" value="true" />
		
				<!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
				<setting name="mapUnderscoreToCamelCase" value="true" />
				<!-- 打印查询语句 -->
				<setting name="logImpl" value="STDOUT_LOGGING" />
			</settings>
		</configuration>
	2.3 在resources下创建spring文件夹,spring下创建spring-dao.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">					这一大坨表示命名空间等配置,固定的写法
			<!-- 配置整合mybatis过程 -->
			<!-- 1.配置数据库相关参数properties的属性:${url} -->
			<context:property-placeholder location="classpath:jdbc.properties"/>

			<!-- 2.数据库连接池 -->
			<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
				<!-- 配置连接池属性 -->
				<property name="driverClass" value="${jdbc.driver}" />
				<property name="jdbcUrl" value="${jdbc.url}" />
				<property name="user" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
		
				<!-- c3p0连接池的私有属性 -->
				<property name="maxPoolSize" value="30" />
				<property name="minPoolSize" value="10" />
				<!-- 关闭连接后不自动commit -->
				<property name="autoCommitOnClose" value="false" />
				<!-- 获取连接超时时间 -->
				<property name="checkoutTimeout" value="10000" />
				<!-- 当获取连接失败重试次数 -->
				<property name="acquireRetryAttempts" value="2" />
			</bean>
		
			<!-- 3.配置SqlSessionFactory对象 -->
			<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
				<!-- 注入数据库连接池 -->
				<property name="dataSource" ref="dataSource" />
				<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
				<property name="configLocation" value="classpath:mybatis-config.xml" />
				<!-- 扫描entity包 使用别名 -->
				<property name="typeAliasesPackage" value="com.imooc.myo2o.entity" />
				<!-- 扫描sql配置文件:mapper需要的xml文件 -->
				<property name="mapperLocations" value="classpath:mapper/*.xml" />
			</bean>
		
			<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
			<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
				<!-- 注入sqlSessionFactory -->
				<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
				<!-- 给出需要扫描Dao接口包 -->
				<property name="basePackage" value="com.imooc.myo2o.dao" />
			</bean>
		</beans>
	2.4 在spring下创建spring-service.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: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/context
		    http://www.springframework.org/schema/context/spring-context.xsd
		    http://www.springframework.org/schema/tx
		    http://www.springframework.org/schema/tx/spring-tx.xsd">
		    <!-- 扫描service包下所有使用注解的类型 -->
		    <context:component-scan base-package="com.imooc.myo2o.service" />
		
		    <!-- 配置事务管理器 -->
		    <bean id="transactionManager"
		        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		        <!-- 注入数据库连接池 -->
		        <property name="dataSource" ref="dataSource" />
		    </bean>
		
		    <!-- 配置基于注解的声明式事务 -->
		    <tx:annotation-driven transaction-manager="transactionManager" />
		</beans>
	2.5 在spring下创建spring-web.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-3.2.xsd">
			<!-- 配置SpringMVC -->
			<!-- 1.开启SpringMVC注解模式 -->
			<mvc:annotation-driven />
		
			<!-- 2.静态资源默认servlet配置 
				(1)加入对静态资源的处理:js,gif,png 
				(2)允许使用"/"做整体映射 -->
			<mvc:resources mapping="/resources/**" location="/resources/" />
			<mvc:default-servlet-handler />
		
			<!-- 3.定义视图解析器 -->
			<bean id="viewResolver"
				class="org.springframework.web.servlet.view.InternalResourceViewResolver">
				<!-- 只要文件放在WEB-INF下,程序外部便不可以访问这里的文件,内部可以,所以使用这个文件夹可以保证安全,通过springDispacherServlet来进行转向,controller来分发到WEB-INF下的页面即可 -->
				<property name="prefix" value="/WEB-INF/html/"></property>
				<property name="suffix" value=".html"></property>
			</bean>

			<!-- 4.扫描web相关的bean -->
			<context:component-scan base-package="com.imooc.myo2o.web" />
		</beans>
	2.6 在web.xml中整合spring的相关配置
		<web-app 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_3_1.xsd"
			version="3.1" metadata-complete="true">
		  <display-name>Archetype Created Web Application</display-name>
		  <welcome-file-list>
		  	<!-- 设置默认的访问页面,从上往下依次找 -->
		  	<welcome-file>aa.jsp</welcome-file>
		  	<welcome-file>index.jsp</welcome-file>
		  </welcome-file-list>
		  <servlet>
		  	<servlet-name>spring-dispatcher</servlet-name>
		  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		  	<init-param>
		  		<param-name>contextConfigLocation</param-name>
		  		<!-- 这里就是将spring的配置文件组合到一起了 -->
		  		<param-value>classpath:spring/spring-*.xml</param-value>
		  	</init-param>
		  </servlet>
		  
		  <servlet-mapping>
		  	<servlet-name>spring-dispatcher</servlet-name>
		  	<!-- 默认匹配所有的请求 -->
		  	<url-pattern>/</url-pattern>
		  </servlet-mapping>
		</web-app>

	实际代码: (对应视频2-7)
	3.1 在包com.imooc.myo2o.entity下创建Area类,代码如下
		public class Area {
			private Long areaId;
			private String areaName;
			private String areaDesc;
			private Integer priority;
			private Date createTime;
			private Date lastEditTime;
			//省略get set
		}	
	3.2 在包com.imooc.myo2o.dao下创建AreaDao类,代码如下
		public interface AreaDao {
			List<Area> queryArea();
		}
	3.3 在resources下的mapper创建AreaDao.xml,内容如下
		<?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="com.imooc.myo2o.dao.AreaDao">
			<select id="queryArea" resultType="com.imooc.myo2o.entity.Area">
				SELECT
				area_id,
				area_name,
				area_desc,
				priority,
				create_time,
				last_edit_time
				FROM
				tb_area
				ORDER BY
				priority DESC
			</select>
		</mapper>
	3.4 在src/test/java下的com.imooc.myo2o下创建测试类BaseTest,内容如下
		/**
		 * 配置spring和junit整合,junit启动时加载springIOC容器 spring-test,junit
		 */
		@RunWith(SpringJUnit4ClassRunner.class)
		@ContextConfiguration({ "classpath:spring/spring-dao.xml" }) // 告诉junit spring配置文件的位置
		public class BaseTest {
		
		}
	3.5 在com.imooc.myo2o.dao下创建测试类ATest,内容如下
		public class AreaDaoTest extends BaseTest {
			@Autowired
			private AreaDao areaDao;
		
			@Test
			public void testBQueryArea() throws Exception {
				List<Area> areaList = areaDao.queryArea();
				assertEquals(4, areaList.size());
			}
		}
	接下来Junit运行testBQueryArea,即可成功!!!!

	补充其他模块:  (对应视频2-8)
	4.1 在包com.imooc.myo2o.service下创建service,代码如下
		public interface AreaService {
		
			List<Area> getAreaList();
		
		}
		在包com.imooc.myo2o.service.Impl下创建实现类,代码如下
		@Service
		public class AreaServiceImpl implements AreaService {
		
			@Autowired
			private AreaDao areaDao;
		
			@Override
			public List<Area> getAreaList() {
				return areaDao.queryArea();
			}
		
		}
	4.2 在测试包com.imooc.myo2o.service下创建AreaServiceTest,代码如下
		public class AreaServiceTest extends BaseTest {
		
			@Autowired
			private AreaService areaService;
		
			@Test
			public void testGetAreaList() {
				List<Area> areaList = areaService.getAreaList();
				assertEquals("东苑", areaList.get(0).getAreaName());
			}
		
		}
		此时需要在BaseTest的配置文件属性中加上classpath:spring/spring-service.xml。运行测试方法,即可成功!!!!
	4.3 创建包com.imooc.myo2o.web.superadmin,包下创建AreaController,代码如下   (对应视频2-9)
		@Controller
		@RequestMapping("/superadmin")
		public class AreaController {
		
			@Autowired
			private AreaService areaService;
		
			@RequestMapping(value = "/listarea", method = RequestMethod.GET)
			@ResponseBody
			private Map<String, Object> listArea() {
				Map<String, Object> modelMap = new HashMap<String, Object>();
				List<Area> list = new ArrayList<Area>();
				try {
					list = areaService.getAreaList();
					modelMap.put("rows", list);
					modelMap.put("total", list.size());
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
					modelMap.put("success", false);
					modelMap.put("errMsg", e.toString());
				}
				return modelMap;
			}
		
		}
	启动tomcat,可以直接在页面访问http://localhost:8080/o2o/superadmin/listarea得到信息,或者通过postman测试也可以!!!!
	
3 logback  (视频3-2)
	3.1 logback对配置的加载顺序
		java程序在运行时有一个参数 Dlogback.configurationFile参数,如果指定了的话,那么就会首先去找这个参数的地址来加载配置
			java -Dlogback.configurationFile=xxxxxx/xxx.xml
		如果没有配置这个属性,那么就会去加载classpath里的logback.groovy文件
		如果没有这个文件,还会加载同级目录下的logback-test.xml文件
		如果还没有,就会加载同目录下logback.xml文件
		如果还没有,jdk在1.6以上的话,会调用ServiceLoader去查找一个com.qos.logback.classic.spi.Configurator接口的第一个实现类,在类中硬编码上相关的配置
		如果还没有,就会用默认的实现类ch.qos.logback.classic.BasicConfigurator,这个日志就只会输出到控制台当中

	3.2 配置文件
		在resources下创建logback.xml,内容为:
		<?xml version="1.0" encoding="utf-8"?>
		<configuration scan="true" scanPeriod="60 seconds" debug="false">
		<!-- scan属性设置为true时表示当配置文件发生改变时会自动重新加载,默认即为true -->
		<!-- scanPeriod表示扫描的时间间隔,默认单位为ms。这里指定单位为秒,设置为一分钟扫描一次 -->
		<!-- debug为true时表示将会打印出logback内部的日志信息,一般是没必要的 -->
		
			<!-- 定义参数常量 -->
			<!-- TRACE<DEBUG<INFO<WARN<ERROR 程序中使用logger.trace("msg")/debug("msg")/...,设置后面的级别前面的语句将无法打印出来 -->
			<property name="log.level" value="debug"/>
			<!-- 日志保留多长时间 -->
			<property name="log.maxHistory" value="30"/>
			<!-- 日志存储的根路径,这里表示tomcat实例的根目录下的logs/webapps -->
			<property name="log.filePath" value="${catalina.base}/logs/webapps"/>
			<!-- 日志格式  这里的格式为:时间 线程 级别(从左往右输出5位) 输出日志的类 日志内容 换行-->
			<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
			<!-- appender定义日志的输出介质 即日志输出的地方-->
			<!-- 控制台日志 -->
			<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
				<!-- 日志信息的格式  encoder既将日志转换成字符串,又将其写入文件-->
				<encoder>
					<pattern>${log.pattern}</pattern>
				</encoder>
			</appender>
			<!-- DEBUG日志 这里面的类表示会根据文件大小滚动生成新的文件-->
			<appender name="debugAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
				<!-- 文件路径 -->
				<file>${log.filePath}/debug.log</file>
				<!-- 滚动策略 -->
				<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
					<!-- 指定日志压缩文件名称格式 logback会自动将日志压缩-->
					<fileNamePattern>${log.filePath}/debug/debug.%d{yyyy-MM-dd}.log.gz
					</fileNamePattern>
					<!-- 日志保留的最大个数 此处表示保留30个,因为是按天生成,相当于保留30天 -->
					<maxHistory>${log.maxHistory}</maxHistory>
				</rollingPolicy>
				<encoder>
					<pattern>${log.pattern}</pattern>
				</encoder>
				<!-- 日志过滤器,此处表示只记录DEBUG日志,符合的就accept,不符合的就拒绝deny -->
				<filter class="ch.qos.logback.classic.filter.LevelFilter">
					<level>DEBUG</level>
					<onMatch>ACCEPT</onMatch>
					<onMismatch>DENY</onMismatch>
				</filter>
			</appender>
			<!-- INFO日志 配置同上,debug换成info即可-->
			<appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
				<file>${log.filePath}/info.log</file>
				<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
					<fileNamePattern>${log.filePath}/info/info.%d{yyyy-MM-dd}.log.gz
					</fileNamePattern>
					<maxHistory>${log.maxHistory}</maxHistory>
				</rollingPolicy>
				<encoder>
					<pattern>${log.pattern}</pattern>
				</encoder>
				<filter class="ch.qos.logback.classic.filter.LevelFilter">
					<level>INFO</level>
					<onMatch>ACCEPT</onMatch>
					<onMismatch>DENY</onMismatch>
				</filter>
			</appender>
			<!-- ERROR日志 配置同上,debug换成error即可-->
			<appender namae="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
				<file>${log.filePath}/info.log</file>
				<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
					<fileNamePattern>${log.filePath}/error/error.%d{yyyy-MM-dd}.log.gz
					</fileNamePattern>
					<maxHistory>${log.maxHistory}</maxHistory>
				</rollingPolicy>
				<encoder>
					<pattern>${log.pattern}</pattern>
				</encoder>
				<filter class="ch.qos.logback.classic.filter.LevelFilter">
					<level>ERROR</level>
					<onMatch>ACCEPT</onMatch>
					<onMismatch>DENY</onMismatch>
				</filter>
			</appender>
			<!-- logger存放日志对象,name属性告诉appender需要关注哪些包的信息,level表示仅记录其以上的日志信息 -->
			<!-- additivity设为true时会将root中的appender也放入logger中,这样logger中的日志也会输出到控制台里 -->
			<!-- 一个类的logger只能指定一个地方,要么是logger要么是root,这里放在了logger里,但是root也包含过来了,所以也会输出到root中设置的控制台里 -->
			<logger name="com.imooc.myo2o" level="${log.level}" additivity="true">
								▶imooc,,之前写成了immoc,一直不符合设置,,可恶!!!
				<!-- logger需要和appender绑定 -->
				<appender-ref ref="debugAppender"/>
				<appender-ref ref="infoAppender"/>
				<appender-ref ref="errorAppender"/>
			</logger>
			<!-- 根日志,只有level属性,就是特殊的logger。如果logger不指定level那么就会继承root的level -->
			<root level="info">
				<appender-ref ref="consoleAppender"/>
			</root>
		</configuration>
	3.3 运行   (对应视频3-3)
		在AreaController中添加日志:
			public class AreaController {
				Logger logger = (Logger) LoggerFactory.getLogger(AreaController.class);	//演示的代码中并没有做强转,这里不做会编译报错,不知为啥
			
				@Autowired
				private AreaService areaService;
			
				@RequestMapping(value = "/listarea", method = RequestMethod.GET)
				@ResponseBody
				private Map<String, Object> listArea() {
					logger.info("===start===");			//▶
					long startTime = System.currentTimeMillis();
					Map<String, Object> modelMap = new HashMap<String, Object>();
					List<Area> list = new ArrayList<Area>();
					try {
						list = areaService.getAreaList();
						modelMap.put("rows", list);
						modelMap.put("total", list.size());
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
						modelMap.put("success", false);
						modelMap.put("errMsg", e.toString());
					}
					logger.error("test error!");			//▶
					long endTime = System.currentTimeMillis();
					logger.debug("costTime:[{}ms]", endTime - startTime);			//▶
					logger.info("===end===");			//▶
					return modelMap;
				}
			
			}
		启动tomcat,可以看到控制台会打印tomcat的文件夹,即配置中的${catalina.base}参数值:
			CATALINA_BASE:     D:\ProjectCodes\eclipse2019\.metadata\.plugins\org.eclipse.wst.server.core\tmp0
		复制进入文件夹,会发现生成了info debug error的日志文件。去浏览器访问http://localhost:8080/o2o/superadmin/listarea,控制台会输出日志:
			2021-06-04 00:53:36.309 [http-nio-8080-exec-3] INFO  com.imooc.myo2o.web.superadmin.AreaController - ===start===
			2021-06-04 00:53:37.128 [http-nio-8080-exec-3] ERROR com.imooc.myo2o.web.superadmin.AreaController - test error!
			2021-06-04 00:53:37.128 [http-nio-8080-exec-3] DEBUG com.imooc.myo2o.web.superadmin.AreaController - costTime:[810ms]
			2021-06-04 00:53:37.132 [http-nio-8080-exec-3] INFO  com.imooc.myo2o.web.superadmin.AreaController - ===end===
		同时对应文件也会记录log。。。过一天的话日志会自动打包进文件夹,验证成功

4 补充文件上传类,Shop的service类和对应测试类	(对应视频4-1~4-5)		▶里面有给图片加水印的测试方法,参ImageUtil类
		<!-- 图片处理 -->
		<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
		<dependency>
		    <groupId>net.coobird</groupId>
		    <artifactId>thumbnailator</artifactId>
		    <version>0.4.8</version>
		</dependency>
	实例网址:https://github.com/coobird/thumbnailator/wiki/Examples

	数据库事务必须抛出RuntimeException或其子类的异常才能回滚

	这里面视频信息有缺失,但是后面的视频有说明。示例代码中使用的是CommonsMultipartFile,但是这样Junit启动就会报spring的错,故后面改成了File类,方便测试。这样在写controller时就得做转换,CommonsMultipartFile中是可以拿到文件流的

5 补充controller中插入店铺的代码,这里涉及到jackson-databind的使用,部分代码如下:
		//▶用ObjectMapper将string转为对象
		String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
		ObjectMapper mapper = new ObjectMapper();
		Shop shop = null;
		try {
			shop = mapper.readValue(shopStr, Shop.class);			
		} catch (Exception e) {}

		//▶从servlet中获取CommonsMultipartFile文件
		CommonsMultipartFile shopImg = null;
		CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
				request.getSession().getServletContext());
		if (commonsMultipartResolver.isMultipart(request)) {
			MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
			shopImg = (CommonsMultipartFile) multipartHttpServletRequest.getFile("shopImg");		
		} else {}
	其他详细代码见ShopManagementController的registerShop方法,包括利用CommonsMultipartFile中的流来转为File

6 使用sui mobile作为前端 		(视频4-6前端设计)
	视频演示的是使用淘宝的cdn来引入css和js,但是现在官网上已经没有这个连接了,所以需要自行下载压缩包,并把文件夹放入webapp下提供给html引入:
    		<link rel="stylesheet" href="sui/css/sm.min.css">
		<link rel="stylesheet" href="sui/css/sm-extend.min.css">
		<script src='//cdn.bootcss.com/jquery/3.1.1/jquery.min.js'></script>
		<script src='sui/js/sm.js'></script>
		<script src='sui/js/sm-extend.js'></script>
	但是在后面将html页面放入WEB-INF中,通过controller访问时又下载不到了,需要在前面加上../
    		<link rel="stylesheet" href="../sui/css/sm.min.css">
	    	<link rel="stylesheet" href="../sui/css/sm-extend.min.css">
		<script src='//cdn.bootcss.com/jquery/3.1.1/jquery.min.js'></script>
		<script src='../sui/js/sm.js'></script>
		<script src='../sui/js/sm-extend.js'></script>

	一般将css的引入放在html的前部分,js放在后部分,这样可以让样式先显示出来,数据后加载,比较合适

7 引入验证码和文件上传解析器完成店铺新增的代码(视频4-8 —— 4-12)
		<!-- 验证码 相关参数配置见web.xml-->
		<!-- https://mvnrepository.com/artifact/com.github.penggle/kaptcha-->
		<dependency>
		    <groupId>com.github.penggle</groupId>
		    <artifactId>kaptcha</artifactId>
		    <version>2.3.2</version>
		</dependency>
		<!-- 文件上传处理 -->
		<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.2</version>
		</dependency>

	<!-- 文件上传解析器 -->
	 <bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<property name="defaultEncoding" value="utf-8"></property>
		<!-- 最大上传文件大小 1024*1024*20M-->
		<property name="maxUploadSize" value="20971520"></property>
		<property name="maxInMemorySize" value="20971520"></property>
	</bean>

B MySQL主从库同步与读写分离
8 




C 项目学习
9. 实际代码解释参:D:\ProjectCodes\eclipse2019\o2o

10. 网站的首页上的图片无法正常显示,是因为数据库中的字段使用的是相对路径,所以页面取不到(当然本项目本身就没有图片,所以实际测试需要先把文件准备好)
	此时可以再后台遍历将父文件夹的路径拼上去,,但是这样做有点损失性能,所以可以使用tomcat自动给该字段拼接。
	在eclipse中,添加了tomcat以后,就会自动有一个Servers的项目,点进去选中对应的tomcat,选中server.xml,拉到最下面可以看到一个Context标签
	可以看到里面对path=/o2o做了处理,所以在页面上访问前加上项目名:http://localhost:8080/o2o就可以定位到这个docBase中的项目
	类似的我们可以添加一个Context标签,在解析到图片路径时,自动给他转到实际的文件夹地址:
		<Context docBase="D:\TestFolder\fold1\upload\frontend" path="/upload/images/item/headtitle"/>			此处为轮播图
		<Context docBase="D:\TestFolder\fold1\upload\shopcategory" path="/upload/images/item/shopcategory"/>	此处为一级大类图
	此配置不依赖于项目名,与项目同级。这样在其他项目中该映射其实也是有效的

11.阿里云部署Java网站和微信开发调试	视频文档地址:https://www.imooc.com/article/20583
	11.1 阿里云服务器部署
		选择云服务器ECS,系统为linux centOS最新的即可,SecureCRT远程连接公有地址登录,密码可以从平台上查到,端口默认。winscp的登录相同。
		远程登录默认进入root文件夹,cd ../可以返回上一次层。这里直接在root文件夹下将下载好的文件用winscp拖进来。文件和路径为(实际文件名按下载页面显示为准):
			JDK1.8		http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html		选择下载jdk-8u144-linux-x64.rpm
			tomcat8	http://tomcat.apache.org/download-80.cgi#8.0.46					选择下载apache-tomcat-8.0.46.tar.gz
			MySQL		https://dev.mysql.com/downloads/repo/yum/				选择下载mysql57-community-release-el7-11.noarch.rpm
			Redis 		https://redis.io/download			选择下载redis-4.0.2.tar.gz
		安装jdk:
			chmod +x jdk-8u144-linux-x64.rpm		//添加可执行权限
			rpm -ivh jdk-8u144-linux-x64.rpm		//安装RPM软件包
			java –version		//查看java的版本信息,若出现版本信息则成功
		安装Mysql:
			rpm -Uvh mysql57-community-release-el7-11.noarch.rpm		//安装用来配置mysql的yum源的rpm包 
			yum install mysql-community-server		//安装Mysql
				这一步可能会报错Error:Unable to find a match: mysql-community-server,需要执行以下语句安装:
					yum module disable mysql		//先禁用本地的 MySQL 模块再安装
					yum -y install mysql-community-server
			service mysqld start		//开启mysql服务
			ps -ef | grep mysqld		//查看是否启动成功(应显示mysql的进程)
			grep ‘temporary password’ /var/log/mysqld.log		//mysql安装成功后创建的超级用户’root’@‘localhost’的密码会被存储在/var/log/mysqld.log,可以使用如下命令查看密码
			mysql -uroot -p	//使用mysql生成的’root’@‘localhost’用户和密码登录数据库
			ALTER USER ‘root’@‘localhost’ IDENTIFIED BY ‘123654’;		//修改密码 
				这里如果密码过于简单,可能会报错ERROR 1819 (HY000): Your password does not satisfy the current policy requirements,使用以下语句:
					SHOW VARIABLES LIKE 'validate_password%'; 		//查看 mysql 初始的密码策略(在这之前需要先把密码改成合适的才能继续操作,比如改为Dingmin@111)
					set global validate_password.length=6;				//根据不同的参数修改设置
					set global validate_password.mixed_case_count=0;
					set global validate_password.policy=LOW;
					set global validate_password.special_char_count=0;
					ALTER USER ‘root’@‘localhost’ IDENTIFIED BY ‘123654’;	//重新修改密码
		去阿里云开通端口的远程访问,包括22 3389 80 3306 6379
		配置mysql远程访问:(文档上演示的语句在8执行总是报错,故使用以下语句)
			use mysql;			//指定数据库
			select Host,User from user;		//查询用户访问权限,此时发现显示的用户都是只有localhost可以访问
			update user set host = '%' where user = 'root';	//允许root用户任何远程访问。%代表允许所有的远程主机进行连接
			grant ALL on *.* to `root`@`%` with grant option;		//授权
			flush privileges;			//刷新权限。。刷新以后就可以从本地navicat连上阿里云的数据库了
		 		mysql -uroot -P3306 -h106.14.18.149 -p		//这里也可以考虑从本地的cmd进入远程的mysql。但是由于本地使用的mysql版本过低,此处连接失败。等以后两者mysql版本都在8.0以上再验证
		安装redis:
			tar -zxvf redis-6.2.5.tar.gz		//解压redis安装包,会在当前文件夹生成redis-6.2.5文件夹
			设置redis以支持远程登录
				vi redis-6.2.5/redis.conf		//编辑该文件
				将bind 127.0.0.1这句话用井号注释掉,这样就能支持远程连接了(按/进入查找功能,查找bind,修改为#bind 127.0.0.1)
				将daemonize的属性值改为yes,以支持redis作为守护进程一直跑在后台(编辑结束按esc退出,按:wq保存退出		:wq!强制保存退出 :w保存但不退出 :q不保存并退出 :q!不保存并强制退出)
			make		//进入redis-6.2.5文件夹,安装
			src/redis-server redis.conf		//启动redis服务(此操作并未有任何输出,与文档显示有差异)
			src/redis-cli		//通过redis-cli连接到redis服务器。当输入ping 得到pong的回应之后,证明redis配置已经完成
		安装tomcat:
			tar -zxvf apache-tomcat-8.5.37.tar.gz			//解压tomcat,生成文件夹apache-tomcat-8.5.37
			./apache-tomcat-8.5.37/bin/startup.sh			//启动tomcat,此时会显示tomcat started










DOWN 返回