人的惰性真是可怕啊! 差不多从中秋以来,都一直处于偷懒的状态,基本上没学习什么新东西,这都要归功于暴雪家的魔兽世界和守望先锋了。玩了这么久,是该总结下这段时间遇到的问题和已经找到的解决方法了,省的以后再遇到这些问题。

遇到的问题

前段时间,领导让学习java并尝试做一个用户管理模块,使用cas管理用户登陆。由于之前也是没做过这类东西,所以在这个过程中主要遇到的问题有这些:

  1. cas服务器的配置;
  2. 集成cas客户端到springboot中;
  3. 如何使用springboot默认的模版thymeleaf
  4. 前端数据如何传给服务器端;
  5. 服务器端在接受不同类型数据的时候,如何做出响应的处理,获取前端传送的数据;
  6. 后端发送的数据传给前端,如何通过模版来表现。

大致归纳起来就是这些,由于是java新手,虽然之前接触过mvc类型的框架,但是在面对这些问题的时候,还是会出这样那样的问题。

如何解决

上边的这些问题,有的甚至花费了我一天的时间,详细的记录这些问题已经解决方法对之后的学习肯定会有帮助。

cas服务器的配置方法

在我看来,cas可以当做是类似譬如数据库一样提供服务的东西,而它的作用则是为系统模块提供单点登录功能。各个系统模块通过集成cas客户端,并完成响应的配置即可实现用户登录管理。 要想模块获得单点登录功能,第一步要先完成自己tomcat对https的支持:

1.tomcat的https配置方法

这一步操作可以参考网上相关教程,比较多,我参考的主要是这个,特别要注意的是,在配置秘钥的时候,输入名字和姓氏、组织单位和组织的时候,一定要配置成自己的服务器域名。 比如我在自己的hosts文件中增加了一条127.0.0.1 cas.eclipsesv.com,我在本地进行测试,就把上边要配置的内容写成cas.eclipsesv.com。 另外要注意的就是在配置过程中一定要细心,注意字母大小写,文件路径这些东西。

2.获取cas server

在完成https配置之后从cas官网上下载完整的cas server,地址在这里; 完成下载之后,解压压缩包,将modules文件夹中的cas-server-webapp-4.0.0.war复制出来,放在配置好的tomcat的webapp文件夹中。 这个时候,cas就算差不多配置完成了。

3.自定义cas server

默认的cas server只能按照配置文件中的用户名和密码进行登录,并且登录页面和登出页面都是cas官方提供的,自己如果要用的话肯定是要改改的。

我们学习过程中用的是oralce数据库,所以要给cas server提供访问oracle的能力,从数据库中读取用户名和密码。 完成这一步需要做两个操作,在cas的lib文件夹中增加commons-pool-1.5.7、commons-dbcp-1.4、ojdbc6这三个jar包;

另外就是在tomcat/webapps/cas/文件夹中的deployerConfigContext.xml中增加如下配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<bean id="casDataSource" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName">
     <value>oracle.jdbc.driver.OracleDriver</value>
   </property>
   <property name="url">
     <value>jdbc:oracle:thin:@10.211.55.17:1521:xe</value>
   </property>    
   <property name="username">
     <value>wangmeng</value>    
   </property>
   <property name="password">
     <value>abc123</value>
   </property>
</bean>
<bean id="primaryAuthenticationHandler" 
    class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
    <property name="dataSource" ref="casDataSource" />
    <property name="sql" value="select PASSWORD from USERS where USER_NAME = ?" />
</bean>

其中上边的bean中是关于数据库的连接,包括数据库ip、端口和实例名以及登录用户名和密码;后边一个bean中则是关于操作用户表的内容,以及查询语句。

另外,如果要自定义cas serveer的默认登录和登出页面,可以在cas文件夹中的WEB-INF/view/jsp/default/ui/中完成修改,casLogoutView.jsp是登出页面,casLoginView.jsp是登录页面。

经过以上三步操作cas server配置基本就可以完成了。

springboot集成cas

在这里,我使用的是Shiro,并主要参考了这两篇博客,spring boot集成shiro和casShiro & CAS 实现单点登录。按照这两篇博客中讲的内容就可以把cas客户端即成到springboot中了。

thymeleaf模版的使用

thymeleaf 是springboot 默认使用的模版,在官网上可以找到比较丰富的文档,讲的还是比较好的。我在使用中主要用到了后端传对象给thymeleaf进行渲染,thymeleaf循环、判断这些很基本的功能。打算这周参考官方文档再系统的过一遍它的其它功能。

前端post数据给后端

在这个小模块的开发过程中,前端post数据我主要是用两种方式,form表单提交和ajax传输。

form表单结合thymeleaf

由于使用了thymeleaf模版,因此表单提交的方法变得更加简便:

1
2
3
4
5
6
7
8
9
<form method="POST" th:action="@{'/newDiscussion/'+${groupid.groupID}}" th:object="${newDiscuss}">
    <div class="form-group"> 
        <label for="groupname">讨论组名</label>
        <input type="text" th:field="*{discussionName}" class="form-control" id="groupname"></input>
        <label for="desc">描述</label>
        <input type="text" th:field="*{desc}" class="form-control" id="desc"></input>
    </div>
    <button type="submit" class="btn btn-default">Submit</button>
</form>

以上述代码为例,该表单是填写信件讨论组相关的内容,我需要做的只是在对应的input中完成newDiscuss对象discussionName、desc属性的填写即可完成。而newDiscuss对象是怎么来的,将会在后边有详细解释。

ajax数据传输

除了form表单,我可能需要在点击某个按钮之后将某些东西post给后端,并做出响应。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function sendData(){
    var addusers = [];
    uniqueGroup = $("h2[name='uniqueGroup']").attr("id");
    addusers.push(uniqueGroup);
    $("input[type='checkbox']").each(
                    function() {
                        if($(this)[0].checked==true)
                        {
                            userid = ($(this).attr("id"));
                            addusers.push(userid);
                        }     
                    }
                );
    $.ajax({
        url:"http://cas.eclipsesv.com:9000/group/adduser",
        data:JSON.stringify(addusers),
        type:"post",
        contentType: "application/json; charset=utf-8",
        dataType:"json",
        success:function(responseText){
                $('#myModal').modal('hide');
                var groupid = responseText.redirect;
                    var url = "http://cas.eclipsesv.com:9000/group/"+groupid;
                    window.location.href = url
                }
    });
}

上述代码是要完成将一个由用户id组成的数组post给后端,并在数据传输成功之后将页面重定向。

后端如何解析来自前端的数据

对应上述前端post数据方法,springboot也有对应的数据解析方法:

解析form表单提交的数据

刚才提到,前端在提交form表单的时候,只需要完成newDiscuss对应属性的填写即可,而这个newDiscuss对象则是我在form表单页面中通过模版嵌入的对象。

1
2
3
4
5
6
@RequestMapping(value = "/group/{groupid}",method = RequestMethod.GET)
public String group(@PathVariable String groupid,Model model){
    DiscussionGroup discussionGroup = new DiscussionGroup();
    model.addAttribute("newDiscuss", discussionGroup);
    return "group";
}

在前端get此页面的时候,new一个DiscussionGroup对象,在模版中用newDiscuss代表它,这样就可以在前端填写表单的时候完成newDiscuss属性的设置。

在完成属性填写之后,后端解析数据通过以下方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@RequestMapping(value = "/newDiscussion/{groupid}",method = RequestMethod.POST)
public String newDiscussion(@PathVariable String groupid,ModelMap model, DiscussionGroup discussionGroup){
    if (discussionGroup != null) {
        System.out.print(groupid);
    }
    ControllerHelper helper = new ControllerHelper(userDAOImpl, groupUserDAOImpl, groupDAOImpl,
            discussionDAOImpl,commentDAOImpl);
    helper.newDiscussionGroup(discussionGroup,helper.getCurrentUser().getUserId(),groupid);
    return "redirect:/group/"+groupid;
}

直接在函数签名中对应写一个DiscussionGroup对象,用以接受刚刚的newDiscuss,就是这样简单。需要额外做的就是在DiscussionGroup中完成相应属性的getter和setter以及默认构造函数。

解析ajax提交的数据

不同于上边form表单提交那样,接受ajax传输的数据需要按照下边这样来:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@RequestMapping(value = "/comments/delete",method = RequestMethod.POST)
@ResponseBody
public Map<String, String>  delComment(@RequestBody String[] userArray){
    ControllerHelper helper = new ControllerHelper(userDAOImpl, groupUserDAOImpl, groupDAOImpl,
            discussionDAOImpl,commentDAOImpl);
    if (userArray[0] != null) {
        String groupid = helper.delComment(userArray[0]);
        System.out.println(userArray[0]+"评论已删除");
        Map<String, String> result = new HashMap<String, String>();
        result.put("redirect", groupid);
        return result;
    }
    else
        return null;
}

需要用到@ResponseBody注解,并且这次返回给前端的数据也不是具体的某个view名,而是实实在在的数据,比如说一个键值对,而返回的数据可以在ajax的sucess中处理:

1
2
3
4
5
6
success:function(responseText){
    $('#myModal').modal('hide');
    var groupid = responseText.redirect;
        var url = "http://cas.eclipsesv.com:9000/group/"+groupid;
        window.location.href = url
}

未完待续

上边写的都是作为一个入门菜鸟在学习过程中遇到的问题和一些稚嫩的解决方法,后边会遇到更复杂的问题,我也会一如即往的记录自己的成长过程。