day04
登录使用session
struts2的session获取支持两种方式,httpSession、SessionMap
导包:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
</dependency>
一:使用的是sessionMap对象----不推荐
Map<String, Object> session = ActionContext.getContext().getSession();
session.put("usernameS", username);
二:使用httpSession方式----不推荐
HttpSession session = ServletActionContext.getRequest().getSession();
session.setAttribute("usernameS", username);
三:实现sessionaware接口,并实现其中的setsession方法---推荐
为了便于其它action共同使用同一个变量session(全局session),我们需要将session抽取成基类,其它action如果使用,则继承此基类即可
/**
* Action基类,便于其它action使用全局session对象信息
* @author likang
* @date 2018-1-10 上午8:56:57
*/
public class BaseAction implements SessionAware{
public Map<String, Object> session;
/**
* 此getter方法,是变量session的getter方法
* @return
*/
public Map<String, Object> getSession() {
return session;
}
/**
* 是接口SessionAware中的接口方法,并非session的setter方法
*/
public void setSession(Map<String, Object> session) {
this.session = session;
}
}
四:设置BaseAction ,session基类,这样全局都可以调用
public class BaseAction implements SessionAware{
public Map<String, Object> session;
public Map<String, Object> getSession() {
return session;
}
public void setSession(Map<String, Object> session) {
this.session = session;
}
}
struts2组件列表
StrutsPrepareAndExecuteFilter
1:接收请求,并且将请求进行过滤
2:进行转发到struts.xml进行处理
filter控制器,是需要配置到web.xml中
并且默认的请求后缀名是action和空
如果想修改请求后缀名,则需要在struts.xml中增加如下属性信息:
<constant name="struts.action.extension" value="do"/>
如果是允许多个请求后缀,则需要用逗号隔开
(需要进行数据拦截)
(会将请求的数据和响应的数据封装到值栈中)
Action
package需要继承struts-default
默认的action是:com.opensymphony.xwork2.ActionSupport
其中有默认的方法:execute
默认的返回值:success
result
1:应用于界面响应的
dispatcher
redirect
2:应用于action响应的
chain
redirectAction
3:应用于字节流的响应
stream
4:应用于json的响应
json---(需要引用struts-json.jar包)
验证码实现
需求:
在登录页面,增加验证码(图片)信息
请求:
login.jsp-->/image.do--->action---->login.jsp
开发步骤:
1:修改login.jsp文件,增加验证码信息
2:配置一个image.do的action信息(struts.xml)
3:添加一个ImageAction.java文件,execute--生成一张验证码图片
login.jsp:
验证码:<input id="code" name="code" type="text"><img src="image.do"></img><br/>
ImageAction.java:
/**
* 生成验证码图片
* @author likang
* @date 2018-1-10 上午10:16:26
*/
@Controller
public class ImageAction {
public InputStream image;
public String execute(){
try {
BufferedImage bi = new BufferedImage(100, 50, BufferedImage.TYPE_INT_RGB);//代表创建一个画布或者像素空间
Graphics graphics = bi.getGraphics();//创建画笔
graphics.setColor(Color.RED);//设置图片前景颜色
graphics.drawString("java13", 0, 50);//画信息
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ImageIO.write(bi, "png", bout);//将图片信息,添加到outputstream中
byte[] by = bout.toByteArray();//j a v a 1 3
image = new ByteArrayInputStream(by);//将字节流转换成字符流
return "success";
} catch (Exception e) {
}
return "error";
}
public InputStream getImage() {
return image;
}
public void setImage(InputStream image) {
this.image = image;
}
}
struts.xml:
<!-- 生成验证码图片 -->
<action name="image" class="imageAction" method="execute">
<result name="success" type="stream">
<param name="inputName">image</param>
</result>
</action>
使用工具类来生成验证码
//通过工具类来生成验证码
ValidateCode vc = new ValidateCode(200, 50, 2, 1);
image = vc.getInputStream();
验证码校验
流程:
1:CheckCodeAction.java需要去判断输入的验证码和系统生成的验证码是否一致
2:系统生成的验证码需要在image.do的时候,就需要获取到code字符值
开发步骤:
1:导包:
<!-- json数据类型 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.5.13</version>
</dependency>
2:修改struts.xml中的package中extends属性为json-default
<package name="user" extends="json-default" namespace="/user">
3:增加验证码校验接口struts.xml
<!-- 验证码校验 -->
<action name="checkCode" class="checkCodeAction" method="execute">
<result name="success" type="json"><!-- 来源于struts-json包中的xml文件 -->
<param name="root">rc</param><!-- root代表json实现类中的参数变量,负责接收json数据 -->
</result>
</action>
4:增加一个返回值的实体信息,封装成json格式数据
/**
* 返回的实体对象信息---json格式
* @author likang
* @date 2018-1-10 上午11:31:31
*/
public class ReturnContans implements Serializable{
private int status;
private String msg;
private Object data;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
5:增加CheckCodeAction
/**
* 验证码校验
* @author likang
* @date 2018-1-10 上午11:27:36
*/
@Controller
public class CheckCodeAction extends BaseAction{
public String code;//接收用户输入的验证码信息
ReturnContans rc = new ReturnContans();
public String execute(){
String Scode = session.get("Scode").toString();//获取系统生成的验证码
if (StringUtils.isNotBlank(code) && StringUtils.isNotBlank(Scode)) {
if (code.equalsIgnoreCase(Scode)) {
rc.setStatus(0);//0:代表验证码正确
rc.setMsg("验证码输入正确");
// return "";//验证码输入正确
}else{
rc.setStatus(1);//1:代表验证码错误
rc.setMsg("验证码输入错误");
}
}
return "success";//验证码输入错误\验证码输入正确
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public ReturnContans getRc() {
return rc;
}
public void setRc(ReturnContans rc) {
this.rc = rc;
}
}
6:在系统验证码生成的时候,需要将验证码存放于session中,便于使用校验
ImageAction.java:
session.put("Scode", vc.getCode());
7:编写login.jsp文件,增加js校验,发送ajax请求
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$("#code").blur(function(){
var code = $("#code").val().trim();
if (code == "") {
$("#Vcode").html("不能为空");
$(":submit").attr("disabled","disabled");
}else{
$.ajax({
url:"${pageContext.request.contextPath }/user/checkCode.do",
type:"post",
dataType:"json",
data:{"code":code},
success:function(result){
if (result.status == 1) {
$("#Vcode").html("验证码错误");
$(":submit").attr("disabled","disabled");
}else{
$("#Vcode").html("验证码正确");
$(":submit").removeAttr("disabled");
}
}
})
}
});
});
</script>
验证码:<input id="code" name="code" type="text"><img src="image.do"></img><span id="Vcode"></span>
Interceptor拦截器
struts2提供大量的拦截器,有一个默认的拦截器栈defaultStack
拦截器可以使用做为登录检测、性能检测、权限检测等等
拦截器栈:interceptor-stack
里面封装了需要执行的拦截器
需求:
/list.do----变更:如果用户没有登录,则不能访问,直接跳转登录页面
开发步骤:
1:自定义一个拦截器,实现Interceptor,并实现其中的intercept方法
/**
* 自定义拦截器---拦截用户是否登录
* @author likang
* @date 2018-1-10 下午2:40:10
*/
public class DemoInterceptor implements Interceptor{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init() {
// TODO Auto-generated method stub
}
/**
* 如果返回值为noLogin,则代表用户没有登录,此时需要跳转toLogin.do接口
* 如果usernameS不为空,则返回NULL,或者返回invocation.invoke(),代表是继续执行下一步拦截
*/
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//检测用户是否登录
Map<String, Object> session = ActionContext.getContext().getSession();
if (session != null) {
if (session.get("usernameS") != null && !"".equals(session.get("usernameS"))) {
}else{
return "noLogin";//-result-----toLogin.do
}
}
return invocation.invoke();
}
}
2:在struts.xml中,增加拦截器设置指定
<package>
<interceptors>
<interceptor name="noLoginInterceptor" class="com.xdl.util.DemoInterceptor"></interceptor>
</interceptors>
</package>
3:在需要拦截的action中,指定拦截器指向ref,和result组件返回值
<interceptor-ref name="noLoginInterceptor"></interceptor-ref>
<result name = "noLogin" type="redirectAction">
<param name="namespace">/user</param>
<param name="actionName">toLogin</param>
</result>
4:为了更方便扩展和应用,将拦截器设置进行提取
<package name="demo-default" extends="struts-default">
<interceptors>
<interceptor name="noLoginInterceptor" class="com.xdl.util.DemoInterceptor"></interceptor>
</interceptors>
<global-results>
<result name = "noLogin" type="redirectAction">
<param name="namespace">/user</param>
<param name="actionName">toLogin</param>
</result>
</global-results>
</package>
5:在需要拦截的action中,进行指定,前提需要package继承demo-default
<default-interceptor-ref name="noLoginInterceptor"></default-interceptor-ref>
开发工具中,前端资源文件报错解决方式
前端文件如:css/js/jsp/html等等
Struts2注解配置
1:导包
<!-- 注解包 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>2.5.13</version>
</dependency>
2:注解
对应到action类上面:
@Namespace(value="/demo")
@ParentPackage(value="demo-default")
对应到action中的方法上面:
@Action(value="hello",results={
@Result(name="success",location="/WEB-INF/jsp/hello.jsp")
})
增加自定义拦截器后,一些功能无法使用问题
修改struts.xml:
<package name="demo-default" extends="struts-default">
<interceptors>
<interceptor name="noLoginInterceptor" class="com.xdl.util.DemoInterceptor"></interceptor>
<interceptor-stack name="demoStack"> <!-- 拦截栈 先走我们自定义的,再走Struts2默认的拦截器-->
<interceptor-ref name="noLoginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<global-results>
<result name = "noLogin" type="redirectAction">
<param name="namespace">/user</param>
<param name="actionName">toLogin</param>
</result>
</global-results>
</package>
<default-interceptor-ref name="demoStack"></default-interceptor-ref>
ValueStack(接口)
前端界面调试以及数据展示:
需要在前端页面增加S标签:
<%@ taglib uri="/struts-tags" prefix="s" %>
<s:debug></s:debug>
OGNL应用
Object-Graph Navigation Language
引入ognl-3.1.15.jar 包
对象导航图语言
public class TestStack {
@Test
public void test1(){
Dept dept = new Dept();
// dept.setDeptName("nihao");
// System.out.println(dept.getDeptName());
setPreperties(dept, "deptName", "nihao");
System.out.println(dept.getDeptName());
}
public void setPreperties(Object entity,String name,String value){
try {
Ognl.setValue(name, entity, value);
} catch (OgnlException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Test
public void test2() throws OgnlException{
Dept dept = new Dept();
dept.setDeptName("nihaoa");
System.out.println("数据初始化:"+dept.getDeptName());
String deptname = (String) Ognl.getValue("deptName", dept);
System.out.println("通过OGNL获取数据值:"+deptname);
Map<String, Object> context = new HashMap<String, Object>();
context.put("deptName", "nihao-----123123");
String deptnameS = (String) Ognl.getValue("#deptName", context, dept);
System.out.println("ognl通过表达式获取值:"+deptnameS);
}
}