ssm 整合 (springmvc + spring + mybatis )

项目环境: eclipse  tomcat  mysql  jdk1.7  maven

 

框架:ssm

 

以下代码复制可用

项目结构

                                                            

    

 

 

自定义aop日志

1.自定义日志注解

 

package com.utils;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

 

// 在使用Retention时必须要提供一个RetentionPolicy的枚举类型参数  

// RetentionPolicy有三个枚举内容:CLASS RUNTIME SOURCE  

// CLASS, //编译程序将Annotation储存于class档中,缺省  

@Retention(RetentionPolicy.RUNTIME)  

// RUNTIME //编译程序将Annotation储存于class当中,可由JVM读入(通过反射机制)。这个功能搭配反射是非常强大的  

// @Target里面的ElementType是用来指定Annotation类型可以用在哪一些元素上的.说明一下:TYPE(类型), FIELD(属性),  

// METHOD(方法), PARAMETER(参数), CONSTRUCTOR(构造函数),LOCAL_VARIABLE(局部变量),  

// ANNOTATION_TYPE,PACKAGE(包),其中的TYPE(类型)是指可以用在Class,Interface,EnumAnnotation类型上.  

@Target(ElementType.METHOD)  

/**

 * 自定义日志注解

 * @作者  罗玲红

 *

 * @时间 2017年3月25日 下午3:50:09

 */

public @interface Loggable {  

  

    /**

     * @func 操作类型:四种(INSERT, UPDATE, SELECT, DELETE)

     */  

    public String optType();  

  

    /**

     * @func 描述

     */  

    public String describe();  

  

    /**

     * @func 日志模块,不同模块的日志保存到不同的日志表中

     */  

    public String module();  

}  

 

 

2.记录日志的实体类

package com.entry;

 

import java.security.Timestamp;

 

/**

 * 记录日志的实体类

 * @作者  罗玲红

 *

 * @时间 2017年3月25日 下午10:28:40

 */

public class Log {

   /**

    * 记录日志的id

    */

   private Integer id;

   /**

    * 操作时间

    */

   private Timestamp optTime;

   /**

    * 操作人

    */

   private String optMan;

   /**

    * 日志类型,比如CURD

    */

   private String logType;

   /**

    * 描述

    */

   private String desc;

   

   /**

    * 状态

    */

   private String status;

   /**

    * 异常

    */

   private String exception;

   

public String getException() {

 return exception;

    }

    public void setException(String exception) {

 this.exception = exception;

    }

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public Timestamp getOptTime() {

return optTime;

}

public void setOptTime(Timestamp optTime) {

this.optTime = optTime;

}

public String getOptMan() {

return optMan;

}

public void setOptMan(String optMan) {

this.optMan = optMan;

}

public String getLogType() {

return logType;

}

public void setLogType(String logType) {

this.logType = logType;

}

public String getDesc() {

return desc;

}

public void setDesc(String desc) {

this.desc = desc;

}

public String getStatus() {

return status;

}

public void setStatus(String status) {

this.status = status;

}

@Override

public String toString() {

return "Log [id=" + id + ", optTime=" + optTime + ", optMan=" + optMan + ", logType=" + logType + ", desc="

+ desc + ", status=" + status + "]";

}

}

3.数据库中不同的日志模板

package com.finall;

 

 

/**

 * 数据库中不同的日志模板

 * @作者  罗玲红

 *

 * @时间 2017年3月25日 下午10:27:42

 */

public class LogModule {  

    

/**

 * 登陆日志表

 */

    public static final String Login = "login_log";

    

    /**

     * 账户日志表

     */

    public static final String Account="account_log";

    /**

     * 字典日志表

     */

    public static final String Dictionary="dictionary_log";

    

    /**

     * 角色日志表

     */

    public static final String Role="role_log";

    

    /**

     * 图书日志表

     */

    public static final String Book="book_log";

    

    /**

     * 期刊日志表

     */

    public static final String Journal="journal_log";

    

    /**

     * 借书卡日志表

     */

    public static final String Borrower="borrower_log";

    

    /**

     * 借书日志表

     */

    public static final String BorrowBooks="borrowBooks_log";

    

    /**

     * 押金日志表

     */

    public static final String Deposit="deposit_log";

    

    /**

     * 还书日志表

     */

    public static final String ReturnBook="returnBook_log";

    

    /**

     * 滞纳金日志表

     */

    public static final String OverdueFine="overdueFine_log";

    

    /**

     * 损书还书日志表

     */

    public static final String Damage="damage_log";

    

    public static final String LossBook="lossbook_log";

 

}

4.数据库操作类型

package com.finall;

 

/**

 * 数据库操作类型

 * @作者  罗玲红

 *

 * @时间 2017年3月25日 下午10:28:13

 */

public class LogOptType {  

    

/**

 * 插入

 */

    public static final String INSERT = "INSERT";  

    /**

     * 修改

     */

    public static final String UPDATE = "UPDATE";

    /**

     * 查询

     */

    public static final String SELECT = "SELECT";

    /**

     * 删除

     */

    public static final String DELETE = "DELETE";  

    

    /**

     * 登陆

     */

    public static final String LOGIN="LOGIN";

}  

 

 

 

 

Log4j日志

log4j.rootLogger=debug,stdout,info,debug,error

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n

 

#\u5E94\u7528\u4E8E\u63A7\u5236\u53F0

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 

log4j.appender.Threshold=DEBUG 

log4j.appender.CONSOLE.Target=System.out 

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout 

log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n 

#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n

 

#Generate one file per hour

log4j.logger.info=info

log4j.appender.info=org.apache.log4j.DailyRollingFileAppender

log4j.appender.info.layout=org.apache.log4j.PatternLayout

log4j.appender.info.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n

log4j.appender.info.datePattern='.'yyyy-MM-dd-HH

log4j.appender.info.Threshold = INFO 

log4j.appender.info.append=true

log4j.appender.info.File=E:\\flowUnfyPay\\logs\\info.log

 

#Generate two file per hour

log4j.logger.debug=debug

log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender

log4j.appender.debug.layout=org.apache.log4j.PatternLayout

log4j.appender.debug.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n

log4j.appender.debug.datePattern='.'yyyy-MM-dd-HH-a

log4j.appender.debug.Threshold = DEBUG 

log4j.appender.debug.append=true

log4j.appender.debug.File=E:\\flowUnfyPay\\logs\\debug.log

 

#Generate one file every day

log4j.logger.error=error

log4j.appender.error=org.apache.log4j.DailyRollingFileAppender

log4j.appender.error.layout=org.apache.log4j.PatternLayout

log4j.appender.error.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n

log4j.appender.error.datePattern='.'yyyy-MM-dd

log4j.appender.error.Threshold = ERROR 

log4j.appender.error.append=true

log4j.appender.error.File=E:\\flowUnfyPay\\logs\\error.log

 

传递Json数据

1.所需要的jar包:

 

 

1.springmvc.xml中配置

<!-- 配置项目中需要的jackson bean -->

<bean  class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"  p:ignoreDefaultModelOnRedirect="true">

<property name="messageConverters">

<list>

<bean  class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />

</list>

</property>

</bean>

 

2.java的使用

@Controller

@RequestMapping("/account")

public class AccountController {

 

@Autowired

private AccountService accountServiceImpl;

 

/**

 * 得到列表分页数据

 *

 * @param nowPage

 *            当前页

 * @return

*/

@RequestMapping(value = { "/list/{nowPage}" }, method = RequestMethod.POST)

@ResponseBody

public Page<Account> json(@PathVariable("nowPage") Integer nowPage) {

Page<Account> page = accountServiceImpl.getList(nowPage, 7);

return page;

}

 

}

 

3.在页面的使用

 

<%@ page language="java" contentType="text/html; charset=utf-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<head>

<title>信息页面</title>

<style> 

.page-right{float:right;width:400px;height:50px;}

</style>

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/page.css">

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/demo.css">

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/layui/css/layui.css">

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/style.css" />

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/basictable.css" />

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/loginDialog.css">

<script src="${pageContext.request.contextPath}/js/jquery-2.1.1.min.js" type="text/javascript"></script>

<script src="<%=request.getContextPath() %>/js/page.js" type="text/javascript"></script>

<script type="text/javascript">

$(function(){

$.ajax({

        type: "POST",

        contentType : "application/json",

        dataType: "json",

        url: "<%=request.getContextPath()%>/account/query/1",

        success: function (data) {

        dis(data);

        }

    });

});

function dis(data){

$("#nowPage").val(data.nowPage);

    $("#pageNum").val(data.pageNum);

    $("#countPage").val(data.countPage);

    $.each(data.rows, function(i, acc) {

$("#tbody").append("<tr><td>"+(acc.id)+"</td><td>"+(acc.account)+"</td><td>

< a οnclick='update("+(acc.id)+");'id='edit' class='layui-btn layui-btn-mini layui-btn-normal'>编辑</a>"+

"<a οnclick='del("+(acc.id)+");' id = 'del' data-id='1' data-opt='del' class='layui-btn layui-btn-danger layui-btn-mini'>删除</a></tr>");

        });

    table();

}

var url = "<%=request.getContextPath()%>/account/query"

function update(id) {

var href="${pageContext.request.contextPath}/account/getUpdate/"+id;

$("#updFormId").attr("action",href).submit();

    }

 

function del(id){

if(confirm("确认要删除 "+ id +"?")){

var href ="${pageContext.request.contextPath}/account/del/"+id;

$("#delFormId").attr("action",href).submit();

return false;

    }

}

</script>

</head>

<body>

<input id="pageNum" type="hidden" />

<input id="nowPage" type="hidden" />

<input id="countPage" type="hidden" />

<div class="container">

<div id="page">

<table id="table">

<blockquote class="layui-elem-quote">

<fieldset class="layui-elem-field">

<div align="right">

<a href="<%=request.getContextPath()%>/account/addList" 

                                                                       class="layui-btn layui-btn-small layui-btn-normal" id="add">

添加信息

</a>

<div class="layui-input-inline">

<input placeholder="请输入相关信息" class="layui-input">

</div>

<div style="float:left">

<font class="layui-btn" size=6 face="楷体">账户列表页面</font>

</div>

</div>

</blockquote>

<thead>

<tr>

<th>ID</th>

<th>账户</th>

<th>操作</th>

</tr>

</thead>

<tbody id ="tbody">

</tbody>

</fieldset>

</table>

<br /> 

<div class="page-right"></div>

<script src="${pageContext.request.contextPath}/js/table.js" type="text/javascript"></script>

</div>

</div>

<script src="${pageContext.request.contextPath}/layui/layui.js" type="text/javascript"></script>

<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.basictable.min.js"></script>

<form id="delFormId" action="" method="POST">

<input type="hidden" name="_method" value="DELETE">

</form>

<form id="updFormId" action="" method="POST">

<input type="hidden" name="_method" value="PUT">

</form>

</body>

</html>

4.Page.js

function table() {

var pageNum = $("#pageNum").val();

var nowPage = $("#nowPage").val();

var countPage = $("#countPage").val();

$('.page-right').html('');

var pringString = "";

pringString += "<ul id='pagination-flickr'>";

if (nowPage <= 1) {

pringString += "<li class='previous-off'><a href='javascript:;'>首页</a></li>";

pringString += "<li class='previous-off'><a href='javascript:;'>«上一页</a></li>";

} else {

var now = parseInt(nowPage);

pringString += "<li class='previous-off'><a href='javascript:;' οnclick='first(1)'>首页</a></li>";

pringString += "<li class='previous-off'><a href='javascript:;' οnclick='pre("+ (now - 1) + ")'>«上一页</a></li>";

}

var count = parseInt(countPage);

var pArr = pageNum.split(',');

for ( var i in pArr) {

if (nowPage == i) {

pringString += "<li class='active'>" + i + "</li>";

} else if (i > 0 && i <= count) {

pringString += "<li><a href='javascript:;' οnclick='oncl(" + i+ ")' id='sum' >" + i + "</a></li>";

}

}

if (nowPage > count - 1) {

pringString += "<li class='next'><a href='javascript:;'>下一页 »</a></li>";

pringString += "<li class='next'><a href='javascript:;'>尾页</a></li>";

} else {

var now = parseInt(nowPage);

pringString += "<li class='next'><a href='javascript:;' οnclick='next("+ (now + 1) + ")' >下一页</a></li>";

pringString += "<li class='next'><a href='javascript:;' οnclick='last("+ (count) + ")'>尾页</a></li>";

}

pringString += "</ul>";

pringString +="<span><li class='next'>总页数    "+countPage+"</li></span>"

$('.page-right').append(pringString);

}

function next(nowPage) {

var u = url + "/" + nowPage;

post(u);

}

function pre(nowPage) {

var u = url + "/" + nowPage;

post(u);

}

function first(nowPage) {

var u = url + "/" + nowPage;

post(u);

}

function last(nowPage) {

var u = url + "/" + nowPage;

post(u);

}

function oncl(nowPage) {

var u = url + "/" + nowPage;

post(u);

}

function post(u) {

$.ajax({

        type: "POST",

        contentType : "application/json",

        dataType: "json",

        url: u,

        success: function (data) {

        $("#tbody").html('');

        dis(data);

        }

    });

}

 

Ajax使用字典

(Jquery+json的二级联动)(可拼接下拉框,复选框)

1.java中的使用

package com.controller;

 

import java.util.List;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.ResponseBody;

 

import com.entry.Book;

import com.entry.BookType;

import com.entry.DamageLevel;

import com.entry.Press;

import com.entry.Role;

import com.interfac.DictionaryService;

 

 

/**

 * 字典Controller

 * @作者  罗玲红

 *

 * @时间 2017329日 上午11:22:52

 * https://my.oschina.net/u/780884/blog/223595

 * http://www.cnblogs.com/zlay0701/p/5919841.html

 * http://m.blog.csdn.net/article/details?id=52537120  spring传递json格式的数据)

 */

@Controller

@RequestMapping(value="/dictionary")

public class DictionaryController {

    @Autowired

    private DictionaryService dictionaryServiceImpl;

    

    

    @RequestMapping(value="/getName",method=RequestMethod.POST)

    @ResponseBody  

public List<BookType> getName(){

List<BookType> list=dictionaryServiceImpl.getListByPid();

        return list;

}

    

    @RequestMapping(value="/getList",method=RequestMethod.POST)

    @ResponseBody

    public List<BookType> getListBookName(Integer id){

    List<BookType> list=dictionaryServiceImpl.getListById(id);

return list;

}

}

 

2.在页面的使用

<%@ page language="java" contentType="text/html; charset=utf-8"%>

<head>

<title>字典列表页面</title>

<script src="${pageContext.request.contextPath}/js/jquery-2.1.1.min.js"></script>

</head>

<script type="text/javascript">

    //图书类型的列表

    $(function initProvinces() {

        $('#bookType').empty();

        $('#bookType').append("<option>请选择书的类型</option>");

        $.ajax({

            type : "POST",

            dataType : "json",  

            url :"${pageContext.request.contextPath}/dictionary/getName",

            success : function(data) {

                $.each(data, function(i,list) {

                    $('#bookType').append("<option value='" + list.id +"'>" + list.name + "</option>"+"<br>")

                });

            }

       });

        

    });

    

    $(function(){

    $('#bookType').on("change",function(){

    var pid = $(this).val();

    initCities(pid)  //图书类下面的图书

    })

    })

    

    function initCities(pid) {

        $('#bookName').empty();

        $.ajax({

            type : "POST",

            dataType : "json",  

            url : "${pageContext.request.contextPath}/dictionary/getList",

            data:{"id":pid},

            success : function(data) {

                $.each(data, function(i, list) {

                    $("<option value='"+list.id +"'>"+ list.name +"</option><br>").appendTo($('#bookName'));

                });

            }

        });

    }

</script>

<body>

 添加图书:

 <select id='bookType' style="width:125px">

    <option>请选择书的类型</option>

 </select>

 <select id='bookName' style="width:125px">

    <option>请选择书的名称</option>

 </select>

</body>

</html>

Spring-security安全框架

1.实现权限管理所需要的jar包:

 

2.web.xml配置

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://java.sun.com/xml/ns/javaee"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

version="2.5">

<!-- 解决post请求中文乱码 -->

<filter>

<filter-name>encodingFilter</filter-name>

<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

<init-param>

<param-name>forceEncoding</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<!-- 允许 将post请求转为delete,put请求方式 -->

<filter>

<filter-name>HiddenHttpMethodFilter</filter-name>

<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>HiddenHttpMethodFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<servlet>

<!-- 配置spring的分发器 -->

<servlet-name>spring</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<!-- 初始化加载配置文件 -->

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:*.xml</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>spring</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

  

  <!-- Spring Security 权限框架 -->

<filter>  

   <filter-name>springSecurityFilterChain</filter-name>

   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

</filter>

<filter-mapping>

   <filter-name>springSecurityFilterChain</filter-name>

   <url-pattern>/*</url-pattern>

</filter-mapping>

    <!--处理拦截器拦截的静态资源  -->

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>/css/*</url-pattern>

<url-pattern>/data/*</url-pattern>

<url-pattern>/js/*</url-pattern>

<url-pattern>/plugins/*</url-pattern>

<url-pattern>/images/*</url-pattern>

<url-pattern>/layui/*</url-pattern>

<url-pattern>/assets/*</url-pattern>

</servlet-mapping>

</web-app>

 

 

3.创建登录验证过滤器

包括两个类:

 

package com.security;

import java.io.IOException;  

import javax.servlet.ServletException;  

import javax.servlet.http.HttpServletRequest;  

import javax.servlet.http.HttpServletResponse;  

import org.springframework.security.core.Authentication;  

import org.springframework.security.core.userdetails.UserDetails;  

import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;  

  

/**

 * 处理管理人员登陆日志

 * @作者  罗玲红

 *

 * @时间 2017年4月10日 上午10:10:09

 */

public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{  

      

    @Override  

    public void onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response,

    Authentication authentication) throws IOException,ServletException {  

    

        UserDetails userDetails = (UserDetails)authentication.getPrincipal();  

        

        System.out.println("管理员 " + userDetails.getUsername() + " 登录");

        request.getSession().setAttribute("account",userDetails.getUsername());  //因为本项目用了aop记录日志,所以就在此将session重新设置进去

        

        super.onAuthenticationSuccess(request, response, authentication);  

    }  

      

}  

 

 

package com.security;

import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;  

 

/**

 * 权限过滤

 * @作者  罗玲红

 * http://hotstrong.iteye.com/blog/1160153

 * @时间 2017年4月10日 上午10:10:49

 */

public class LoginUsernamePasswordAuthenticationFilter extends  

        UsernamePasswordAuthenticationFilter {  

      

}

  

4.spring-security.xml配置

<?xml version="1.0" encoding="UTF-8"?>  

    <beans:beans xmlns="http://www.springframework.org/schema/security"  

        xmlns:b="http://www.springframework.org/schema/beans" xmlns:beans="http://www.springframework.org/schema/beans"  

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  

       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

        <http >  

            <!-- 不拦截login.jsp -->  

            <intercept-url pattern="/views/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />  

            <!--仅拦截到manager下面的内容,具备access对应权限的-->  

            <intercept-url pattern="/**"/>  

            <!-- 设置登录过滤器 -->  

            <custom-filter before="FORM_LOGIN_FILTER" ref="authenticationProcessingFilter" />  

            <!-- 登录表单设置 -->  

            <form-login login-page="/views/login"  

                default-target-url="/views/main"  

                authentication-failure-url="/views/login" />  

              

            <!-- 登出操作后跳转到该页面 -->  

            <logout logout-success-url="/views/loggedout"  

                delete-cookies="JSESSIONID" />  

            <remember-me />  

              

            <!-- SESSION超时后跳转到该页面 -->  

            <session-management invalid-session-url="/views/timeout">  

            </session-management>  

        </http>  

          

        <authentication-manager alias="authenticationManager">  

            <authentication-provider>  

                <!-- 直接使用SQL语句查询登录帐号对应权限,  

                    users-by-username-query:查询登录用户是否存在  

                    authorities-by-username-query:查询登录用户权限(登录用户可以不属于任何组,从power表中获取权限)  

                    group-authorities-by-username-query:查询登录用户所在组的权限  

                -->  

                <jdbc-user-service data-source-ref="dataSource"  

                    users-by-username-query="select a.account,a.`password`,true from account as a where a.account = ?"  

                    authorities-by-username-query="select a.account,p.`name` from account as a LEFT OUTER JOIN roleaccount as ra on (a.id=ra.accountId)

                                         LEFT OUTER JOIN role as r on (r.`code`=ra.roleId )  LEFT OUTER JOIN rolepower as rp on (rp.roleCode=r.`code`)

                                        LEFT OUTER JOIN power as p on (rp.powerId=p.id ) where a.account = ?" />  

            </authentication-provider>  

        </authentication-manager>  

          

        <!-- 自定义消息 -->  

        <b:bean id="messageSource"  

            class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  

            <b:property name="basename"  

                value="classpath:org/springframework/security/messages" />  

        </b:bean>  

          

        <!-- 定制登录过滤器 -->  

        <beans:bean id="loginSuccessHandler" class="com.security.LoginSuccessHandler">  

            <b:property name="defaultTargetUrl">  

                <!-- 登录成功后转发到该页面 -->  

                <b:value>/views/main</b:value>  

            </b:property>  

        </beans:bean>  

       <beans:bean id="authenticationProcessingFilter" class="com.security.LoginUsernamePasswordAuthenticationFilter">    

       <beans:property name="authenticationSuccessHandler" ref="loginSuccessHandler"></beans:property>    

       <beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler"></beans:property>    

       <beans:property name="authenticationManager" ref="authenticationManager"></beans:property>    

        </beans:bean>  

        <beans:bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">    

        <beans:property name="defaultFailureUrl">  

            <!-- 登录失败后转发到该页面 -->  

            <beans:value>/views/login</beans:value>    

        </beans:property>  

        </beans:bean>  

         <!-- 自定义拦截器 -->

</beans:beans>  

 

 

5.页面使用

导入标签:

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>

 

<security:authorize ifAnyGranted="ROLE_ADMIN,ROLE_BOOK_SELECT">

<a class="waves-effect" href="javascript:Tab.addTab('图书管理', '${pageContext.request.contextPath}/views/book/list');">图书管理</a>

</security:authorize>

 

 

 

Springmvc Spring Mybatis Maven 项目管理

 

2.pom.xml

注意:当导入的jar比eclipse自带的版本低的时候会报错,mybatis-spring的版本要1.3.0

<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.test.mybatis</groupId>

<artifactId>firstMybatis</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>firstMybatis Maven Webapp</name>

<url>http://maven.apache.org</url>

<properties>

<!-- spring版本号 -->

<spring.version>4.3.5.RELEASE</spring.version>

<!-- mybatis版本号 -->

<mybatis.version>3.4.1</mybatis.version>

<!-- slf4j版本 -->

<slf4j.version>1.7.7</slf4j.version>

<!-- log4j日志文件管理包版本 -->

<log4j.version>1.2.17</log4j.version>

<!-- springsecurity 版本号 -->

<org.springframework.security.version>3.2.9.RELEASE</org.springframework.security.version>

<!-- jackson版本 -->

<com.fasterxml.jackson.version>2.8.2</com.fasterxml.jackson.version>

<!-- junit测试版本 -->

<junit.version>4.10</junit.version>

<!-- c3p0版本号 -->

<com.mchange>0.9.2.1</com.mchange>

<!-- mybatis-spring 版本 -->

<org.mybatis.spring>1.3.0</org.mybatis.spring>

<!-- mysql链接包 -->

<mysql.connector>5.1.39</mysql.connector>

</properties>

 

<dependencies>

<dependency>

<groupId>com.mchange</groupId>

<artifactId>c3p0</artifactId>

<version>${com.mchange}</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>${junit.version}</version>

</dependency>

<!-- spring核心包 -->

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-expression</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-beans</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-web</artifactId>

<version>${org.springframework.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-taglibs</artifactId>

<version>${org.springframework.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-config</artifactId>

<version>${org.springframework.security.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-web</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-oxm</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aspects</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-tx</artifactId>

<version>${spring.version}</version>

</dependency>

 

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-jdbc</artifactId>

<version>${spring.version}</version>

</dependency>

 

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aop</artifactId>

<version>${spring.version}</version>

</dependency>

 

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context-support</artifactId>

<version>${spring.version}</version>

</dependency>

 

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-test</artifactId>

<version>${spring.version}</version>

</dependency>

<!-- mybatis核心包 -->

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>${mybatis.version}</version>

</dependency>

<!-- mybatis/spring包 -->

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis-spring</artifactId>

<version>${org.mybatis.spring}</version>

</dependency>

<!-- 导入java ee jar 包 -->

<dependency>

<groupId>javax</groupId>

<artifactId>javaee-api</artifactId>

<version>7.0</version>

</dependency>

 

<dependency>

<groupId>org.hamcrest</groupId>

<artifactId>hamcrest-all</artifactId>

<version>1.3</version>

</dependency>

<!-- 导入Mysql数据库链接jar包 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>${mysql.connector}</version>

</dependency>

<!-- 导入dbcpjar包,用来在applicationContext.xml中配置数据库 -->

<dependency>

<groupId>commons-dbcp</groupId>

<artifactId>commons-dbcp</artifactId>

<version>1.2.2</version>

</dependency>

<!-- JSTL标签类 -->

<dependency>

<groupId>jstl</groupId>

<artifactId>jstl</artifactId>

<version>1.2</version>

</dependency>

 

<!-- 格式化对象,方便输出日志 -->

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>fastjson</artifactId>

<version>1.1.41</version>

</dependency>

 

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>${slf4j.version}</version>

</dependency>

 

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>${slf4j.version}</version>

</dependency>

<!-- log end -->

<!-- 上传组件包 -->

<dependency>

<groupId>commons-fileupload</groupId>

<artifactId>commons-fileupload</artifactId>

<version>1.3.1</version>

</dependency>

<dependency>

<groupId>commons-io</groupId>

<artifactId>commons-io</artifactId>

<version>2.4</version>

</dependency>

<dependency>

<groupId>commons-codec</groupId>

<artifactId>commons-codec</artifactId>

<version>1.9</version>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-validator</artifactId>

<version>5.4.1.Final</version>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-validator</artifactId>

<version>5.4.1.Final</version>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-core</artifactId>

<version>${com.fasterxml.jackson.version}</version>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-annotations</artifactId>

<version>${com.fasterxml.jackson.version}</version>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

<version>${com.fasterxml.jackson.version}</version>

</dependency>

<dependency>

<groupId>jstl</groupId>

<artifactId>jstl</artifactId>

<version>1.2</version>

</dependency>

<dependency>

<groupId>taglibs</groupId>

<artifactId>standard</artifactId>

<version>1.1.2</version>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>javax.servlet-api</artifactId>

<version>3.1.0</version>

</dependency>

<dependency>

<groupId>org.apache.logging.log4j</groupId>

<artifactId>log4j-core</artifactId>

<version>2.7</version>

</dependency>

<!--Log4j2配置 -->

<dependency>

<groupId>org.apache.logging.log4j</groupId>

<artifactId>log4j-api</artifactId>

<version>2.5</version>

</dependency>

<dependency>

<groupId>org.apache.logging.log4j</groupId>

<artifactId>log4j-core</artifactId>

<version>2.5</version>

</dependency>

<dependency>

<groupId>org.apache.logging.log4j</groupId>

<artifactId>log4j-web</artifactId>

<version>2.5</version>

</dependency>

<!--解决Spring使用slf4j输出日志与log4j冲突的问题 -->

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>1.7.13</version>

</dependency>

 

</dependencies>

<build>

<finalName>library</finalName>

</build>

</project>

 

3.web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://java.sun.com/xml/ns/javaee"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

version="2.5">

 

<!-- 解决Post请求中文乱码问题  -->

<filter>

<filter-name>encodingFilter</filter-name>

<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

<init-param>

<param-name>forceEncoding</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<!-- 使得支持 GET POST PUT DELETE 请求 -->

<filter>

<filter-name>HiddenHttpMethodFilter</filter-name>

<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>HiddenHttpMethodFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

 

<!-- springSecurity权限控制框架的配置 -->

<filter>

<filter-name>springSecurityFilterChain</filter-name>

<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

</filter>

<filter-mapping>

<filter-name>springSecurityFilterChain</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

 

<!-- spring的配置 -->

<servlet>

<!-- 配置springmvc的分发器 -->

<servlet-name>spring</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<!-- 初始化加载spring的配置文件 -->

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:*.xml</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>spring</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

</web-app>

 

spring框架的启动入口 ContextLoaderListener 2 作用:在启动Web 容器时,自动装配Spring applicationContext.xml 的配置信息,所有有时候报错是因为没有配置applicationContext.xml

 

<context-param>

 <param-name>contextConfigLocation</param-name> 

<param-value>classpath:applicationContext.xml</param-value> 

</context-param> 

<listener> 

<listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> 

</listener>

4.配置applicationContext-dataSource.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

 

<context:property-placeholder location="classpath:db.properties" />

 

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

<property name="dataSource" ref="dataSource"></property>

</bean>

 

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="user" value="${jdbc.user}"></property>

<property name="password" value="${jdbc.password}"></property>

<property name="driverClass" value="${jdbc.driverClass}"></property>

<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>

<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>

<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>

</bean>

</beans>

 

5.配置applicationContext-springmvc.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:mvc="http://www.springframework.org/schema/mvc"

xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

<mvc:annotation-driven />

<mvc:default-servlet-handler />

<!-- 如果需要用<mvc:view-controller>,那么一定要加上<mvc:annotation-driven />,否则除<mvc:view-controller>配置有效外,其他的url都为404 -->

<mvc:view-controller path="/login" view-name="login" />

<mvc:view-controller path="/main" view-name="main" />

<mvc:view-controller path="/loggedout" view-name="loggedout" />

<mvc:view-controller path="/timeout" view-name="timeout" />

 

<bean id="multipartResolver"

class="org.springframework.web.multipart.support.StandardServletMultipartResolver">

</bean>

 

<!-- 配置springmvc的视图渲染器 -->

<bean id="jspViewResolver"

class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="viewClass"

value="org.springframework.web.servlet.view.JstlView" />

<property name="prefix" value="/WEB-INF/views/" />

<property name="suffix" value=".jsp" />

</bean>

<!-- 配置项目中需要的jackson bean -->

<bean

class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"

p:ignoreDefaultModelOnRedirect="true">

<property name="messageConverters">

<list>

<bean

class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />

</list>

</property>

</bean>

 

</beans>

 

6.配置applicationContext-mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

 

<import resource="applicationContext-dataSource.xml" />

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

<!-- 自动扫描mapping.xml文件 -->

<property name="mapperLocations" value="classpath:com/mapper/*.xml"></property>

<!-- 类型命名 -->

<property name="typeAliasesPackage" value="com.entry" />

</bean>

 

<!-- 配置mapper扫描器 -->

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

<!-- 扫描对应的接口的路径,如果需要扫描多个包中间用半角逗号隔开 -->

<property name="basePackage" value="com.interDao"></property>

</bean>

</beans>

 

7.配置applicationContext-tx.xml

 

为了让大家看的更加清楚,这里我使用了两种事务配置方式,在项目中一般使用一种事务配置方式(注解方式,xml配置方式,推荐使用xml配置方式)

事务一般都在service中使用,所以aop记录日志都切至service层

1,全注解方式 applicationContext-tx.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:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

 

<!-- 引入是为了去消黄色警告-->

<import resource="applicationContext-mybatis.xml" />

<bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"></property>

</bean>

<!-- 需要配置注解驱动 -->

<tx:annotation-driven transaction-manager="transactionManager" order="3" />

</beans>

8.配置applicationContext-aop.xml

aop这里事务的配置方式的是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:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

 

<context:component-scan base-package="com"></context:component-scan>

 

<import resource="applicationContext-mybatis.xml" />

<import resource="applicationContext-tx.xml" />

<aop:config>

 <!-- 配置aop切点  -->

<aop:pointcut expression="execution(* com.service.*.*(..))" id="log" />

<aop:advisor advice-ref="txAdvice" pointcut-ref="log" order="2" />

<aop:aspect id="log" ref="aopLogHandler" order="1">

<aop:before method="before" pointcut-ref="log" />

<aop:after-returning method="returning" pointcut-ref="log" />

<aop:after-throwing method="throwing"  pointcut-ref="log" throwing="e" />

</aop:aspect>

</aop:config>

<tx:advice id="txAdvice" transaction-manager="transactionManager">

<tx:attributes>

<tx:method name="return*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

<tx:method name="throw*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

</tx:attributes>

</tx:advice>

 

</beans>

注意看这两个配置文件中红色标记处,这是设置优先级,用以保证事务回滚时,aop中的数据不会回滚

 

9.配置 applicationContext-security.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/security"

xmlns:b="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:beans="http://www.springframework.org/schema/beans"

xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

<http pattern="/getCodeImgServlet" security="none"/>

<http>

<!-- 不拦截login.jsp -->

<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />

<!--仅拦截到manager下面的内容,具备access对应权限的 -->

<intercept-url pattern="/com/**" />

<!-- 设置登录过滤器 -->

<custom-filter before="FORM_LOGIN_FILTER" ref="authenticationProcessingFilter" />

<!-- 登录表单设置 -->

<form-login login-page="/login" default-target-url="/main" authentication-failure-url="/login" />

<!-- 登出操作后跳转到该页面 -->

<logout logout-success-url="/loggedout" delete-cookies="JSESSIONID" />

<remember-me />

 

<!-- SESSION超时后跳转到该页面 -->

<session-management invalid-session-url="/timeout"></session-management>

</http>

 

<authentication-manager alias="authenticationManager">

<authentication-provider>

<!-- 直接使用SQL语句查询登录帐号对应权限, users-by-username-query:查询登录用户是否存在 authorities-by-username-query:查询登录用户权限(登录用户可以不属于任何组,从t_user_role表中获取权限)

group-authorities-by-username-query:查询登录用户所在组的权限 -->

<jdbc-user-service data-source-ref="dataSource"

users-by-username-query="SELECT ACC.ACCOUNT ,ACC.`PASSWORD`,true FROM ACCOUNT AS ACC WHERE ACC.account= ?"

authorities-by-username-query="SELECT A.account,P.`name` FROM ACCOUNT AS A

LEFT OUTER JOIN ROLEACCOUNT AS RA ON (A.id = RA.accountId)

LEFT OUTER JOIN ROLE AS R ON (R.id = RA.roleId)

LEFT OUTER JOIN ROLEPOWERS AS RP ON (RP.roleId = R.id)

LEFT OUTER JOIN POWERS AS P ON (P.id = RP.powersId)

WHERE A.account = ?" />

</authentication-provider>

</authentication-manager>

 

<!-- 自定义消息 -->

<b:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

<b:property name="basename"

value="classpath:org/springframework/security/messages" />

</b:bean>

 

<!-- 定制登录过滤器 -->

<beans:bean id="loginSuccessHandler" class="com.security.LoginSuccessHandler">

<b:property name="defaultTargetUrl">

<!-- 登录成功后转发到该页面 -->

<b:value>/main</b:value>

</b:property>

</beans:bean>

<beans:bean id="authenticationProcessingFilter" class="com.security.LoginUsernamePasswordAuthenticationFilter">

<beans:property name="authenticationSuccessHandler" ref="loginSuccessHandler"></beans:property>

<beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler"></beans:property>

<beans:property name="authenticationManager" ref="authenticationManager"></beans:property>

</beans:bean>

<beans:bean id="authenticationFailureHandler"

class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">

<beans:property name="defaultFailureUrl">

<!-- 登录失败后转发到该页面 -->

<beans:value>/login</beans:value>

</beans:property>

</beans:bean>

</beans:beans>

 

10.讲述一下springSecurity权限框架的简单使用

上面 applicationContext-security.xml中有两个自定义类

 

public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{  

      

    @Override  

    @Loggable(describe = "登陆验证", module = LogModule.ACCOUNT, optType = LogOptType.SELECT)

    public void onAuthenticationSuccess(HttpServletRequest request,  

            HttpServletResponse response, Authentication authentication) throws IOException,  

            ServletException {  

          

        UserDetails userDetails = (UserDetails)authentication.getPrincipal();  

          

        //输出登录提示信息,得到用户名:  userDetails.getUsername()

        System.out.println("管理员 " + userDetails.getUsername() + " 登录");  

        request.getSession().setAttribute("account",userDetails.getUsername());

        super.onAuthenticationSuccess(request, response, authentication);  

    }  

      

}

 

public class LoginUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {  

      //这里是用作验证码的验证的,重写attemptAuthentication()方法,这里不做详细介绍

}

 

首先这里的login.jsp将会有些不同,主要体现在form表单

<form id="form" action="<%=request.getContextPath() %>/j_spring_security_check" method="POST">

 

<input type="text" id="account" name="j_username" class="form-control" placeholder="帐号">

<input type="password" id="password" name="j_password" class="form-control" placeholder="密码">

<input type="submit" value="登陆" />

 

</form>

 

登陆以后在jsp中可以控制div的显示

 

如下面一段代码

 

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>

 

<security:authorize ifAnyGranted='ROLE_ADMIN,ROLE_ACCOUNT_SELECT'>

<li><a class="waves-effect" 

href="javascript:Tab.addTab('账号管理', '${pageContext.request.contextPath}/sys/account/list');">账号管理

</a></li>

</security:authorize>

 

ifAnyGranted='ROLE_ADMIN,ROLE_ACCOUNT_SELECT'

表示拥有ROLE_ADMIN 或者 拥有 ROLE_ACCOUNT_SELECT 权限的用户才能看到该内容的显示 (用or不行)

 

ifAnyGranted='ROLE_ADMIN and ROLE_ACCOUNT_SELECT'

表示ROLE_ADMIN 和 拥有 ROLE_ACCOUNT_SELECT 权限的用户才能看到该内容的显示

 

11.ssm 整合ehcache缓存

 若要整合ehcache 缓存需要引入jar

 

<!-- 整合ehcache缓存机制所需要的jar -->

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis-ehcache</artifactId>

<version>1.0.0</version>

</dependency>

<dependency>

<groupId>org.ehcache</groupId>

<artifactId>ehcache</artifactId>

<version>3.0.1</version>

</dependency>

 

spring 配置文件中配置ehcache 的bean

 

<!-- 配置ehcache缓存Bean -->

<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">

    <property name="configLocation" value="classpath:applicationContext-ehcache.xml" />

</bean>

 

编写application-ehcache.xml缓存配置

 

描述:

 

<!-- maxElementsInMemory:缓存中最大允许创建的对象数 。maxInMemory:设定内存中创建对象的最大值。

    eternal:设置元素(译注:内存中对象)是否永久驻留。如果是,将忽略超时限制且元素永不消亡。

timeToIdleSeconds:设置某个元素消亡前的停顿时间。 timeToLiveSeconds:为元素设置消亡前的生存时间.

overflowToDisk:设置当内存中缓存达到maxInMemor限制时元素是否可写到磁盘上。

memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。

你可以设置为FIFO(先进先出)或是LFU(较少使用)。 diskPersistent:重启时内存不持久化到硬盘。 -->

 

<?xml version="1.0" encoding="UTF-8"?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"

updateCheck="false">

<diskStore path="java.io.tmpdir" />

<defaultCache 

maxElementsInMemory="10000"

memoryStoreEvictionPolicy="LRU"

eternal="false"

      timeToIdleSeconds="300"

timeToLiveSeconds="300"

      overflowToDisk="false"

      diskPersistent="false" />

 

<cache 

name="districtDataCache" 

maxElementsInMemory="4000"

eternal="true" 

            overflowToDisk="false" 

diskPersistent="false"

memoryStoreEvictionPolicy="LRU" />

</ehcache>

 

mapper.xml中配置ehcache缓存

<cache readOnly="true">

<property name="timeToIdleSeconds" value="3600" />

<property name="timeToLiveSeconds" value="3600" />

<property name="maxEntriesLocalHeap" value="1000" />

<property name="maxEntriesLocalDisk" value="10000000" />

<property name="memoryStoreEvictionPolicy" value="LRU" />

</cache>

12.一个account模块的例子

1.accountMapper.xml

下面是一个mapper.xml  -- accountMapper.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.interDao.AccountMapper">

 

<!-- 得到分页数据 -->

<select id="getList" resultMap="accountResultMap">

select * from account where 1 = 1 limit #{startIndex},#{endIndex}

</select>

 

<!-- 得到数据总条数 -->

<select id="getTotal" resultType="java.lang.Integer">

select count(*) from account

</select>

 

<delete id="del">

delete from account where id = #{id}

</delete>

 

<update id="upd" parameterType="Account">

<![CDATA[

update account set account = #{account} , `password` = #{password} where id = #{id}

]]>

</update>

 

<!-- 添加一条记录,并返回主键 -->

<insert id="add" parameterType="Account" useGeneratedKeys="true" keyProperty="id">

<![CDATA[

insert into account(account,password) values (#{account},#{password})

]]>

</insert>

<!-- 修改回显 -->

<select id="each" resultMap="accountResultMap">

select * from account where id = #{value}

</select>

<!-- 批量插入,一个账户对应多个角色 -->

<insert id="addRoleAcc">

<selectKey order="AFTER" keyProperty="id" resultType="java.lang.Integer">

 SELECT LAST_INSERT_ID()

</selectKey>

insert into roleAccount values

<foreach collection="role" item="roleName" separator=",">

(

#{accId},#{roleName}

)

</foreach>

</insert>

 

<resultMap type="Account" id="accountResultMap">

<result property="id" column="id" />

<result property="account" column="account" />

<result property="password" column="password" />

</resultMap>

</mapper>

 

2.interface AccountMapper.java

 

com.interDao.AccountMapper.java

 

package com.interDao;

 

import java.util.List;

 

import org.apache.ibatis.annotations.Param;

 

import com.entry.Account;

 

public interface AccountMapper {

/**

 * 查询ACCOUNT中的分页数据

 *

 * @param nowPage

 *            当前页

 * @param pageSize

 *            每页显示多少条

 * @return

 */

public List<Account> getList(@Param(value = "startIndex") Integer startIndex,

@Param(value = "endIndex") Integer endIndex);

 

/**

 * 得到account表总条数

 *

 * @return total 数据总条数

 */

public Integer getTotal();

 

/**

 * 添加ACCOUNT中的数据

 *

 * @param acc

 *            Account

 * @return 返回影响行数

 */

public int add(Account acc);

 

/**

 * 根据id删除数据

 *

 * @param id

 * @return 影响行数

 */

public int del(Integer id);

 

/**

 * 修改

 *

 * @param acc

 *            Account

 * @return 影响行数

 */

public int upd(Account acc);

 

/**

 * 给账户分配角色

 *

 * @param accId

 *            账户id

 * @param list

 *            角色id 集合

 * @return 影响行数

 */

public int addRoleAcc(@Param(value = "accId") Integer accId, @Param(value = "role") List<String> list);

 

/**

 * 信息修改回显示

 *

 * @param id

 *            账户id

 * @return Account

 */

public Account each(Integer id);

}

 

3.AccountController.java

下面贴出 controller 与 service 的代码

 

@Controller

@RequestMapping("/com/sys/account/")

public class AccountController {

 

@Autowired

private AccountService accountServiceImpl;

 

/**

 * 账户添加

 *

 * @param acc Account

 * @param bindResult 使用了jsr303

 * @param model Model

 * @return

 */

@RequestMapping("add")

public String add(@Valid Account acc, BindingResult bindResult, Model model) {

try {

if (bindResult.getErrorCount() > 0)

model.addAttribute(Status.MESSAGE, Status.RESPONSE_ADDFAIL);

else {

boolean bool = accountServiceImpl.add(acc);

if (!bool)

model.addAttribute(Status.MESSAGE, Status.RESPONSE_ADDFAIL);

}

} catch (Exception e) {

e.printStackTrace();

}

return "sys/account/list";

}

 

/**

 * 账户删除

 *

 * @param model Model

 * @param id 主键

 * @return

 */

@RequestMapping(value = { "del/{id}" }, method = RequestMethod.DELETE)

public String del(Model model, @PathVariable("id") Integer id) {

try {

boolean bool = accountServiceImpl.del(id);

if (!bool)

model.addAttribute(Status.MESSAGE, Status.RESPONSE_DELFAIL);

} catch (Exception e) {

e.printStackTrace();

}

return "sys/account/list";

}

 

/**

 * 账户修改

 *

 * @param acc Account

 * @param bindResult 

 * @param model

 * @return

 */

@RequestMapping(value = { "update" }, method = RequestMethod.POST)

public String update(@Valid Account acc, BindingResult bindResult, Model model) {

try {

if (bindResult.getErrorCount() > 0)

model.addAttribute(Status.MESSAGE, Status.RESPONSE_UPDFAIL);

else {

boolean bool = accountServiceImpl.update(acc);

if (!bool)

model.addAttribute(Status.MESSAGE, Status.RESPONSE_UPDFAIL);

}

} catch (Exception e) {

e.printStackTrace();

}

return "sys/account/list";

}

 

/**

 * 得到修改回显的数据

 *

 * @param model

 * @param id

 *            主键

 * @return

*/

@RequestMapping(value = { "echo/{id}" }, method = RequestMethod.PUT)

public String echo(Model model, @PathVariable("id") Integer id) {

Account acc = accountServiceImpl.echo(id);

model.addAttribute("acc", acc);

return "sys/account/update";

}

 

/**

 * 得到列表分页数据

 *

 * @param nowPage

 *            当前页

 * @return

*/

@RequestMapping(value = { "list/{nowPage}" }, method = RequestMethod.POST)

@ResponseBody

public Page<Account> json(@PathVariable("nowPage") Integer nowPage) {

Page<Account> page = accountServiceImpl.getList(nowPage, 7);

return page;

}

 

}

 

4.interface AccountService.java

下面贴出接口 AccountService.java

 

package com.interfac;

 

import com.entry.Account;

import com.entry.Page;

 

/**

 *

 * @author 肖亮亮

 *

 * @date 2017年4月4日 上午10:19:39

 */

public interface AccountService {

 

/**

 * 查询ACCOUNT中的分页数据

 *

 * @param nowPage

 *            当前页

 * @param pageSize

 *            每页显示多少条

 * @return

 */

public Page<Account> getList(int nowPage, int pageSize);

 

/**

 * 根据id删除ACCOUNT中的数据

 *

 * @param id

 *            表主键

 * @return true 删除成功 , false 删除失败

 */

public boolean del(int id);

 

/**

 * 修改ACCOUNT中的数据

 *

 * @param acc

 *            Account

 * @return true 修改成功, false 修改失败

 */

public boolean update(Account acc);

 

/**

 * 添加ACCOUNT中的数据

 *

 * @param acc

 *            Account

 * @return true 添加成功, false 添加失败

 */

public boolean add(Account acc);

 

/**

 * 账户修改信息回显,根据id

 *

 * @param id

 *            表主键

 * @return true 成功, false 失败

 */

public Account echo(int id);

 

/**

 * 向角色账户关系表中插入数据

 *

 * @param acc

 *            Account

 * @param key

 *            添加时返回的主键

 * @return

 */

public boolean insertRoleAccount(Account acc, int key);

}

 

5.AccountServiceImpl.java

 

下面贴出业务逻辑层实现类 AccountServiceImpl.java

/**

 *

 * @author 肖亮亮

 *

 * @date 2017年3月28日 下午3:36:24

 */

@Service

public class AccountServiceImpl implements AccountService {

 

@Autowired

private AccountMapper accountMapper;

 

/**

 * 查询ACCOUNT中的分页数据

 *

 * @param nowPage

 *            当前页

 * @param pageSize

 *            每页显示多少条

 * @return

 */

@Override

@Loggable(describe = "查询ACCOUNT中的分页数据", module = LogModule.ACCOUNT, optType = LogOptType.SELECT)

public Page<Account> getList(int nowPage, int pageSize) {

Page<Account> page = new Page<>(nowPage, pageSize, accountMapper.getTotal());

List<Account> rows = accountMapper.getList(page.getStartIndex(), page.getEndIndex());

page.setRows(rows);

return page;

}

 

/**

 * 根据id删除ACCOUNT中的数据

 *

 * @param id

 *            表主键

 * @return true 删除成功 , false 删除失败

 */

@Override

@Transactional(propagation = Propagation.REQUIRED)

@Loggable(describe = "根据id删除ACCOUNT中的数据", module = LogModule.ACCOUNT, optType = LogOptType.DELETE)

public boolean del(int id) {

int sum = accountMapper.del(id);

return (sum == 1 ? true : false);

}

 

/**

 * 修改ACCOUNT中的数据

 *

 * @param acc

 *            Account

 * @return true 修改成功, false 修改失败

 */

@Override

@Transactional(propagation = Propagation.REQUIRED)

@Loggable(describe = "修改ACCOUNT中的数据", module = LogModule.ACCOUNT, optType = LogOptType.UPDATE)

public boolean update(Account acc) {

int sum = accountMapper.upd(acc);

return (sum == 1 ? true : false);

}

 

/**

 * 添加ACCOUNT中的数据

 *

 * @param acc

 *            Account

 * @return true 添加成功, false 添加失败

 */

@Override

@Transactional(propagation = Propagation.REQUIRED)

@Loggable(describe = "插入数据到ACCOUNT中", module = LogModule.ACCOUNT, optType = LogOptType.INSERT)

public boolean add(Account acc) {

boolean is = false;

// 向Account表中插入数据

accountMapper.add(acc);

int key = acc.getId();

// 向关系表roleAccount中插入数据

is = insertRoleAccount(acc, key);

return is;

}

 

/**

 * 账户修改信息回显,根据id

 *

 * @param id

 *            表主键

 * @return true 成功, false 失败

 */

@Override

@Loggable(describe = "账户修改信息回显,根据id", module = LogModule.ACCOUNT, optType = LogOptType.SELECT)

public Account echo(int id) {

Account acc = accountMapper.each(id);

return acc;

}

 

/**

 * 向角色账户关系表中插入数据

 *

 * @param acc

 *            Account

 * @param key

 *            添加时返回的主键

 * @return true 添加成功 , false 添加失败

 */

@Override

@Loggable(describe = "向关系表roleAccount中插入数据", module = LogModule.ROLE_ACCOUNT, optType = LogOptType.INSERT)

public boolean insertRoleAccount(Account acc, int key) {

String strArr[] = acc.getRole().split(",");

List<String> list = Arrays.asList(strArr);

int sum = accountMapper.addRoleAcc(acc.getId(), list);

return (sum >= 1 ? true : false);

}

 

}

 

6.Page.java

 

package com.entry;

 

import java.util.ArrayList;

import java.util.List;

 

import org.springframework.jdbc.core.JdbcTemplate;

 

/**

 * 分页实体类

 *

 * @author 肖亮亮

 *

 * @date 2017年3月28日 上午9:08:45

 */

public class Page<T> {

 

// 当前页

private Integer nowPage;

// 页面要显示信息条数

private Integer pageSize = 5;

// 根据页面显示的条数计算总页数

private Integer countPage;

// 根据传入的数据库查询数据库中的信息的条数

private Integer total;

// 向数据库查询时的开始的下标

private Integer startIndex;

// 向数据库查询时的查询条数

private Integer endIndex;

// 页面页码个数

private Integer num = 5;

// 页面页码总数

private String pageNum;

// 将查询到的数据存放到这里

private List<T> rows = new ArrayList<>();

 

/**

 * 传入总记录数 和当前页

 *

 * @param total

 *            总记录数

 * @param nowPage

 *            当前页

 */

public Page(Integer nowPage, String tableName, Integer pageSize, JdbcTemplate jdbcTemplate) {

String sql = "SELECT COUNT(*) FROM " + tableName;

// 一共有多少条数据

this.total = jdbcTemplate.queryForObject(sql, Integer.class);

getData(nowPage, pageSize);

}

 

private void getData(Integer nowPage, Integer pageSize) {

// 每页显示多少条

this.pageSize = pageSize;

// 赋值

this.nowPage = nowPage;

// 判断当前页是否合法

if (this.nowPage < 1) {

this.nowPage = 1;

}

// 计算总页数

this.countPage = this.total % this.pageSize == 0 ? this.total / this.pageSize : this.total / this.pageSize + 1;

 

if (this.nowPage > this.countPage) {

this.nowPage = this.countPage;

}

// 计算出开始的记录下标,和每页要显示的条数

 

if (this.nowPage == 0) {

this.startIndex = this.nowPage * this.pageSize;

this.endIndex = this.pageSize;

} else {

this.startIndex = (this.nowPage - 1) * this.pageSize;

this.endIndex = this.pageSize;

}

this.pageNum = getPageNums();

}

 

public Page(Integer nowPage, Integer pageSize, Integer total) {

this.total = total;

getData(nowPage, pageSize);

}

 

/**

 * pageCount 总页数 pageCurr 当前页 num 显示的页码数

 *

 * @return

 */

private String getPageNums() {

StringBuffer sb = new StringBuffer();

if (num >= countPage) {

for (int i = 1; i <= countPage; i++) {

sb.append(i).append(",");

}

} else if (nowPage == countPage) {

for (int i = countPage - num + 1; i <= countPage; i++) {

if (i > countPage) {

break;

}

sb.append(i).append(",");

}

} else if (nowPage + num > countPage) {

for (int i = countPage - num; i < countPage; i++) {

if (i > countPage) {

break;

}

sb.append(i).append(",");

}

} else {

for (int i = nowPage; i < nowPage + num; i++) {

if (i > countPage) {

break;

}

sb.append(i).append(",");

}

}

return sb.toString();

}

 

public String getPageNum() {

return pageNum;

}

 

public void setPageNum(String pageNum) {

this.pageNum = pageNum;

}

 

public List<T> getRows() {

return rows;

}

 

public void setRows(List<T> rows) {

this.rows = rows;

}

 

public Integer getStartIndex() {

return startIndex;

}

 

public Integer getEndIndex() {

return endIndex;

}

 

public Integer getTotal() {

return total;

}

 

public Integer getNowPage() {

return nowPage;

}

 

public void setNowPage(Integer nowPage) {

this.nowPage = nowPage;

}

 

public Integer getPageSize() {

return pageSize;

}

 

public void setPageSize(Integer pageSize) {

this.pageSize = pageSize;

}

 

public Integer getCountPage() {

return countPage;

}

 

public void setCountPage(Integer countPage) {

this.countPage = countPage;

}

 

public void setTotal(Integer total) {

this.total = total;

}

 

public void setStartIndex(Integer startIndex) {

this.startIndex = startIndex;

}

 

public void setEndIndex(Integer endIndex) {

this.endIndex = endIndex;

}

 

}

 

7.Page.js

function table() {

var pageNum = $("#pageNum").val();

var nowPage = $("#nowPage").val();

var countPage = $("#countPage").val();

$('.page-right').html('');

var pringString = "";

pringString += "<ul id='pagination-flickr'>";

if (nowPage <= 1) {

pringString += "<li class='previous-off'><a href='javascript:;'>首页</a></li>";

pringString += "<li class='previous-off'><a href='javascript:;'>«上一页</a></li>";

} else {

var now = parseInt(nowPage);

pringString += "<li class='previous-off'><a href='javascript:;' οnclick='oncl(1)'>首页</a></li>";

pringString += "<li class='previous-off'><a href='javascript:;' οnclick='oncl("+ (now - 1) + ")'>«上一页</a></li>";

}

var count = parseInt(countPage);

var pArr = pageNum.split(',');

for ( var i in pArr) {

if (nowPage == i) {

pringString += "<li class='active'>" + i + "</li>";

} else if (i > 0 && i <= count) {

pringString += "<li><a href='javascript:;' οnclick='oncl(" + i+ ")' id='sum' >" + i + "</a></li>";

}

}

if (nowPage > count - 1) {

pringString += "<li class='next'><a href='javascript:;'>下一页 »</a></li>";

pringString += "<li class='next'><a href='javascript:;'>尾页</a></li>";

} else {

var now = parseInt(nowPage);

pringString += "<li class='next'><a href='javascript:;' οnclick='oncl("+ (now + 1) + ")' >下一页</a></li>";

pringString += "<li class='next'><a href='javascript:;' οnclick='oncl("+ (count) + ")'>尾页</a></li>";

}

pringString += "</ul>";

pringString +="<span><li class='next'>总页数    "+countPage+"</li></span>"

$('.page-right').append(pringString);

}

 

function oncl(nowPage) {

$('#nowPage').val(nowPage);

get();

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值