@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;//当前页数据 数据库查询
}
/**
* 手动分页查询
* 用 @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;
}
接口
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;
}
/**
* 查询产品表总记录数
* 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);
<%@ 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是国内非常优秀的一款开源的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
添加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>
在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);
}
}
在你需要进行分页的 MyBatis 查询方法前调用PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。
public static <E> Page<E> startPage(int pageNum, int pageSize) {
return startPage(pageNum, pageSize, true);//参数被绑定到当前线程
}
参数:pageNum:当前页;pageSize:当前页显示的条数
创建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());
}
简单修改一下而已
/**
* 分页助手实现分页查询
* 用 @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;
}
接口
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;
}
之前的findAll 也可以直接调用service里的findAll
<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;
}
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
<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>
在类加载路径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>
<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>
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>
<%@ 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>
<%@ 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>
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
登录失败
body>
html>
<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>
委派代理过滤器链+多读取一个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>
可以初步尝试是否生效 只不过此时用户密码静态的
login.jsp
header.jsp内注销改成 logout 最好都写绝对路径
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;
}
<security:authentication-manager>
<security:authentication-provider user-service-ref="userServiceImpl">
security:authentication-provider>
security:authentication-manager>
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;
}
}
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>
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数据库方言即可(或者直接自动选择)
web层需要输出日志 因此要依赖utils了
<dependency>
<groupId>cn.ahpugroupId>
<artifactId>ssm_utils_331artifactId>
<version>1.0-SNAPSHOTversion>
dependency>
utils模块没有依赖dao层,还需要单独复制一下log4j2.xml了,不分模块没有这个问题。
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));
}
}
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}
:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置
helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:
oracle,
mysql,
mariadb,
sqlite,
hsqldb,
postgresql,
db2,
sqlserver,
informix,
h2,
sqlserver2012,
derby**特别注意:**使用 SqlServer2012 数据库时,需要手动指定为
sqlserver2012,否则会使用 SqlServer2005 的方式进行分页。 你也可以实现
AbstractHelperDialect`,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。offsetAsPageNum
:默认值为 false
,该参数对使用 RowBounds
作为分页参数时有效。 当该参数设置为 true
时,会将 RowBounds
中的 offset
参数当成 pageNum
使用,可以用页码和页面大小两个参数进行分页。rowBoundsWithCount
:默认值为false
,该参数对使用 RowBounds
作为分页参数时有效。 当该参数设置为true
时,使用 RowBounds
分页会进行 count 查询。pageSizeZero
:默认值为 false
,当该参数设置为 true
时,如果 pageSize=0
或者 RowBounds.limit = 0
就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page
类型)。reasonable
:分页合理化参数,默认值为false
。当该参数设置为 true
时,pageNum<=0
时会查询第一页,pageNum>pages
(超过总数时),会查询最后一页。默认false
时,直接根据参数进行查询。params
:为了支持startPage(Object params)
方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable
,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
。supportMethodsArguments
:支持通过 Mapper 接口参数来传递分页参数,默认值false
,分页插件会从查询方法的参数值中,自动根据上面 params
配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 com.github.pagehelper.test.basic
包下的 ArgumentsMapTest
和 ArgumentsObjTest
。autoRuntimeDialect
:默认值为 false
。设置为 true
时,允许在运行时根据多数据源自动识别对应方言的分页 (不支持自动选择sqlserver2012
,只能使用sqlserver
),用法和注意事项参考下面的场景五。closeConn
:默认值为 true
。当使用运行时动态数据源或没有设置 helperDialect
属性自动获取数据库类型时,会自动获取一个数据库连接, 通过该属性来设置是否关闭获取的这个连接,默认true
关闭,设置为 false
后,不会关闭获取的连接,这个参数的设置要根据自己选择的数据源来决定。