Spring+SpringMVC+Mybatis(SSM)框架搭建教程(五)-扩展:过滤器Filter应用

背景

上一篇《Spring+SpringMVC+Mybatis(SSM)框架搭建教程(四)-应用功能开发实例》着重介绍了框架在项目开发过程中的使用方法,以实例的方式讲解了两种请求方式的代码编写形式。本篇着重介绍此框架在应用开发过程中的扩展——过滤器的配置。

目标

本篇我们要实现两种过滤器:

  • 字符编码过滤器
  • 参数空格过滤器

字符编码过滤器

在中文软件系统中,中文汉字在不同的编码形式下呈现形态不一,可能会出现乱码,一般来说,程序中统一对汉字以“UTF-8”编码形式表示。在未设置字符编码过滤器时,学生信息查询功能(接上一篇开发的示例系统)中输入姓名:张三,点击查询后,得到下图内容
乱码
我们可以看到,原来的“张三”,从后台过了一下,显示回前台是已经变了样,呈现为乱码,主要问题就是框架层面并未对字符编码做处理,默认使用ISO-8859-1编码集,此时中文就出现了乱码问题。
处理此问题可分为两步:
1、在项目中新建com.dommy.filter包,写一个字符编码过滤器,实现import javax.servlet.Filter接口:

package com.dommy.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * 字符编码过滤器
 */
public class CharacterEncodingFilter implements Filter {
    @SuppressWarnings("unused")
    private FilterConfig filterConfig = null; // 过滤器配置参数
    private String encoding = null; // 字符编码

    public CharacterEncodingFilter() {
        super();
    }

    public void destroy() {
        this.filterConfig = null;
        this.encoding = null;
    }

    /**
     * 过滤方法
     */
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException,
            ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        String methodName = request.getMethod();
        if ("post".equalsIgnoreCase(methodName)) {
            // post请求编码设置
            request.setCharacterEncoding(this.encoding);
        } else if ("get".equalsIgnoreCase(methodName)) {
            // get请求编码设置,需要逐个参数解析
            request = new MyRequestWrapper(request);
            HashMap map = new HashMap(request.getParameterMap());
            if (map != null && map.size() > 0) {
                Set<Entry> entrySet = map.entrySet();
                for (Map.Entry entry : entrySet) {
                    Object key = entry.getKey();
                    Object value = entry.getValue();
                    if (value instanceof String[]) {
                        String[] valueArray = (String[]) value;
                        for (int i = 0; i < valueArray.length; ++i) {
                            // 改编码
                            valueArray[i] = doEncoding(valueArray[i]);
                        }
                        map.put(key, valueArray);
                    }
                }
            }

            ParameterRequestWrapper wrapRequest = new ParameterRequestWrapper(request, map);
            request = wrapRequest;
        }

        // 设置输出的字符编码
        res.setContentType("text/html;charset=" + encoding);
        // 继续执行后面的程序
        fc.doFilter(request, res);
    }

    public void init(FilterConfig filterConfig) throws ServletException {

        this.filterConfig = filterConfig;

        /* 获取字符编码 */
        this.encoding = filterConfig.getInitParameter("encoding");
        if (encoding == null || encoding.length() == 0) {
            encoding = "UTF-8";
        }
    }

    /**
     * 内部类,继承自 HttpServletRequestWrapper 类
     */
    public class MyRequestWrapper extends HttpServletRequestWrapper {
        HttpServletRequest request = (HttpServletRequest) super.getRequest();

        public MyRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getParameter(String name) {
            String value = this.encode(request.getParameter(name));
            return value;
        }

        @Override
        public String[] getParameterValues(String name) {
            String[] values = request.getParameterValues(name);
            if (values != null) {
                for (int i = 0; i < values.length; i++) {
                    values[i] = this.encode(values[i]);
                }
            }
            return values;
        }

        /**
         * 字符编码处理
         * @param value 编码前的字符串
         * @return 编码后的字符串
         */
        public String encode(String value) {
            if (value != null) {
                try {
                    value = new String(value.getBytes("ISO-8859-1"), CharacterEncodingFilter.this.encoding);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            return value;
        }
    }

    /**
     * 修改编码
     * @param value 编码前的字符串
     * @return String 编码后的字符串
     */
    private String doEncoding(String value) {
        if (value != null && value.length() > 0) {
            try {
                value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return value;
    }
}

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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    ...
    <!-- 配置编码过滤器 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>com.dommy.filter.CharacterEncodingFilter</filter-class>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    ...
</web-app>

重启tomcat服务器,再输入“张三”时,查询结果变成了:
中文已转码
我们可以发现中文已经正确显示。

*(当然如果不设置过滤器,在每个Controller里面也可以对每个参数逐个编码解码,不过那样会很麻烦;或者在tomcat容器中设置编码也可以解决,不过会受限于容器配置,部署的时候必须保证配置统一)

参数空格过滤器

用户在使用系统时有意无意可能会输入空格,一般来说在字符串首尾的空格都是无意义的(密码值除外),所以常见系统里面还可以加入参数空格过滤器。同样是两步走:
1、在项目包com.dommy.filter里,写一个参数空格编码过滤器,实现import javax.servlet.Filter接口:

package com.dommy.filter;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * 请求参数值空格过滤器(去除前后空格)
 */
public class ParameterTrimFilter implements Filter {
    public void init(FilterConfig filterconfig) throws ServletException {
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HashMap map = new HashMap(request.getParameterMap());
        if (map != null && map.size() > 0) {
            Set<Entry> entrySet = map.entrySet();
            // 遍历,参数值去空格
            for (Map.Entry entry : entrySet) {
                Object key = entry.getKey();
                Object value = entry.getValue();
                if (value instanceof String[]) {
                    String[] valueArray = (String[]) value;
                    for (int i = 0; i < valueArray.length; ++i) {
                        // 去空格
                        valueArray[i] = valueArray[i].trim();
                    }
                    map.put(key, valueArray);
                }
            }
        }

        // 类型转换
        ParameterRequestWrapper wrapRequest = new ParameterRequestWrapper(req, map);
        request = wrapRequest;
        chain.doFilter(request, response);
    }

}

其中,ParameterRequestWrapper类:

package com.dommy.filter;

import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class ParameterRequestWrapper extends HttpServletRequestWrapper {
    private Map params;

    public ParameterRequestWrapper(HttpServletRequest request, Map newParams) {
        super(request);
        this.params = newParams;
    }

    public Map getParameterMap() {
        return this.params;
    }

    public Enumeration getParameterNames() {
        Vector l = new Vector(this.params.keySet());
        return l.elements();
    }

    public String[] getParameterValues(String name) {
        Object v = this.params.get(name);
        if (v == null)
            return null;
        if (v instanceof String[])
            return (String[]) v;
        if (v instanceof String) {
            return new String[] { (String) v };
        }
        return new String[] { v.toString() };
    }

    public String getParameter(String name) {
        Object v = this.params.get(name);
        if (v == null)
            return null;
        if (v instanceof String[]) {
            String[] strArr = (String[]) v;
            if (strArr.length > 0) {
                return strArr[0];
            }
            return null;
        }
        if (v instanceof String) {
            return (String) v;
        }
        return v.toString();
    }
}

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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    ...

    <!-- 配置去空格过滤器 -->
    <filter>
        <filter-name>ParameterTrimFilter</filter-name>
        <filter-class>com.dommy.filter.ParameterTrimFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ParameterTrimFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    ...
</web-app>

重新发布并启动项目,在界面中输入“ 张三 ”,点击查询:
带空格的查询
可以看到查询结果中能查到张三,而且姓名的填入值也变成了“张三”,空格全部被过滤了。
过滤空格的查询结果

结语

本篇从过滤器的角度对SSM框架的搭建进行了扩展,在本框架中还可以添加SessionFilter用以验证用户身份,当然还可以使用SpringMVC提供的HandlerInterceptor接口来实现请求拦截,用到的就是AOP方面的技术了。

至此,Spring+SpringMVC+Mybatis(SSM)框架搭建方案的内容已经全部讲完,下一篇将对前面的内容做一个小结,并给出示例代码的下载地址。

源码下载

项目源码下载地址:
http://download.csdn.net/download/ahuyangdong/10262363

GitHub地址:
https://github.com/ahuyangdong/SSMDemo

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个Spring+SpringMVC+MybatisSSM中使用Shiro进行登陆验证的完整程序示例: 1. 添加依赖 在pom.xml文件中添加Shiro的依赖: ```xml <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.7.1</version> </dependency> ``` 2. 配置Shiro 在Spring配置文件中添加Shiro的配置,例如在applicationContext.xml中添加如下配置: ```xml <!-- Shiro配置 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm" /> </bean> <bean id="myRealm" class="com.example.shiro.MyRealm"> <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="SHA-256" /> </bean> </property> </bean> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/login.jsp" /> <property name="successUrl" value="/index.jsp" /> <property name="unauthorizedUrl" value="/unauthorized.jsp" /> <property name="filterChainDefinitions"> <value> /login.jsp = anon /login.do = anon /logout.do = logout /** = authc </value> </property> </bean> ``` 其中,securityManager配置了SecurityManager实现类;myRealm配置了自定义的Realm实现类;shiroFilter配置了ShiroFilter的相关设置。 3. 编写Realm实现类 创建一个自定义的Realm实现类,用于验证用户的账号和密码。具体代码如下: ```java import java.util.HashSet; import java.util.Set; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class MyRealm extends AuthorizingRealm { //模拟数据库中的用户信息 private static final String USERNAME = "admin"; private static final String PASSWORD = "admin"; private static final String SALT = "123456"; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //授权 Set<String> roles = new HashSet<>(); roles.add("admin"); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(roles); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //认证 UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); if (!USERNAME.equals(username)) { return null; } String password = PASSWORD; String salt = SALT; HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("SHA-256"); matcher.setHashIterations(1024); SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, matcher); authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(salt)); return authenticationInfo; } } ``` 其中,doGetAuthorizationInfo方法用于授权,可以设置用户的角色和权限;doGetAuthenticationInfo方法用于认证,可以验证用户的账号和密码。 4. 编写登陆验证代码 在Java代码中创建一个Shiro的工具类,用于登陆验证和权限控制。具体代码如下: ```java import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; public class ShiroUtils { @Autowired private SecurityManager securityManager; public boolean login(String username, String password) { //1.将SecurityManager设置到运行环境中 SecurityUtils.setSecurityManager(securityManager); //2.创建Subject Subject subject = SecurityUtils.getSubject(); //3.创建Token UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { //4.登陆 subject.login(token); return true; } catch (UnknownAccountException e) { //用户名不存在 System.out.println("用户名不存在"); } catch (IncorrectCredentialsException e) { //密码错误 System.out.println("密码错误"); } catch (LockedAccountException e) { //账户被锁定 System.out.println("账户被锁定"); } catch (AuthenticationException e) { //认证失败 System.out.println("认证失败"); } return false; } public void logout() { //1.获取Subject Subject subject = SecurityUtils.getSubject(); //2.登出 subject.logout(); } } ``` 5. 在Controller中使用Shiro进行登陆验证 在需要进行登陆验证的Controller中,引入ShiroUtils,并调用其login方法进行验证。具体代码如下: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class LoginController { @Autowired private ShiroUtils shiroUtils; @RequestMapping("/login.do") public String login(String username, String password) { if (shiroUtils.login(username, password)) { return "redirect:/index.jsp"; } else { return "redirect:/login.jsp"; } } } ``` 以上就是一个简单的Spring+SpringMVC+MybatisSSM中使用Shiro进行登陆验证的完整程序示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值