课表是在一张table里的,提取table里的内容进行解析,解析方法不止一种,我在解析过程中也尝试了多种方法,直接看代码把

?
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/**
     * 根据网页返回结果解析课程并保存
     *
     * @param content
     * @return
     */
    publicString parseCourse(String content) {
        StringBuilder result = newStringBuilder();
        Document doc = Jsoup.parse(content);
  
        Elements semesters = doc.select(option[selected=selected]);
        String[] years=semesters.get(0).text().split(-);
        intstartYear=Integer.parseInt(years[0]);
        intendYear=Integer.parseInt(years[1]);
        intsemester=Integer.parseInt(semesters.get(1).text());
  
  
  
        Elements elements = doc.select(table#Table1);
        Element element = elements.get(0).child(0);
        //移除一些无用数据
  
        element.child(0).remove();
        element.child(0).remove();
        element.child(0).child(0).remove();
        element.child(4).child(0).remove();
        element.child(8).child(0).remove();
        introwNum = element.childNodeSize();
        int[][] map = newint[11][7];
        for(inti = 0; i < rowNum - 1; i++) {
            Element row = element.child(i);
            intcolumnNum = row.childNodeSize() - 2;
            for(intj = 1; j < columnNum; j++) {
                Element column = row.child(j);
                intweek = fillMap(column, map, i);
                //填充map,获取周几,第几节至第几节
                //作用:弥补不能获取这些数据的格式
                if(column.hasAttr(rowspan)) {
                    try{
                        System.out.println(周+ week+  第+ (i + 1)+ 节-第+ (i + Integer.parseInt(column.attr(rowspan))) + 节);
                        splitCourse(column.html(), startYear,endYear,semester,week, i + 1,i + Integer.parseInt(column.attr(rowspan)));
                    }catch(NumberFormatException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
  
        returnresult.toString();
    }
  
  
  
    /**
     * 根据传进来的课程格式转换为对应的实体类并保存
     * @param sub
     * @param startYear
     * @param endYear
     * @param semester
     * @param week
     * @param startSection
     * @param endSection
     * @return
     */
    privateCourse storeCourseByResult(String sub,intstartYear,intendYear,intsemester, intweek,
            intstartSection, intendSection) {
        // 周二第1,2节{第4-16周}      二,1,2,4,16,null
        // {第2-10周|3节/周}            null,null,null,2,10,3节/周
        // 周二第1,2节{第4-16周|双周}   二,1,2,4,16,双周
        // 周二第1节{第4-16周}            二,1,null,4,16,null
        // 周二第1节{第4-16周|双周}         二,1,null,4,16,双周
        // str格式如上,这里只是简单考虑每个课都只有两节课,实际上有三节和四节,模式就要改动,其他匹配模式请自行修改
  
        String reg = 周?(.)?第?(\d{1,2})?,?(\d{1,2})?节?\{第(\d{1,2})-(\d{1,2})周\|?((.*周))?\};
  
        String splitPattern =
;
        String[] temp = sub.split(splitPattern);
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(temp[1]);
        matcher.matches();
        Course course = newCourse();
        //课程开始学年
        course.setStartYear(startYear);
        //课程结束学年
        course.setEndYear(endYear);
        //课程学期
        course.setSemester(semester);
  
        //课程名
        course.setCourseName(temp[0]);
        //课程时间,冗余字段
        course.setCourseTime(temp[1]);
        //教师
        course.setTeacher(temp[2]);
  
        try{
            // 数组可能越界,即没有教室
            course.setClasssroom(temp[3]);
        }catch(ArrayIndexOutOfBoundsException e) {
            course.setClasssroom(无教室);
        }
        //周几,可能为空,此时使用传进来的值
        if(null!= matcher.group(1)){
            course.setDayOfWeek(getDayOfWeek(matcher.group(1)));
        }else{
            course.setDayOfWeek(getDayOfWeek(week+));
        }
        //课程开始节数,可能为空,此时使用传进来的值
        if(null!= matcher.group(2)){
            course.setStartSection(Integer.parseInt(matcher.group(2)));
        }else{
            course.setStartSection(startSection);
        }
  
        //课程结束时的节数,可能为空,此时使用传进来的值
        if(null!= matcher.group(3)){
            course.setEndSection(Integer.parseInt(matcher.group(3)));
        }else{
            course.setEndSection(endSection);
        }
  
        //起始周
        course.setStartWeek(Integer.parseInt(matcher.group(4)));
        //结束周
        course.setEndWeek(Integer.parseInt(matcher.group(5)));
        //单双周
        String t = matcher.group(6);
        setEveryWeekByChinese(t, course);
        save(course);
        returncourse;
    }
  
  
  
  
    /**
     * 提取课程格式,可能包含多节课
     * @param str
     * @param startYear
     * @param endYear
     * @param semester
     * @param week
     * @param startSection
     * @param endSection
     * @return
     */
    privateint splitCourse(String str, intstartYear,intendYear,intsemester,intweek, intstartSection,
            intendSection) {
        String pattern =
;
        String[] split = str.split(pattern);
        if(split.length > 1) {// 如果大于一节课
            for(inti = 0; i < split.length; i++) {
                if(!(split[i].startsWith(
) && split[i].endsWith(
))) {
                    storeCourseByResult(split[i], startYear,endYear,semester,week, startSection,
                            endSection);// 保存单节课
                }else{
                    //
文化地理(网络课程)
周日第10节{第17-17周}
李宏伟
                    // 以上格式的特殊处理,此种格式在没有教师的情况下产生,即教室留空后
依旧存在
                    intbrLength =
.length();
                    String substring = split[i].substring(brLength,
                            split[i].length() - brLength);
                    storeCourseByResult(substring, startYear,endYear,semester,week, startSection,
                            endSection);// 保存单节课
                }
            }
            returnsplit.length;
        }else{
            storeCourseByResult(str, startYear,endYear,semester,week, startSection, endSection);// 保存
            return1;
        }
    }
  
    /**
     * 填充map,获取周几,第几节课至第几节课
     * @param childColumn
     * @param map
     * @param i
     * @return 周几
     */
    publicstatic int fillMap(Element childColumn, intmap[][], inti) {
        //这个函数的作用自行领悟,总之就是返回周几,也是无意中发现的,于是就这样获取了,作用是双重保障,因为有些课事无法根据正则匹配出周几第几节到第几节
        booleanhasAttr = childColumn.hasAttr(rowspan);
        intweek = 0;
        if(hasAttr) {
            for(intt = 0; t < map[0].length; t++) {
                if(map[i][t] == 0) {
                    intr = Integer.parseInt(childColumn.attr(rowspan));
                    for(intl = 0; l < r; l++) {
                        map[i + l][t] = 1;
                    }
                    week = t + 1;
                    break;
                }
            }
  
        }else{
            if(childColumn.childNodes().size() > 1) {
                childColumn.attr(rowspan,1);
            }
            for(intt = 0; t < map[0].length; t++) {
                if(map[i][t] == 0) {
                    map[i][t] = 1;
                    week = t + 1;
                    break;
                }
            }
        }
        returnweek;
    }
    /**
     * 设置单双周
     * @param week
     * @param course
     */
    publicvoid setEveryWeekByChinese(String week, Course course) {
        // 1代表单周,2代表双周
        if(week != null) {
            if(week.equals(单周))
                course.setEveryWeek(1);
            elseif (week.equals(双周))
                course.setEveryWeek(2);
        }
        // 默认值为0,代表每周
    }
  
    /**根据中文数字一,二,三,四,五,六,日,转换为对应的阿拉伯数字
     * @param day
     * @return int
     */
    publicint getDayOfWeek(String day) {
        if(day.equals(一))
            return1;
        elseif (day.equals(二))
            return2;
        elseif (day.equals(三))
            return3;
        elseif (day.equals(四))
            return4;
        elseif (day.equals(五))
            return5;
        elseif (day.equals(六))
            return6;
        elseif (day.equals(日))
            return7;
        else
            return0;
    }

以上代码是提取课程的关键代码,课程的格式是在一个table里,tr里有很多td,td里就是课程,一个td里可能不止一节课

td有rowspan属性,代表占了几行,2代表占了两行,也就是两节课,有些课不是两节课的,rowspan的值也就对应改变,课程的节数有1,2,3,4节都有。我们可以根据课程的时间提取该课程是周几上课,第几节课到第几节课,有了这些信息就可以在界面上显示出来了,但是,有些格式,如第2-10周|3节/周是没办法提取时间的,这时候就用一定的技巧提取它,这里使用了fillmap函数对一个7*12的数组进行填充,原理是扫描一行,如果具有rowspan值,则填充该行该列为1,如果rowspan大于等于2,则该列下面几行对应的列也填充为1,等到扫描下一行的时候,该位置不会有课程,且不会有td,则如果是一个空td,则填充该行第一个为0的位置。技巧有点难以理解,具体细节稍微自己琢磨领悟下,这样课程的信息就都提取出来了,当然提取方式不止一种。这种方法也不一定能提取所有格式的课程。

提取完毕后进行显示,本来呢是使用LinearLayout简单达到超级课程表的效果的,后来稍微暴力的使用了下自定义ViewGroup,注意了,这个自定义ViewGroup不具有现实使用意义,只是为了展示效果,里面的代码都太暴力了。。。所以看过一遍就无视吧,简直不忍直视

首先是自定义属性

?
1
2
3
4
5
6
7
8
9
10
<!--?xml version=1.0encoding=utf-8?-->
<resources><linknode><linknode>
    <declare-styleable name="CourseView">
         
         
         
         
    </attr></attr></attr></attr></declare-styleable>
     
</linknode></linknode></resources>

然后是课程自定义View,继承Button,增加一些课程信息而已。

?
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
packagecn.lizhangqu.kb.view;
importandroid.content.Context;
importandroid.content.res.TypedArray;
importandroid.util.AttributeSet;
importandroid.widget.Button;
importcn.lizhangqu.kb.R;
publicclass CourseView extendsButton {
    privateint courseId;
    privateint startSection;
    privateint endSection;
    privateint weekDay;
    publicCourseView(Context context) {
        this(context,null);
    }
    publicCourseView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
    publicCourseView(Context context, AttributeSet attrs, intdefStyle) {
        super(context, attrs, defStyle);
        TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.CourseView);
        courseId = array.getInt(R.styleable.CourseView_courseId, 0);
        startSection=array.getInt(R.styleable.CourseView_startSection,0);
        endSection=array.getInt(R.styleable.CourseView_endSection,0);
        weekDay=array.getInt(R.styleable.CourseView_weekDay,0);
        array.recycle();
    }
    publicint getCourseId() {
        returncourseId;
    }
    publicvoid setCourseId(intcourseId) {
        this.courseId = courseId;
    }
    publicint getStartSection() {
        returnstartSection;
    }
    publicvoid setStartSection(intstartSection) {
        this.startSection = startSection;
    }
    publicint getEndSection() {
        returnendSection;
    }
    publicvoid setEndSection(intendSection) {
        this.endSection = endSection;
    }
    publicint getWeek() {
        returnweekDay;
    }
    publicvoid setWeek(intweek) {
        this.weekDay = week;
    }
}

最后是自定义布局,简单暴力,注意了,这个布局没有处理重复时间的课程,也就是说没有处理单双周的情况,只是用来简单显示

?
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
packagecn.lizhangqu.kb.view;
importjava.util.ArrayList;
importjava.util.List;
importandroid.content.Context;
importandroid.content.res.TypedArray;
importandroid.util.AttributeSet;
importandroid.util.DisplayMetrics;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.view.WindowManager;
publicclass CourseLayout extendsViewGroup {
    privateList<courseview><linknode><linknode> courses = newArrayList<courseview>();
    privateint width;//布局宽度
    privateint height;//布局高度
    privateint sectionHeight;//每节课高度
    privateint sectionWidth;//每节课宽度
    privateint sectionNumber = 12;//一天的节数
    privateint dayNumber = 7;//一周的天数
    privateint pideWidth = 2;//分隔线宽度,dp
    privateint pideHeight = 2;//分隔线高度,dp
    publicCourseLayout(Context context) {
        this(context,null);
    }
    publicCourseLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    publicCourseLayout(Context context, AttributeSet attrs, intdefStyle) {
        super(context, attrs, defStyle);
        width = getScreenWidth();//默认宽度全屏
        height = dip2px(600);//默认高度600dp
        pideWidth = dip2px(2);//默认分隔线宽度2dp
        pideHeight = dip2px(2);//默认分隔线高度2dp
    }
    @Override
    protectedvoid onMeasure(intwidthMeasureSpec, intheightMeasureSpec) {
        setMeasuredDimension(width, height);
    }
    @Override
    protectedvoid onLayout(booleanchanged, intl, intt, intr, intb) {
        courses.clear();//清除
        sectionHeight = (getMeasuredHeight() - pideWidth * sectionNumber)/ sectionNumber;//计算每节课高度
        sectionWidth = (getMeasuredWidth() - pideWidth * dayNumber)/ dayNumber;//计算每节课宽度
        intcount = getChildCount();//获得子控件个数
        for(inti = 0; i < count; i++) {
            CourseView child = (CourseView) getChildAt(i);
            courses.add(child);//增加到list中
             
            intweek = child.getWeek();//获得周几
            intstartSection = child.getStartSection();//开始节数
            intendSection = child.getEndSection();//结束节数
            intleft = sectionWidth * (week - 1) + (week) * pideWidth;//计算左边的坐标
            intright = left + sectionWidth;//计算右边坐标
            inttop = sectionHeight * (startSection - 1) + (startSection) * pideHeight;//计算顶部坐标
            intbottom = top + (endSection - startSection + 1) * sectionHeight+ (endSection - startSection) * pideHeight;//计算底部坐标
            child.layout(left, top, right, bottom);
        }
    }
    publicint dip2px(floatdip) {
        floatscale = getContext().getResources().getDisplayMetrics().density;
        return(int) (dip * scale + 0.5f);
    }
    publicint getScreenWidth() {
        WindowManager manager = (WindowManager) getContext().getSystemService(
                Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = newDisplayMetrics();
        manager.getDefaultDisplay().getMetrics(displayMetrics);
        returndisplayMetrics.widthPixels;
    }
}
</courseview></linknode></linknode></courseview>

使用控件,记得增加命名空间

?
1
2
3
4
5
6
7
8
9
<linearlayout android:layout_height="match_parent"android:layout_width="match_parent"android:orientation="vertical"tools:context="${relativePackage}.${activityClass}"xmlns:android="https://schemas.android.com/apk/res/android"xmlns:custom="https://schemas.android.com/apk/res/cn.lizhangqu.kb"xmlns:tools="https://schemas.android.com/tools"><linknode><linknode>
    <linearlayout android:id="@+id/weekend"android:layout_height="30dp"android:layout_width="match_parent"android:orientation="horizontal"><button android:background="@drawable/kb0"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp"android:text="周一"android:textcolor="#2e94da"android:textsize="12sp"></button><button android:background="@drawable/kb0"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp"android:text="周二"android:textcolor="#2e94da"android:textsize="12sp"></button><button android:background="@drawable/kb0"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp"android:text="周三"android:textcolor="#2e94da"android:textsize="12sp"></button><button android:background="@drawable/kb0"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp"android:text="周四"android:textcolor="#2e94da"android:textsize="12sp"></button><button android:background="@drawable/kb0"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp"android:text="周五"android:textcolor="#2e94da"android:textsize="12sp"></button><button android:background="@drawable/kb0"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp"android:text="周六"android:textcolor="#2e94da"android:textsize="12sp"></button><button android:background="@drawable/kb0"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp"android:text="周日"android:textcolor="#2e94da"android:textsize="12sp">
     
    <scrollview android:id="@+id/scrollview"android:layout_height="wrap_content"android:layout_width="wrap_content"android:scrollbars="none">
        <cn.lizhangqu.kb.view.courselayout android:background="#e8e8e8"android:id="@+id/courses"android:layout_height="wrap_content"android:layout_width="wrap_content">
        </cn.lizhangqu.kb.view.courselayout>
    </scrollview></button></linearlayout></linknode></linknode></linearlayout>

?
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
packagecn.lizhangqu.kb.activity;
importjava.util.List;
importandroid.app.Activity;
importandroid.content.res.ColorStateList;
importandroid.graphics.Color;
importandroid.os.Bundle;
importandroid.util.TypedValue;
importandroid.view.Gravity;
importcn.lizhangqu.kb.R;
importcn.lizhangqu.kb.model.Course;
importcn.lizhangqu.kb.service.CourseService;
importcn.lizhangqu.kb.util.CommonUtil;
importcn.lizhangqu.kb.view.CourseLayout;
importcn.lizhangqu.kb.view.CourseView;
/**
 * @author lizhangqu
 * @date 2015-2-1
 */
publicclass CourseActivity extendsActivity {
    //某节课的背景图,用于随机获取
    privateint[] bg={R.drawable.kb1,R.drawable.kb2,R.drawable.kb3,R.drawable.kb4,R.drawable.kb5,R.drawable.kb6,R.drawable.kb7};
    privateCourseService courseService;
    privateCourseLayout layout;
    @Override
    protectedvoid onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_course);
        initValue();
        initView();
    }
    /**
     * 初始化变量
     */
    privatevoid initValue() {
        courseService=CourseService.getCourseService();
    }
    /**
     * 初始化视图
     */
    privatevoid initView() {
        //这里有逻辑问题,只是简单的显示了下数据,数据并不一定是显示在正确位置
        //课程可能有重叠
        //课程可能有1节课的,2节课的,3节课的,因此这里应该改成在自定义View上显示更合理
        List<course><linknode><linknode> courses=courseService.findAll();//获得数据库中的课程
        layout=(CourseLayout) findViewById(R.id.courses);
        Course course=null;
        //循环遍历
        for(inti = 0; i < courses.size(); i++) {
            course=courses.get(i);
            CourseView view=newCourseView(getApplicationContext());
            view.setCourseId(course.getId());
            view.setStartSection(course.getStartSection());
            view.setEndSection(course.getEndSection());
            view.setWeek(course.getDayOfWeek());
            intbgRes=bg[CommonUtil.getRandom(bg.length-1)];//随机获取背景色
            view.setBackgroundResource(bgRes);
            view.setText(course.getCourseName()+@+course.getClasssroom());
            view.setTextColor(Color.WHITE);
            view.setTextSize(12);
            view.setGravity(Gravity.CENTER);
            layout.addView(view);
            }
    }
}
</linknode></linknode></course>

背景图使用的是shape,这里贴出其中一个,其余的就只是颜色不同

?
1
2
3
4
5
6
7
<!--?xml version=1.0encoding=utf-8?-->
<shape android:shape="rectangle"xmlns:android="https://schemas.android.com/apk/res/android"><linknode><linknode>
    <solid android:color="#ef9ea0/">
    <stroke android:color="#ef9ea0"android:width="1dp">
    <corners android:radius="5dp/">
  
</corners></stroke></solid></linknode></linknode></shape>

至此,超级课程表的一键提取课表功能就完成了。显示最终效果见下方

整个过程可简单概括为抓包分析,数据提取,数据显示,其中关键的一步就是数据的提取。这个过程中有个注意点就是抓课程数据的时候header请求头信息里的referer信息请务必设置为登录成功后的网址,即https://***.***.***.***/xs_main.aspx?xh=XH,否则抓数据的时候页面会被循环重定向,将抓不到数据,程序也会报异常。

实现-超级课程表——校园登录(2)相关推荐

  1. 实现-超级课程表——校园登录(1)

    如果你是在校大学生,或许你用多了各种课程表,比如课程格子,超级课程表.它们都有一个共同点就是可以一键导入教务处的课程.那么一直都是用户的我们,没有考虑过它是如何实现的.那么现在就来模仿一款" ...

  2. 【超级课程表】大学校园客户端App(查成绩,一卡通,课表,一键评教,正方系统……)

    原文地址:https://zhuanlan.zhihu.com/p/29776226 githu地址:https://github.com/longer96/CDTU 大一时针对我校开发的校园客户端, ...

  3. 超级课程表显示服务器错误,超级课程表怎么注册?超级课程表注册不了怎么办?...

    超级课程表怎么注册 超级课程表是一款校园课程兼社交的应用软件,通过对接高校教务系统,可快速录入课表到手机,收录五百万课程信息,可以实现校内跨院系任意蹭课.超级课程表怎么注册呢?您是否在注册上遇到了问题 ...

  4. “超级课程表”余佳文:初生牛犊不怕虎

    余佳文,1990年生人,广州某大学大四学生:小小年纪已经是一个30余人创业公司的CEO,其团队开发的"超级课程表"是个能为大学生自动获取课表.附带校园社交功能的应用,在高校尤其是广 ...

  5. android课程表删除课程,超级课程表话题删除方法

    超级课程表是学生党必备的神器哦,非常好用哦,还可以进行交友哦,今天就告诉大家如何删除发表的话题哦. [话题删除方法] 1)打开超级课程表,在[下课聊]栏点击右上角[按钮],选择[我参与的]: 2)找到 ...

  6. Android超级课程表实现原理

    感觉有必要更新一下文章.很久之前看到的这篇博文,觉得写的不错,故转载收藏.之后陆续有人私信相关问题(要源码什么的),都没有过多的回复. -------------------------------- ...

  7. android 仿课程格子,课程格子对比超级课程表 实用性大比拼

    开学在即,大家已经做好准备了吗?新学期我们除了要接受新的挑战,新的同学之外,还有就是新的课表,现在的学生压力是越来越大,课程也是越来越多,如何才能够更好的安排课程,单是一张纸质的课表可不管用,今天小编 ...

  8. java毕业设计_超级课程表

    超级课程表mysql数据库创建语句 超级课程表oracle数据库创建语句 超级课程表sqlserver数据库创建语句 超级课程表spring+springMVC+hibernate框架对象(javaB ...

  9. android 项目实战——打造超级课程表一键提取课表功能

    转载文章请注明来自http://blog.csdn.net/sbsujjbcy 如果你是在校大学生,或许你用多了各种课程表,比如课程格子,超级课程表.它们都有一个共同点就是可以一键导入教务处的课程.那 ...

最新文章

  1. 联想小新air13pro重装系统_联想 小新Air 13 ProU盘装系统win7教程
  2. POC测试——原型验证,降低风险,IT系统销售工作之一
  3. win10 自待wmi应用 查询wmi
  4. Oracle truncate table 与 delete tabel的区别(转)
  5. Java黑皮书课后题第5章:5.4(将英里转换成千米)编写程序,显示下面的表格(注意:1英里为1.609千米)
  6. Virtualenv系列(一):使用Virtualenv搭建python虚拟环境
  7. mysql登录root 1130_通过Navicat for MySQL远程连接的时候报错mysql 1130的解决方法
  8. 使用redis数据库的目的?
  9. sql 如何设置行级锁_如何使用SQL Server 2016行级安全性过滤和阻止数据访问
  10. zynq开发系列5:通过AXI GPIO的中断实现PL端按键控制PS端LED
  11. 程序人生:做技术,切不可沉湎于技术
  12. 选择排序(Select Sort)
  13. Java实现学生管理系统代码
  14. 最实用的正则表达式整理
  15. 比尔沃服务器位置,防辐射植物哪个更好?
  16. DSP TMS320C5509A 控制DDS AD9854芯片进行AM-MSK调制
  17. 关于我为什么跨考计算机研究生以及对未来的思考
  18. F矩阵的自由度是多少?
  19. RRT路径规划算法在二维仿真环境中的应用 -- Python代码实现
  20. 死锁的四个必要条件和解决办法

热门文章

  1. 设备软件控制平台会是什么样子?
  2. workbench小教程
  3. 老男孩Openstack全新实战课程
  4. 简单说说disney sea
  5. mysql 查询rownum_mysql中实现rownum功能
  6. 完美国际地图文件在服务器那个文件夹,完美世界的安装目录在什么地方啊
  7. 浏览器中java在什么位置_win10浏览器安装位置在哪里_如何找到win10浏览器的安装路径...
  8. 马航失联客机中国乘客家属发表联合声明
  9. #MH370失联五周年# 从马航失联五周年看航空安全
  10. [Photoshop] ps中选区新建为图层的快捷键