ssm练习第三天_分页助手_安全框架

文章目录

  • 一、手动分页
    • 1、页面入口
    • 2、编写分页实体PageBean
    • 3、编写Controller(修改昨日findAll)
    • 4、编写Service
    • 5、编写Dao
    • 6、编写页面product-list.jsp
  • 二、分页助手PageHelper的使用
    • 1、PageHelper简介
    • 2、PageHelper的环境搭建
    • 3、PageHelper的快速入门
    • 4、PageHelper的API解析
      • 4.1 设置分页参数
      • 4.2 获得分页相关数据
    • 5、分页查询集成PageHelper
      • 5.1、页面入口
      • 5.2、编写Controller
      • 5.3、编写Service
      • 5.4、编写Dao
      • 5.5、编写页面
  • 三、SpringSecurity安全框架入门
    • SpringSecurity的简介
    • SpringSecurity的入门使用
      • 1、创建itheima_springSecurity项目(war)
      • 2、导入SpringSecurity的坐标(pom.xml)
      • 3、配置spring-security.xml
      • 4、配置web.xml
      • 5、测试
      • 6、配置自定义登录页面
      • 7、login.jsp页面
      • 8、success.html页面
      • 9、error.html页面
  • 四、项目集成SpringSecurity(项目实战中的应用)
    • 1、添加spring-security.xml配置文件
    • 2、修改web.xml
        • 注意:前端登录和注销的路径要改 Google浏览器+一些静态资源放行
      • 3、创建用户表和用户实体
      • 4、修改spring-security.xml,修改认证方式为查询数据库
      • 5、编写UserService业务代码
      • 6、dao实现
  • 五、加入日志(复制一个文件就行了)
    • 1.查看日志发现框架的分页查询是这么写的
    • 2. log4j2日志输出自己的提示信息(替换sout输出) ★
      • LogUtils.java
      • 测试
  • 附录:PageHelper分页插件的相关参数

一、手动分页

1、页面入口

ssm练习第三天_分页助手_安全框架_第1张图片

2、编写分页实体PageBean

@Data
public class PageBean<T> {//其实不一定写T 写任何字母都行 就是一个普通变量
    private Integer currPage;//当前页      页面传参
    private Integer pageSize;//每页条数    页面传参
    private Long totalCount;//总条数       查询数据库
    private Integer totalPage;//总页数     计算:Math.ceil(totalCount*1.0/pageSize)向上取整 注意乘以1.0 否则小数部分都没有了
    private List<T> list;//当前页数据       数据库查询
}

3、编写Controller(修改昨日findAll)

    /**
     * 手动分页查询
     *  用 @RequestParam 注解设置默认值
     * @return
     */
    @RequestMapping("/findAll")
    public ModelAndView findAll(
            @RequestParam(value = "currPage",required = false,defaultValue = "1") Integer currPage,
            @RequestParam(value = "pageSize",required = false,defaultValue = "5") Integer pageSize
    ){
        //数据
        PageBean<Product> pageBean = productService.findByPage(currPage,pageSize);

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("pageBean", pageBean);
        //页面
        modelAndView.setViewName("product-list");
        //返回
        return modelAndView;
    }

4、编写Service

接口

PageBean<Product> findByPage(Integer currPage, Integer pageSize);

实现

//根据分页参数查询pageBean对象
    @Override
    public PageBean<Product> findByPage(Integer currPage, Integer pageSize) {
        PageBean<Product> pageBean = new PageBean<>();
        //封装5个参数
        pageBean.setCurrPage(currPage);
        pageBean.setPageSize(pageSize);
        //直接查 怎么方便怎么写 先不要痴心妄想啥效率
        Long totalCount=productDao.findTotalCount();
        pageBean.setTotalCount(totalCount);
        pageBean.setTotalPage((int) Math.ceil(totalCount*1.0/pageSize));//方便lombok的使用
        /**
         * 1: 1 5
         * 2: 6 10
         * 3: 11 15
         * ...
         * n: (n-1)*5+1 n*5
         *  即是:(currPage-1)*pageSize+1  ~  pageSize*currPage
         *  化简:pageSize*currPage-pageSize+1 ~ pageSize*currPage
         */
        Integer startIndex=(currPage-1)*pageSize+1;
        Integer endIndex=pageSize*currPage;
        List<Product> products= productDao.findByPage(startIndex,endIndex);
        pageBean.setList(products);
        return pageBean;
    }

5、编写Dao

/**
     * 查询产品表总记录数
     *  count(*) 效率最低
     *  count(主键) 唯一且不重复 效率高
     *  count(1) 查询常量列 效率非常高
     *      可以在pl/sql dev..里面测试 对比时间 一目了然
     * @return
     */
    @Select("select count(1) from product")
    Long findTotalCount();

    /**
     * 根据分页参数 查询单页记录
     * @param startIndex
     * @param endIndex
     * @return
     */
    @Select("select t.* from (select p.*,rownum rn from product p) t where t.rn between #{param1} and #{param2}")
    List<Product> findByPage(Integer startIndex, Integer endIndex);

6、编写页面product-list.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div class="box-footer">
	<div class="pull-left">
		<div class="form-group form-inline">
			第${pageBean.currPage} 页,
			总共${pageBean.totalPage} 页,共${pageBean.totalCount} 条数据。 每页
			<select class="form-control" name="pageSize" id="pageSize" onchange="gotoPage(1)">
				<%--前10个用循环写 方便--%>
				<c:forEach begin="2" end="10" var="i">
					<option value="${i}">${i}option>
				c:forEach>
				<option value="15">15option>
				<option value="20">20option>
				<option value="30">30option>
				<option value="40">40option>
				<option value="50">50option>
	
			select>div>
	div>
	
	<div class="box-tools pull-right">
		<ul class="pagination" id="gotoLi">
			<%--超链接里访问js函数 必须加前缀javascript:--%>
			<li><a href="javascript:gotoPage(1)" aria-label="Previous">首页a>li>
			<li><a href="javascript:gotoPage(${pageBean.currPage-1})">上一页a>li>
			<c:forEach begin="1" end="${pageBean.totalPage}" var="i">
				<li><a href="javascript:gotoPage(${i})">${i}a>li>
			c:forEach>
			<li><a href="javascript:gotoPage(${pageBean.currPage+1})">下一页a>li>
			<li><a href="javascript:gotoPage(${pageBean.totalPage})" aria-label="Next">尾页a>li>
		ul>
	div>
div>

js代码

前端写一个gotoPage(i) 函数最为方便
注意切换每页条数后需要刷新当前页 去展示第一页 否则切换当前页数后点下一页 会出错

//方法写在外面 会自动执行 注意先得给每个option加上value="xx" 不能没有value属性
//每页显示几条的数据回显 select option
$("#pageSize option[value=${pageBean.pageSize}]").prop("selected","selected");
//跳转页面
function gotoPage(currPage) {
      //页面的越界检查此处判断也很方便
	  if(currPage<1||currPage>${pageBean.totalPage}) return;
      var pageSize=$("#pageSize").val();
      location.href="${pageContext.request.contextPath}/product/findAll?currPage="+currPage+"&pageSize="+pageSize;
}

二、分页助手PageHelper的使用

1、PageHelper简介

PageHelper是国内非常优秀的一款开源的mybatis分页插件,它支持基本主流与常用的数据库,例如mysql、oracle、mariaDB、DB2、SQLite、Hsqldb等。

网址:https://pagehelper.github.io/

本项目在 github 的项目地址:https://github.com/pagehelper/Mybatis-PageHelper

本项目在 gitosc 的项目地址:http://git.oschina.net/free/Mybatis_PageHelper

2、PageHelper的环境搭建

添加PageHelper坐标(之前的pom中已经包含该坐标)


<dependency>
    <groupId>com.github.pagehelpergroupId>
    <artifactId>pagehelperartifactId>
    <version>5.1.2version>
dependency>

配置mybatis的PageHelper插件,mybatis的配置已经集成到spring的配置文件中了,所以在配置SqlSessionFactory时指定插件
applicationContext-dao.xml

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    
    <property name="dataSource" ref="dataSource">property>
    
    <property name="plugins">
        <array>
            <bean class="com.github.pagehelper.PageInterceptor">
                <property name="properties">
                    <props>
                        
                        <prop key="helperDialect">oracleprop>
                    props>
                property>
            bean>
        array>
    property>
bean>

3、PageHelper的快速入门

在ssm_service或者web的test测试目录中创建TestPageHelper测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:spring/*.xml")
public class TestPageHelper {
    @Autowired
    ProductService productService;

    @Test
    public void test(){
        productService.testFindByPageHelper(2,5);
    }
}

4、PageHelper的API解析

4.1 设置分页参数

在你需要进行分页的 MyBatis 查询方法前调用PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。

public static <E> Page<E> startPage(int pageNum, int pageSize) {
    return startPage(pageNum, pageSize, true);//参数被绑定到当前线程
}

参数:pageNum:当前页;pageSize:当前页显示的条数

4.2 获得分页相关数据

创建PageInfo对象,将查询结果作为参数传递进构造,则可以通过PageInfo获得分页的相关信息:
ProductServiceImpl.java

	@Override
    public void testFindByPageHelper(Integer currPage, Integer pageSize) {
        //为分页助手初始化参数  两个参数会绑定到当前线程 然后拦截器生效执行
        PageHelper.startPage(currPage,pageSize);
        //直接查询全部 拦截器自动添加限制条件 仅仅查询当前页数据
        List<Product> products = productDao.findAll();
        //创建pageInfo对象 相当于自定义的pageBean  需要通过构造方法传入集合对象
        //第二个参数5就是每页最多显示的页码数(数据太多时不可能1 2 3 .. 100多个页面全部打印出来)
        PageInfo<Product> pageInfo = new PageInfo<>(products,5);
        //点进去api 注释是中文 不怕字段含义不清楚了
        
        //测试
        System.out.println("当前页:"+pageInfo.getPageNum());//就是当前页码
        System.out.println("每页条数:"+pageInfo.getPageSize());
        System.out.println("总页数:"+pageInfo.getPages());//注意api含义
        System.out.println("总条数:"+pageInfo.getTotal());
        System.out.println("数据:"+pageInfo.getList().size());
        System.out.println("上页页码:"+pageInfo.getPrePage());
        System.out.println("下页页码:"+pageInfo.getNextPage());
        System.out.println("是否第一页:"+pageInfo.isIsFirstPage());
        System.out.println("是否最后一页:"+pageInfo.isIsLastPage());
        System.out.println("页面显示的第一个页码是:"+pageInfo.getNavigateFirstPage());
        System.out.println("页面显示的最后一个页码是:"+pageInfo.getNavigateLastPage());
    }

5、分页查询集成PageHelper

5.1、页面入口

ssm练习第三天_分页助手_安全框架_第2张图片

5.2、编写Controller

简单修改一下而已

    /**
     *  分页助手实现分页查询
     *  用 @RequestParam 注解设置默认值
     * @return
     */
    @RequestMapping("/findAll")
    public ModelAndView findAll(
            @RequestParam(value = "currPage",required = false,defaultValue = "1") Integer currPage,
            @RequestParam(value = "pageSize",required = false,defaultValue = "5") Integer pageSize
    ){
        //数据
        PageInfo<Product> pageHelper = productService.findByPageHelper(currPage, pageSize);

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("pageHelper", pageHelper);
        //页面
        modelAndView.setViewName("product-list");
        //返回
        return modelAndView;
    }

5.3、编写Service

接口

    PageInfo<Product> findByPageHelper(Integer currPage,Integer pageSize);

实现类

    /**
     * 使用分页助手简单分页查询
     * @param currPage
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Product> findByPageHelper(Integer currPage, Integer pageSize) {
        //指定分页参数
        PageHelper.startPage(currPage,pageSize);
        //查询全部 分页参数已经被绑定到当前线程 拦截器根据参数帮你做到拦截
        List<Product> products = findAll();
        //创建PageInfo对象 控制页面最多显示5个页码
        PageInfo<Product> pageInfo = new PageInfo<>(products, 5);
        //返回
        return pageInfo;
    }

5.4、编写Dao

之前的findAll 也可以直接调用service里的findAll

5.5、编写页面

<div class="box box-primary">
<div class="box-header with-border">
	<h3 class="box-title">列表</h3>
</div>

<div class="box-body">
	<form action="${pageContext.request.contextPath}/product/delMany?" id="delForm">
	<!-- 数据表格 -->
	<div class="table-box">
		<!--数据列表-->
		<table id="dataList"
			class="table table-bordered table-striped table-hover dataTable">
			<thead>
				<tr>
					<th class="" style="padding-right: 0px;"><input
						id="selall" type="checkbox" class="icheckbox_square-blue">
					</th>
					<th class="sorting_asc">ID</th>

					<th class="sorting">产品编号</th>
					<th class="sorting">产品名称</th>
					<th class="sorting">出发城市</th>
					<th class="sorting">出发时间</th>
					<th class="sorting">产品价格</th>
					<th class="sorting">产品描述</th>
					<th class="sorting">产品状态</th>

					<th class="text-center">操作</th>
				</tr>
			</thead>
			<tbody>
				<c:forEach items="${pageHelper.list}" var="product">
				<tr>
					<td><input name="ids" type="checkbox" value="${product.id}"></td>
					<td>${product.id}</td>

					<td>${product.productNum}</td>
					<td>${product.productName}</td>
					<td>${product.cityName}</td>
					<td>
						<%--el标签可以 格式化标签 注意MM大写--%>
						<fmt:formatDate value="${product.departureTime}" pattern="yyyy-MM-dd HH:mm"></fmt:formatDate>
					</td>
					<td>${product.productPrice}</td>
					<td>${product.productDesc}</td>
					<td>${product.productStatus == 1?'开启':'关闭'}</td>

					<td class="text-center">
						<button type="button" class="btn bg-olive btn-xs"
							onclick='location.href="all-order-manage-edit.html"'>订单</button>
						<button type="button" class="btn bg-olive btn-xs"
							onclick='delOne(${product.id})'>删除</button>
						<button type="button" class="btn bg-olive btn-xs"
							onclick='location.href="${pageContext.request.contextPath}/product/updateUI?productId=${product.id}"'>修改</button>
					</td>
				</tr>
				</c:forEach>
			</tbody>

		</table>
		<!--数据列表/-->
	</div>
	<!-- 数据表格 /-->
	</form>

</div>
<!-- /.box-body -->

<!-- .box-footer-->
<div class="box-footer">
	<div class="pull-left">
		<div class="form-group form-inline">
			第${pageHelper.pageNum} 页,
			总共${pageHelper.pages} 页,共${pageHelper.total} 条数据。 每页
			<select class="form-control" name="pageSize" id="pageSize" onchange="gotoPage(1)">
				<%--10个用循环写 方便--%>
				<c:forEach begin="2" end="10" var="i">
					<option value="${i}">${i}</option>
				</c:forEach>
				<option value="15">15</option>
				<option value="20">20</option>
				<option value="30">30</option>
				<option value="40">40</option>
				<option value="50">50</option>

			</select></div>
	</div>

	<div class="box-tools pull-right">
		<ul class="pagination" id="gotoLi">
			<%--超链接里访问js函数 必须加前缀javascript:--%>
			<li><a href="javascript:gotoPage(1)" aria-label="Previous">首页</a></li>
				<%--prePage多方便--%>
			<li><a href="javascript:gotoPage(${pageHelper.prePage})">上一页</a></li>
				<%--页面上显示几个页码也简单可控了 实在太方便了--%>
			<c:forEach begin="${pageHelper.navigateFirstPage}" end="${pageHelper.navigateLastPage}" var="i">
				<li><a href="javascript:gotoPage(${i})">${i}</a></li>
			</c:forEach>
			<li><a href="javascript:gotoPage(${pageHelper.nextPage})">下一页</a></li>
			<li><a href="javascript:gotoPage(${pageHelper.pages})" aria-label="Next">尾页</a></li>
		</ul>
	</div>

</div>
</div>

js代码

//方法写在外面 会自动执行 注意先得给每个option加上value="xx" 不能没有value属性
//每页显示几条的数据回显 select option
$("#pageSize option[value=${pageHelper.pageSize}]").prop("selected","selected");

//跳转页面
function gotoPage(currPage) {
    //页面的越界检查此处判断也很方便
	if(currPage<1||currPage>${pageHelper.pages}) return;

    var pageSize=$("#pageSize").val();
    location.href="${pageContext.request.contextPath}/product/findAll?currPage="+currPage+"&pageSize="+pageSize;
}

三、SpringSecurity安全框架入门

SpringSecurity的简介

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

  • “认证”,是为用户建立一个他所声明的主体。主体一般是指用户,设备或可以在你系 统中执行动作的其他系统。
  • “授权”,指的是一个用户能否在你的应用中执行某个操作,在到达授权判断之前,身份的主题已经由身份验证过程建立了。

SpringSecurity的入门使用

1、创建itheima_springSecurity项目(war)

ssm练习第三天_分页助手_安全框架_第3张图片

2、导入SpringSecurity的坐标(pom.xml)

<properties>
    <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    <maven.compiler.source>1.7maven.compiler.source>
    <maven.compiler.target>1.7maven.compiler.target>
    <spring.version>5.0.2.RELEASEspring.version>
    <spring.security.version>5.0.1.RELEASEspring.security.version>
  properties>

  <dependencies>
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>4.11version>
      <scope>testscope>
    dependency>

    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-coreartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webmvcartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-context-supportartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-testartifactId>
      <version>${spring.version}version>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-jdbcartifactId>
      <version>${spring.version}version>
    dependency>

    
    
    <dependency>
      <groupId>org.springframework.securitygroupId>
      <artifactId>spring-security-webartifactId>
      <version>${spring.security.version}version>
    dependency>
    
    <dependency>
      <groupId>org.springframework.securitygroupId>
      <artifactId>spring-security-configartifactId>
      <version>${spring.security.version}version>
    dependency>
    
    <dependency>
      <groupId>org.springframework.securitygroupId>
      <artifactId>spring-security-taglibsartifactId>
      <version>${spring.security.version}version>
    dependency>

    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>javax.servlet-apiartifactId>
      <version>3.1.0version>
      <scope>providedscope>
    dependency>

  dependencies>

  <build>
    <finalName>ssm_spring_securityfinalName>
    <pluginManagement>
      <plugins>
        
        <plugin>
          <groupId>org.apache.maven.pluginsgroupId>
          <artifactId>maven-compiler-pluginartifactId>
          <version>3.2version>
          <configuration>
            <source>1.8source>
            <target>1.8target>
            <encoding>UTF-8encoding>
          configuration>
        plugin>
        <plugin>
          <groupId>org.apache.tomcat.mavengroupId>
          <artifactId>tomcat7-maven-pluginartifactId>
          <configuration>
            
            <port>8080port>
            
            <path>/path>
          configuration>
        plugin>


        <plugin>
          <artifactId>maven-clean-pluginartifactId>
          <version>3.1.0version>
        plugin>
        
        <plugin>
          <artifactId>maven-resources-pluginartifactId>
          <version>3.0.2version>
        plugin>
        <plugin>
          <artifactId>maven-compiler-pluginartifactId>
          <version>3.8.0version>
        plugin>
        <plugin>
          <artifactId>maven-surefire-pluginartifactId>
          <version>2.22.1version>
        plugin>
        <plugin>
          <artifactId>maven-war-pluginartifactId>
          <version>3.2.2version>
        plugin>
        <plugin>
          <artifactId>maven-install-pluginartifactId>
          <version>2.5.2version>
        plugin>
        <plugin>
          <artifactId>maven-deploy-pluginartifactId>
          <version>2.8.2version>
        plugin>
      plugins>
    pluginManagement>
  build>

3、配置spring-security.xml

在类加载路径resources下创建spring-security.xml配置文件,配置认证和授权信息


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security.xsd">

    

    
    <security:http auto-config="true" use-expressions="false">
        
        <security:intercept-url pattern="/**" access="ROLE_USER"/>
    security:http>

    
    <security:authentication-manager>
        
        <security:authentication-provider>
            
            <security:user-service>
                
                
                
                <security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
            security:user-service>
        security:authentication-provider>
    security:authentication-manager>
beans>

4、配置web.xml



<web-app>
  <display-name>Archetype Created Web Applicationdisplay-name>

  
  <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>classpath:spring-security.xmlparam-value>
  context-param>
  
  <filter>
    <filter-name>springSecurityFilterChainfilter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
  filter>
  <filter-mapping>
    <filter-name>springSecurityFilterChainfilter-name>
    <url-pattern>/*url-pattern>
  filter-mapping>

  
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>

web-app>

5、测试

没有自定义页面 系统默认提供的页面
ssm练习第三天_分页助手_安全框架_第4张图片

6、配置自定义登录页面

spring-security.xml.


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security.xsd">

    

    
    <security:http pattern="/login.jsp" security="none">security:http>
    <security:http pattern="/error.jsp" security="none">security:http>
    
    

    
    <security:http auto-config="true" use-expressions="false">
        
        <security:intercept-url pattern="/**" access="ROLE_USER"/>
        
        <security:form-login login-page="/login.jsp"
                             login-processing-url="/login"
                             default-target-url="/success.jsp"
                             authentication-failure-url="/error.jsp"
        >security:form-login>

        
        <security:csrf disabled="true">security:csrf>
        
        <security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.jsp"/>

    security:http>

    
    <security:authentication-manager>
        
        <security:authentication-provider>
            
            <security:user-service>
                
                
                
                <security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
            security:user-service>
        security:authentication-provider>
    security:authentication-manager>
beans>

7、login.jsp页面

<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
<h1>自定义的登录页面h1>
<form action="login" method="post">
    <table>
        <tr>
            <td>用户名:td>
            <td><input type="text" name="username" />td>
        tr>
        <tr>
            <td>密码:td>
            <td><input type="password" name="password" />td>
        tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" value="登录" />
                <input type="reset" value="重置" />td>
        tr>
    table>
form>

body>
html>

8、success.html页面

<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
success html<br>
<a href="logout">退出a>
body>
html>

9、error.html页面

<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
登录失败
body>
html>

四、项目集成SpringSecurity(项目实战中的应用)

1、添加spring-security.xml配置文件


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security.xsd">

    

    
    <security:http pattern="/login.jsp" security="none">security:http>
    <security:http pattern="/error.jsp" security="none">security:http>
    
    <security:http pattern="/favicon.ico" security="none">security:http>
    
    <security:http pattern="/css/**" security="none">security:http>
    <security:http pattern="/img/**" security="none">security:http>
    <security:http pattern="/plugins/**" security="none">security:http>



    
    <security:http auto-config="true" use-expressions="false">
        
        <security:intercept-url pattern="/**" access="ROLE_USER"/>
        
        <security:form-login login-page="/login.jsp"
                             login-processing-url="/login"
                             default-target-url="/index.jsp"
                             authentication-failure-url="/login.jsp"
        >security:form-login>

        
        <security:csrf disabled="true">security:csrf>
        
        <security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.jsp"/>

    security:http>

    
    <security:authentication-manager>
        
        <security:authentication-provider>
            
            <security:user-service>
                
                
                
                <security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
            security:user-service>
        security:authentication-provider>
    security:authentication-manager>
beans>

2、修改web.xml

委派代理过滤器链+多读取一个xml



<web-app>
  <display-name>Archetype Created Web Applicationdisplay-name>
  
  <context-param>
    <param-name>contextConfigLocationparam-name>
    
    <param-value>classpath*:spring/*.xml,classpath:spring-security.xmlparam-value>
  context-param>

  
  <filter>
    <filter-name>CharacterEncodingFilterfilter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
    <init-param>
      <param-name>encodingparam-name>
      <param-value>utf-8param-value>
    init-param>
  filter>

  
  <filter>
    <filter-name>springSecurityFilterChainfilter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
  filter>
  <filter-mapping>
    <filter-name>springSecurityFilterChainfilter-name>
    <url-pattern>/*url-pattern>
  filter-mapping>


  <filter-mapping>
    <filter-name>CharacterEncodingFilterfilter-name>
    <url-pattern>/*url-pattern>
  filter-mapping>

  
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>

  
  <servlet>
    <servlet-name>DispatcherServletservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    <init-param>
      <param-name>contextConfigLocationparam-name>
      <param-value>classpath:spring-mvc.xmlparam-value>
    init-param>
  servlet>
  <servlet-mapping>
    <servlet-name>DispatcherServletservlet-name>
    <url-pattern>/url-pattern>
  servlet-mapping>

web-app>

可以初步尝试是否生效 只不过此时用户密码静态的

注意:前端登录和注销的路径要改 Google浏览器+一些静态资源放行

login.jsp
在这里插入图片描述
header.jsp内注销改成 logout 最好都写绝对路径
ssm练习第三天_分页助手_安全框架_第5张图片

Google浏览器特殊问题,放行即可
ssm练习第三天_分页助手_安全框架_第6张图片
ssm练习第三天_分页助手_安全框架_第7张图片
静态资源也要放行

3、创建用户表和用户实体

create sequence user_seq;

CREATE TABLE sys_user(
  id number PRIMARY KEY,
  username VARCHAR2(50) unique,
  email VARCHAR2(50) ,
  password VARCHAR2(80),
  phoneNum VARCHAR2(20),
  status number
) 

select * from sys_user;
insert into sys_user values(user_seq.nextval,'zhangsan','[email protected]',
       '123','110',1);
insert into sys_user values(user_seq.nextval,'zhaosi','[email protected]',
       '123','120',1);

安全框架内有个类User,因此此处就换个名字吧

@Data
public class SysUser {
    private Long id;
    private String username;
    private String email;
    private String password;
    private String phoneNum;
    private int status;
}

4、修改spring-security.xml,修改认证方式为查询数据库


<security:authentication-manager>
    
    <security:authentication-provider user-service-ref="userServiceImpl">
    security:authentication-provider>
security:authentication-manager>

5、编写UserService业务代码

userService接口,接口集成UserDetailsService接口

public interface UserService extends UserDetailsService{
}

userServiceImpl实现

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    Userdao userdao;

    /**
     * 通过用户名 得到用户对象
     * 创建用户详情对象,返回
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //System.out.println(username);
        SysUser sysUser = userdao.findByUsername(username);
        if(sysUser==null) return null;
        //配置文件里没有指定角色了 需要自己创建角色对象
        //创建角色的集合对象
        Collection<GrantedAuthority> authorities=new ArrayList<>();
        //创建临时角色对象  正常情况下应该是数据库角色表中查的
        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
        //对象添加到集合中
        authorities.add(grantedAuthority);
        //User是安全框架内实现了UserDetails接口的一个类
        //第三个参数是:角色列表对象 (此处角色名ROLE_USER自己定义 xml里需要这个名字)
        //{noop}前缀表示不加密
        UserDetails user = new User(sysUser.getUsername(),"{noop}"+sysUser.getPassword(),authorities);
        return user;
    }
}

6、dao实现

public interface Userdao {
    //根据用户名查询用户对象 唯一对象(username必须唯一)
    @Select("select * from sys_user where username=#{username}")
    SysUser findByUsername(String username);
}

五、加入日志(复制一个文件就行了)

log4j2版本的日志操作傻瓜式的,将log4j2文件复制到dao层下的resources根目录下即可
注意复制别人的日志文件,包名要改正确


<Configuration status="warn" monitorInterval="30" strict="true" schema="Log4J-V2.2.xsd">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            
            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %level [%C{36}.%M] - %msg%n"/>
        Console>
        
        <file name="myLogFile" fileName="d:/log/ssm.log" append="true">
            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %level [%C{36}.%M] - %msg%n"/>
        file>
    Appenders>

    <Loggers>
        
        <root level="info">
            
            <appenderRef ref="Console"/>
            <appender-ref ref="myLogFile"/>
        root>

        
        <logger name="cn.ahpu.service" level="debug" additivity="false">
            <appender-ref ref="Console"/>
            <appender-ref ref="myLogFile"/>
        logger>

        
        <logger name="cn.ahpu.dao" level="debug" additivity="false">
            <appender-ref ref="Console"/>
            <appender-ref ref="myLogFile"/>
        logger>
        
        <logger name="org.springframework.jdbc" level="debug" additivity="false">
            <appender-ref ref="Console"/>
            <appender-ref ref="myLogFile"/>
        logger>
    Loggers>
Configuration>

1.查看日志发现框架的分页查询是这么写的

SELECT * FROM ( SELECT TMP_PAGE.*, ROWNUM ROW_ID FROM ( select * from product ) TMP_PAGE WHERE ROWNUM <= ? ) WHERE ROW_ID > ? 
9(Integer), 6(Integer)

<=9不需要临时表也能得到,>6就必须利用临时表先生成了
换个角度,以后mysql还是oracle的分页查询,sql语句怎么写都不用自己考虑了,告诉mybatis数据库方言即可(或者直接自动选择)

2. log4j2日志输出自己的提示信息(替换sout输出) ★

web层需要输出日志 因此要依赖utils了

 <dependency>
    <groupId>cn.ahpugroupId>
     <artifactId>ssm_utils_331artifactId>
     <version>1.0-SNAPSHOTversion>
 dependency>

utils模块没有依赖dao层,还需要单独复制一下log4j2.xml了,不分模块没有这个问题。
ssm练习第三天_分页助手_安全框架_第8张图片

LogUtils.java

public class LogUtils {
    static Logger logger=LoggerFactory.getLogger(LogUtils.class);

    public static void print(Object info){
        logger.info(info.toString());
    }

    public static void print(Object[] info){
        logger.info(Arrays.toString(info));
    }
}

测试

ssm练习第三天_分页助手_安全框架_第9张图片
日志输出:

2020-05-09 22:29:33.621 [http-nio-8080-exec-7] INFO [cn.ahpu.utils.LogUtils.print] - PageInfo{pageNum=1, pageSize=5, size=5, startRow=1, endRow=5, total=12, pages=3, list=Page{count=true, pageNum=1, pageSize=5, startRow=0, endRow=5, total=12, pages=3, reasonable=false, pageSizeZero=false}, prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]}
2020-05-09 22:29:33.622 [http-nio-8080-exec-7] INFO [cn.ahpu.utils.LogUtils.print] - 本页数据Page{count=true, pageNum=1, pageSize=5, startRow=0, endRow=5, total=12, pages=3, reasonable=false, pageSizeZero=false}

附录:PageHelper分页插件的相关参数

  1. helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby**特别注意:**使用 SqlServer2012 数据库时,需要手动指定为sqlserver2012,否则会使用 SqlServer2005 的方式进行分页。 你也可以实现AbstractHelperDialect`,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。
  2. offsetAsPageNum:默认值为 false,该参数对使用 RowBounds 作为分页参数时有效。 当该参数设置为 true 时,会将 RowBounds 中的 offset 参数当成 pageNum 使用,可以用页码和页面大小两个参数进行分页。
  3. rowBoundsWithCount:默认值为false,该参数对使用 RowBounds 作为分页参数时有效。 当该参数设置为true时,使用 RowBounds 分页会进行 count 查询。
  4. pageSizeZero:默认值为 false,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit = 0 就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page 类型)。
  5. reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页,pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。
  6. params:为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
  7. supportMethodsArguments:支持通过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 com.github.pagehelper.test.basic 包下的 ArgumentsMapTestArgumentsObjTest
  8. autoRuntimeDialect:默认值为 false。设置为 true 时,允许在运行时根据多数据源自动识别对应方言的分页 (不支持自动选择sqlserver2012,只能使用sqlserver),用法和注意事项参考下面的场景五
  9. closeConn:默认值为 true。当使用运行时动态数据源或没有设置 helperDialect 属性自动获取数据库类型时,会自动获取一个数据库连接, 通过该属性来设置是否关闭获取的这个连接,默认true关闭,设置为 false 后,不会关闭获取的连接,这个参数的设置要根据自己选择的数据源来决定。

你可能感兴趣的:(后端框架-SSM,#,ssm实战)