总结
我是最棒的!基础不牢,地动山摇!
表单重复提交
表单重复提交就是将表单中的元素标签对应的数据多次提交到服务器
产生原因
- 请求转发,请求了一次之后,回车浏览器站点,造成再次提交
- 当网络繁忙的时候,提交了多次
- 使用了回退,没有修改数据,再次发送请求
解决办法
-
使用重定向(但是不彻底)
只能解决产生原因的第一种
-
使用token来解决(彻底解决重复提交)
原理:在jsp中产生一个sessionID,然后再到后台去匹配你前端产生的token值,如果值是相等的,就证明是在一次会话中。也能证明是第一次提交,但是提交完毕之后,压在后台销毁session,代表一次会话结束
package cn.itsource.repeat;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class RepeatServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取前端传入的金额和sessionId
String account = req.getParameter("account");
String tokenId = req.getParameter("sessionId");
System.out.println(tokenId);
//获取当前的sessionId
HttpSession session = req.getSession();
String id = session.getId();
//清除当前session,一次会话结束
session.invalidate();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(id.equals(tokenId)){
//sessionId匹配,则证明在一次会话中
System.out.println("转账金额为:" + account);
}else {
//不匹配则不再同义词会话中
System.out.println("已经转账成功!");
}
// req.getRequestDispatcher("/repeat/success.jsp").forward(req, resp);
resp.sendRedirect("/repeat/success.jsp");
}
}
过滤器Filter
过滤器是tomcat的又一组件,强调责任分离。对代码进行组件化,对公共代码进行抽取。开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截和处理。
javaweb中的过滤器都是双向的
过滤器的作用
- 对字符进行编码
- 让浏览器不缓存(现在不太需要)
- 屏蔽非法字符
- 登录权限的验证(例如没有登录,统一跳转到登录界面)
chain
过滤器链,多个过滤器按照一定顺序进行排列。按照web.xml中filter-mapping的顺序来执行
下面的执行顺序为A->B->C,响应顺序为C->B->A
<filter>
<filter-name>AFilter</filter-name>
<filter-class>cn.itsource.chain.AFilter</filter-class>
</filter>
<filter>
<filter-name>BFilter</filter-name>
<filter-class>cn.itsource.chain.BFilter</filter-class>
</filter>
<filter>
<filter-name>CFilter</filter-name>
<filter-class>cn.itsource.chain.CFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>BFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
字符编码
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>cn.itsource.encoding.EncodingFilter</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>
EncodingFilter
package cn.itsource.encoding;
import java.io.IOException;
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.HttpServletResponse;
public class EncodingFilter implements Filter{
private String encoding = "";
private boolean forceEncoding = false;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
encoding = filterConfig.getInitParameter("encoding");
forceEncoding = Boolean.valueOf(filterConfig.getInitParameter("forceEncoding"));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
/*
* 如果encoding不为空,并且系统本身没有指定的字符集,强制更改字符集为false
* 如果encoding不为空,并且系统有指定的字符集,但是强制更改字符集为true
* 满足两种情况之一才能进行设置字符集
*/
if(hasLength(encoding) && (!hasLength(req.getCharacterEncoding())) || forceEncoding){
req.setCharacterEncoding(encoding);
}
chain.doFilter(req, resp);
}
/**
* 判断字符串是否为空的方法
* @param str
* @return
*/
public static boolean hasLength(String str){
return str == null && "".equals(str) ? false : true;
}
@Override
public void destroy() {
}
}
权限验证
平时未登录时点击会直接跳转登录界面,模拟一下
AuthorityServlet
package cn.itsource.authority;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/authority")
public class AuthorityServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
//会话跟踪
req.getSession().setAttribute("username", username);
if("admin".equals(username)&&"admin".equals(password)){
//用户名密码正确重定向到主界面
resp.sendRedirect("/authority/main.jsp");
}else {
//用户名或者密码错误提示
req.setAttribute("msg", "用户名或者密码错误");
req.getRequestDispatcher("/authority/login.jsp").forward(req, resp);;
}
}
}
AuthorityFilter
package cn.itsource.authority;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebFilter("/*")
public class AuthorityFilter implements Filter{
/**判断不需要过滤的界面*/
private List<String> excludes = Arrays.asList("/authority/login.jsp","/authority");
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
Object obj = req.getSession().getAttribute("username");
String uri = req.getRequestURI();
/*
* 判断获取的username是否为空,若不为空且为不需要过滤的界面直接重定向到登录界面
* 其他情况放行
*/
if(obj == null && !excludes.contains(uri)){
resp.sendRedirect("/authority/login.jsp");
return;
}else {
chain.doFilter(req, resp);
}
}
@Override
public void destroy() {
}
}