一、课程介绍
模仿企业对于人员的管理,包括部门信息,人员信息,日志信息记录和浏览的管理
二、案例展示及概述
三、案例准备及控制模块开发
创建表后再添加约束,这样就不用担心表的创建顺序。
示例:给staff表添加外键
alter table staff add constraint fk_staff(外键表名)_dep(主键表名)【约束名】 foreign key(did)(以当前表的哪个字段进行关联) references department(id)(关联到该表的那个字段);
Spring全局配置需要做的事情,第一、Spring和Mybatis的整合,实质就是将Mybatis管理的SqlSessionFactory对象和持久化对象交给Spring管理
第二、声明式事务,需配置事务管理器、通知、以及将通知织入
第三、全局扫描,包扫面和aspectj表达式扫描
mybatis.xml配置文件模板实例
<?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> <!--propertis配置,用于加载外部的properties配置文件--> <properties resource="db.properties"></properties> <!--environments 主要用于进行数据源的配置 可以配置多个数据源,通过default属性来指定当前项目运行过程中使用的是哪个数据源 environmets中的default属性对应于environment中的id,对应哪个即使用那个独立的数据源--> <environments default="development"> <environment id="development"> <!--transactionManager用于配置事务管理,默认情况下使用JDBC事务管理--> <transactionManager type="JDBC"/> <!--dataSource具体数据源的链接信息,type属性用于指定是否使用连接池--> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> <environment id="product"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> <environment id="test"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!--mappers主要用于配置外部的映射配置文件 在主配置文件中需要引入加载外部的映射配置文件--> <mappers> <!--mapper主要配置引入某一个具体的映射配置文件,resource进行路径方式的引入--> <mapper resource="mapper/usersMapper.xml"/> </mappers> </configuration>
Spring.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:aop="http://www.springframework.org/schema/aop" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--spring整合mybatis,即把mybatis原本管理的持久化操作对象和SqlSessionFactory对象交给spring管理--> <!--数据源--> <bean id="dateSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/sm?useUnicode=true&characterEncoding=utf-8"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!--session工厂--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dateSource"></property> <property name="typeAliasesPackage" value="com.imooc.sm.entity"></property> </bean> <!--持久化对象,对应于mybatis.xml映射器接口的配置--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.imooc.sm.dao"></property> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!--声明式事务--> <!--事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dateSource"></property> </bean> <!--通知--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="search*" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!--织入--> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.imooc.sm.service.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor> </aop:config> <!--全局扫描--> <context:component-scan base-package="com.imooc.sm"></context:component-scan> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
为什么要有核心控制器(也是一个Servlet): 当用户向web容器发送请求时,web容器会根据url判断这个请求是否该用Servlet以及用哪个Servlet处理。判断完成后它会构造出Servlet对象然后进行初始化,之后再调用service方法对请求进行处理。 但是,Servlet对象由Web容器进行管理,service对象、dao对象由ioc容器进行管理。Servlet对象处理用户请求时需要调用Service对象,(根据IoC思想,你需要对象我就可以帮你注入这个对象,
但是无法实现。因为servlet对象不再IoC容器里,所以没办法注入他需要的对象)所以在Servlet对象无法使用spring_ioc进行对象的注入。 解决:核心控制器。 用户发送请求到web容器,web容器将请求全部交给核心控制器,核心控制器不做具体操作,只是判断该调用哪个控制器进行处理。 又因为核心控制器也是一个对象且是由我们写的,所以可以将这个放到ioc容器里。再从ioc容器里获取对象。
核心控制器干什么: 1、解析url得到ioc容器里小控制器的bean的名字。
2、处理这一次请求时获得这个请求要用的方法。通过bean的名字在ioc容器中把这个bean对象(即最终进行处理的控制器)拿出来,然后再通过方法名反射执行该方法。
核心控制器代码
package com.imooc.sm.global; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class DispatchServlet extends GenericServlet { private ApplicationContext context; //在Servlet初始化时就生成Ioc容器,从而只执行一次,不会每次都加载配置文件 @Override public void init() throws ServletException { super.init(); context = new ClassPathXmlApplicationContext("spring.xml"); } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { //强转后才能获得请求路径 HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse; /* 使用核心控制器的相关规范:1.访问路径格式 存在两种格式 /staff/add(方法名).do类型和login.do类型 2.控制器的命名 BeanName 应如 staffController 3.定义处理请求的实际方法格式 public void add(httpServletRequest,httpServletResponse){} */ //获取url,去掉前面的“/”才是需要的url String path = httpServletRequest.getServletPath().substring(1);//相当于substring(0,1) System.out.println(httpServletRequest.getServletPath()+"===="+httpServletRequest.getContextPath()); //获取BeanName和处理此次请求的方法 String beanName = null; String methodName = null; int index = path.indexOf(\'/\'); //判断路径格式类型 if (index != -1) { beanName = path.substring(0, index) + "Controller"; methodName = path.substring(index + 1, path.indexOf(".do")); } else { beanName = "selfController"; methodName = path.substring(0, path.indexOf(".do")); } //访问IOC容器有beanName获取对象 //获取Spring上下文 Object object = context.getBean(beanName); try { //通过反射获取方法 Method method = object.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); //执行方法 try { method.invoke(object, httpServletRequest, httpServletResponse); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (NoSuchMethodException e) { e.printStackTrace(); } } }
四、部门及员工管理实现
1 ) 功能实现
2)部门管理实现-业务
Dao接口与Sql映射文件(分两部分配置实体类和数据表的对应关系、持久化接口中的操作方法对应的sql):
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--Dao接口与Sql映射--> <mapper namespace="com.imooc.sm.dao.DepartmentDao">
<!--实体类和表的对应关系--> <!--实体类属性和数据库表字段的映射关系--> <!--配置结果集,type为实体类类名,此处配置了能使用类名简称--> <resultMap id="resultMap" type="Department"> <!--属性对应字段为主键时用id标签,其他则用result标签--> <id property="id" column="id" javaType="Integer"/> <result property="name" column="name" javaType="String"/> <result property="address" column="address" javaType="String"/> </resultMap>
<!--持久化操作接口中操作方法对应的sql--> <!--配置sql,dao接口有多少个方法配置多少个sql,sql的id为方法名--> <!--parameterType设置方法参数类型,insert语句需要调用数据库自增的规范,故要设置useGeneratedKeys--> <insert id="insert" parameterType="Department" useGeneratedKeys="true"> insert into department(name,address) values(#{name},#{address}) </insert> <delete id="delete" parameterType="Integer"> delete from department where id=#{id} </delete> <update id="update" parameterType="Department"> update department set name=#{name},address=#{address} where id=#{id} </update> <select id="selectById" parameterType="Integer" resultMap="resultMap"> select * from department where id=#{id} </select> <select id="selectAll" resultMap="resultMap"> select * from department </select> </mapper>
3)部门管理实现-界面
4)员工管理实现-业务
员工关联部门,获取员工对象时希望也能获取关联的复杂的部门对象
1) 实体类中需要先定义关联的对象 private Department department
2)配置文件中定义
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.imooc.sm.dao.StaffDao"> <resultMap id="resultMap" type="Staff"> <id property="id" column="id" javaType="Integer"/> <result property="account" column="account" javaType="String"/> <result property="password" column="password" javaType="String"/> <result property="status" column="status" javaType="String"/>
<!--关联字段did--> <result property="did" column="did" javaType="Integer"/> <result property="name" column="name" javaType="String"/> <result property="sex" column="sex" javaType="String"/> <result property="idNumber" column="id_number" javaType="String"/> <result property="workTime" column="work_time" javaType="java.util.Date"/> <result property="leaveTime" column="leave_time" javaType="java.util.Date"/> <result property="bornDate" column="born_date" javaType="java.util.Date"/> <result property="info" column="info" javaType="String"/>
<!--想要获取的复杂对象--> <association property="department" column="did" javaType="Department" select="com.imooc.sm.dao.DepartmentDao.selectById" /> </resultMap> <insert id="insert" parameterType="Staff" useGeneratedKeys="true"> insert into staff(account,password,status,did,name,sex,id_number,work_time,leave_time,born_date,info) values(#{account},#{password},#{status},#{did},#{name},#{sex},#{idNumber},#{workTime},#{leaveTime},#{bornDate},#{info}) </insert> <delete id="delete" parameterType="Integer"> delete from staff where id=#{id} </delete> <update id="update" parameterType="Staff"> update staff set account=#{account},password=#{password},status=#{status}, did=#{did},name=#{name},sex=#{sex},id_number=#{idNumber}, work_time=#{workTime},leave_time=#{leaveTime},born_date=#{bornDate},info=#{info} where id=#{id} </update> <select id="selectById" parameterType="Integer" resultMap="resultMap"> select * from staff where id=#{id} </select> <select id="selectAll" resultMap="resultMap"> select * from staff </select> </mapper>
默认登陆密码设置可通过交给SpringIOC产生bean对象时就设置为默认属性
@Resource private StaffDao staffDao; public void add(Staff staff) { staff.setPassword("123456"); staff.setWorkTime(new Date()); staff.setStatus("正常"); staffDao.insert(staff); }
五、登录与个人中心实现
登录过滤器;
package com.imooc.sm.global; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; //该过滤器功能:登录后才能访问后台功能,不能直接跳过登录通过url访问 public class LoginFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest)servletRequest; HttpServletResponse response=(HttpServletResponse)servletResponse; String path=request.getServletPath(); //判断该路径中是否包含login,如果有则不过滤放过 if (path.toLowerCase().indexOf("login")!=-1){ filterChain.doFilter(request,response); }else { HttpSession session=request.getSession(); //判断session中是否保存用户信息 Object object=session.getAttribute("USER"); if (object!=null){ filterChain.doFilter(request,response); }else { //拦截的url可能是一级目录形式,也可能是二级,故此处要用绝对路径 response.sendRedirect(request.getContextPath()+"/toLogin.do"); } } } public void destroy() { } }
六、日志处理实现(切面编程注入)
实现从底层开始实现,先创建实体类,创建持久化操作接口,配置持久化接口和sql映射文件(.xml),业务层接口及实现类,表现层(什么时候记录日志,记录日志需要考虑操作源,操作源保存在session中在web层,处理用户请求时开始记录日志)