-
Notifications
You must be signed in to change notification settings - Fork 0
hw3 myCourseMVC
Spring MVC๋ฅผ ํ์ฉํ์ฌ ์๊ตฌ ์ฌํญ์ ๋ง๊ฒ ์น ์์ฉ ํ๋ก๊ทธ๋จ์ ์์ฑํ๋ค.
๋ก๊ทธ์ธ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ๊ธฐ ์ํด security-context.xml
์ jdbc-user-service๋ฅผ ์ด์ฉํ์ฌ DB์ ์ ์ฅ๋ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์กฐํํ์ฌ ์ธ์ฆํ๋ค. ๋ํ, ์ ๊ทผ ๊ถํ์ Login ํ์ด์ง๋ง permitAll๋ก ์ง์ ํ๊ณ ๋๋จธ์ง ํ์ด์ง๋ค์ hasRole(โROLE_STUDENTโ)
๋ก ์ง์ ํจ์ผ๋ก์จ ์น ํ์ด์ง ์ ์ ์ ์ธ์ฆ๋์ง ์์ ๊ฒฝ์ฐ์๋ ๋ก๊ทธ์ธ ํผ์ ์ถ๋ ฅํ๋๋ก ํ๊ณ , ์ธ์ฆ๋ ๊ฒฝ์ฐ ๋ค๋ฅธ ํ์ด์ง๋ค์ ๋๋ฌ๋ณผ ์ ์๋๋ก ํ๋ค.
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username, password, enabled from users where username=?"
authorities-by-username-query="select username, authority from authorities where username=?" />
</authentication-provider>
</authentication-manager>
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/summary" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/details/2018-1" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/details/2018-2" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/details/2019-1" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/details/2019-2" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/details/2020-1" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/details/2020-2" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/register" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/doRegister" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/successRegistration" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/viewRegistration" access="hasRole('ROLE_STUDENT')" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/**" access="denyAll" />
<form-login login-page="/login" authentication-failure-url="/login?error" />
<logout />
</http>
๋ก๊ทธ์ธ ๋์ง ์์ ์ํ์ผ ๊ฒฝ์ฐ ๋ณด์ฌ์ค ๋ก๊ทธ์ธ ํ์ด์ง(login.jsp
)๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฒด์ ์ผ๋ก ์์ฑํ์๋ค. ์ธ์ฆ ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด LoginController.java
์์ ์ค์ ๋ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋๊ณ ์ ์์ ์ผ๋ก ๋ก๊ทธ์ธ ํ ๋๋ CSRF Token์ ํจ๊ป ์ ์กํจ์ผ๋ก์จ ๊ณต๊ฒฉ์๋ก๋ถํฐ์ ๊ณต๊ฒฉ์ ๋ฐฉ์งํ๋ค.
<head>
<title>Login (jhlee customized)</title>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="<c:url value="login" />">
<h2 class="form-signin-heading">Please sign in๐</h2>
<c:if test="${ not empty errorMsg }">
<div style="color: #ff0000"> <h4> ${ errorMsg }</h4></div>
</c:if>
<c:if test="${ not empty logoutMsg }">
<div style="color: #0000ff"> <h4> ${ logoutMsg }</h4></div>
</c:if>
<p>
<label for="username" class="sr-only">UserName</label>
<input type="text" id="username", name="username", class="form-control" placeholder="Username" required autofocus>
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password", name="password", class="form-control" placeholder="Password" required>
</p>
<input name="${ _csrf.parameterName }" type="hidden" value="${ _csrf.token }" />
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</div>
</body>
![](https://github.com/coding-Benny/web-framework/raw/master/myCourseMVC/images/login.png)
์ธ์ฆ๋ ์ฌ์ฉ์๋ ํ๊ธฐ ๋ณ ์ด์ ํ์ ์กฐํ, ์๊ฐ ์ ์ฒญํ๊ธฐ, ์๊ฐ ์ ์ฒญ ์กฐํ ๋ฉ๋ด๊ฐ ๋ณด์ด๋ ๋ฉ์ธ ํ์ด์ง(home.jsp
)๋ก ์ด๋ํ๋ค. ๋ก๊ทธ์์ ์์๋ LoginController.java
์์ ์ ์ํ๋๋ก ๋ก๊ทธ์ธ ํผ์ผ๋ก ์ด๋ํ์ฌ ๋ก๊ทธ์์ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค.
<head>
<title>Menu</title>
</head>
<body>
<p><a href="${ pageContext.request.contextPath }/summary">ํ๊ธฐ๋ณ ์ด์ ํ์ ์กฐํ</a></p>
<p><a href="${ pageContext.request.contextPath }/register">์๊ฐ ์ ์ฒญํ๊ธฐ</a></p>
<p><a href="${ pageContext.request.contextPath }/viewRegistration">์๊ฐ ์ ์ฒญ ์กฐํ</a></p>
<c:if test="${ pageContext.request.userPrincipal.name != null }">
<a href="javascript:document.getElementById('logout').submit()">Logout</a>
</c:if>
<form id="logout" action="<c:url value="/logout" />" method="post">
<input type="hidden" name="${ _csrf.parameterName }" value="${ _csrf.token }" />
</form>
</body>
![](https://github.com/coding-Benny/web-framework/raw/master/myCourseMVC/images/main.png)
๊ฐ ๋ฉ๋ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์๋ ๋จผ์ model์ด ํ์ํ๋ค. ์ด๋ฒ ๊ณผ์ ์์์ ๋ชจ๋ธ์ ์๊ฐํ ๊ต๊ณผ๋ชฉ์ด๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ด Course.java
๋ฅผ ์์ฑํ์๋ค. ์ถํ ์๊ฐ์ ์ฒญ ํผ ์์ฑ ์ ์
๋ ฅํ ๋ฐ์ดํฐ์ ๋ํ ๊ฒ์ฆ ์์
์ ํ ๋ ๊ฐ ๋ณ์์ ๋ํ ์กฐ๊ฑด๊ณผ ๋ง์กฑํ์ง ์์์ ๊ฒฝ์ฐ ์ถ๋ ฅํ ๋ฉ์์ง๋ฅผ ์ค์ ํ๋ค.
@Getter
@Setter
@NoArgsConstructor
@ToString
public class Course {
@Range(min=2018, max=2021, message="It's not a valid course year")
private int year; // ์๊ฐ๋
๋
@Range(min=1, max=2, message="It's not a valid semester")
private int semester; // ํ๊ธฐ
@NotEmpty(message="Class name cannot be empty")
private String className; // ๊ต๊ณผ๋ชฉ๋ช
@NotEmpty(message="Classification cannot be empty")
private String classification; // ๊ต๊ณผ๊ตฌ๋ถ
@NotEmpty(message="Professor name cannot be empty")
private String professor; // ๋ด๋น๊ต์
@Range(min=1, max=3, message="It's not a valid credits")
private int credits; // ํ์
}
DB์ ์ ์ฅ๋ ๋ฐ์ดํฐ์ ์ ๊ทผํ๋ ํธ๋์ญ์
๊ฐ์ฒด์ธ CoruseDao.java
์ ์์ฑ๋ ๋ฉ์๋๋ฅผ ํตํด ํ์ํ ์ ๋ณด๋ฅผ ์กฐํํ๋๋ก ํ์๋ค.
@Repository
public class CourseDao {
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public List<Course> getSummary() { // ํ๋
/ํ๊ธฐ๋ณ ์ด์ ํ์ ์ ๋ณด ์กฐํ
String sqlStatement = "select ์๊ฐ๋
๋, ํ๊ธฐ, sum(ํ์ ) from courses GROUP BY ์๊ฐ๋
๋, ํ๊ธฐ ORDER BY ์๊ฐ๋
๋, ํ๊ธฐ";
return jdbcTemplate.query(sqlStatement, new RowMapper<Course>() {
@Override
public Course mapRow(ResultSet rs, int rowNum) throws SQLException {
Course summary = new Course();
summary.setYear(rs.getInt("์๊ฐ๋
๋"));
summary.setSemester(rs.getInt("ํ๊ธฐ"));
summary.setCredits(rs.getInt("sum(ํ์ )"));
return summary;
}
});
}
// ํน์ ํ๊ธฐ์ ์๊ฐํ ๊ฐ์ ์ ๋ณด ์กฐํ
public List<Course> getSemesterCourses(int year, int semester) {
String sqlStatement = "select * from courses where ์๊ฐ๋
๋=? and ํ๊ธฐ=?";
return jdbcTemplate.query(sqlStatement, new Object[] {year, semester}, new RowMapper<Course>() {
@Override
public Course mapRow(ResultSet rs, int rowNum) throws SQLException {
Course course = new Course();
course.setYear(rs.getInt("์๊ฐ๋
๋"));
course.setSemester(rs.getInt("ํ๊ธฐ"));
course.setClassName(rs.getString("๊ต๊ณผ๋ชฉ๋ช
"));
course.setClassification(rs.getString("๊ต๊ณผ๊ตฌ๋ถ"));
course.setProfessor(rs.getString("๋ด๋น๊ต์"));
course.setCredits(rs.getInt("ํ์ "));
return course;
}
});
}
public int getTotalCredits() { // ์ด์ ์ด ํ์ ๊ณ์ฐ
String sqlStatement = "select sum(ํ์ ) from courses";
return jdbcTemplate.queryForObject(sqlStatement, Integer.class);
}
public boolean insert(Course insertCourse) { // DB์ ์๊ฐ์ ์ฒญ ์ ๋ณด ์ฝ์
int year = insertCourse.getYear();
int semester = insertCourse.getSemester();
String className = insertCourse.getClassName();
String classification = insertCourse.getClassification();
String professor = insertCourse.getProfessor();
int credits = insertCourse.getCredits();
String sqlStatement = "insert into registrations (๋
๋, ํ๊ธฐ, ๊ต๊ณผ๋ชฉ๋ช
, ๊ต๊ณผ๊ตฌ๋ถ, ๋ด๋น๊ต์, ํ์ ) values (?,?,?,?,?,?)";
return (jdbcTemplate.update(sqlStatement, new Object[] {year, semester, className, classification, professor, credits}) == 1);
}
public List<Course> getRegisterCourses() { // ์๊ฐ์ ์ฒญ ๋ด์ญ ์กฐํ
String sqlStatement = "select * from registrations";
return jdbcTemplate.query(sqlStatement, new RowMapper<Course>() {
@Override
public Course mapRow(ResultSet rs, int rowNum) throws SQLException {
Course registerCourse = new Course();
registerCourse.setYear(rs.getInt("๋
๋"));
registerCourse.setSemester(rs.getInt("ํ๊ธฐ"));
registerCourse.setClassName(rs.getString("๊ต๊ณผ๋ชฉ๋ช
"));
registerCourse.setClassification(rs.getString("๊ต๊ณผ๊ตฌ๋ถ"));
registerCourse.setProfessor(rs.getString("๋ด๋น๊ต์"));
registerCourse.setCredits(rs.getInt("ํ์ "));
return registerCourse;
}
});
}
}
CourseService.java
์์๋ CourseDao.java
์์ ์กฐํํ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋๋ฅผ ์์ฑํด์ CourseController.java
์์ ์ด์ฉํ ์ ์๋๋ก ๋ง๋ค์ด์ค๋ค.
@Service
public class CourseService {
@Autowired
private CourseDao courseDao;
// ํ๋
/ํ๊ธฐ๋ณ ์ด์ ํ์ ์ ๋ณด ์กฐํ
public List<Course> getTakenSummary() {
return courseDao.getSummary();
}
// ์ด์ ์ด ํ์ ๊ณ์ฐ
public int getTotalTakenCredits() {
return courseDao.getTotalCredits();
}
// ํน์ ํ๊ธฐ์ ์๊ฐํ ๊ฐ์ ์ ๋ณด ์กฐํ
public List<Course> getSemesterCourses(int year, int semester) {
return courseDao.getSemesterCourses(year, semester);
}
// DB์ ๊ฐ์ ์ ๋ณด ์ฝ์
public void insert(Course course) {
courseDao.insert(course);
}
// ์๊ฐ์ ์ฒญ ๊ฐ์ ๋ด์ญ ์กฐํ
public List<Course> getRegisterCourses() {
return courseDao.getRegisterCourses();
}
}
์์ฒญ URL์ ๋งคํํ๋ CourseController๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํจ์ผ๋ก์จ mapping๋ URL ํ์ด์ง์์ DB์ ์ ์ฅ๋ ์ ๋ณด๋ฅผ ์กฐํํด์ ๊ฐ์ ธ์จ ์ ๋ณด๋ฅผ ๋ณ์์ ์ ์ฅํด์ ์ฌ์ฉํ ์ ์๋ค.
@Controller
public class CourseController {
@Autowired
private CourseService courseService;
@RequestMapping("/summary") // ํ๊ธฐ๋ณ ์ด์ ํ์ ์กฐํ ํ์ด์ง
public String showSummary(Model model) {
List<Course> summaries = courseService.getTakenSummary(); // ํ๊ธฐ๋ณ ์ทจ๋ ํ์
model.addAttribute("summaries", summaries);
int totalCredits = courseService.getTotalTakenCredits(); // ์ด ์ด์ ํ์
model.addAttribute("totalCredits", totalCredits);
return "summary";
}
// ํ๊ธฐ ์ ๋ณด๋ฅผ ๋ณ์๋ก ๋ฐ์ ํด๋น ํ๊ธฐ์ ์๊ฐ ๋ด์ญ ํ์ด์ง๋ก ๋งคํ
@RequestMapping("/details/{semesterInfo}")
public String showDetails(@PathVariable String semesterInfo, Model model) {
int year = Integer.parseInt(semesterInfo.split("-")[0]);
int semester = Integer.parseInt(semesterInfo.split("-")[1]);
List<Course> courses = courseService.getSemesterCourses(year, semester);
model.addAttribute("courses", courses);
return semesterInfo;
}
@RequestMapping("/register") // ์๊ฐ์ ์ฒญ ํ์ด์ง
public String registerCourse(Model model) {
model.addAttribute("course", new Course());
return "register";
}
// ์๊ฐ์ ์ฒญ ํ์ด์ง์์ ํผ ์ ์ก(submit) ์
@RequestMapping(value="/doRegister", produces="text/plain;charset=UTF-8")
public String doRegister(Model model, @Valid Course course, BindingResult result) {
if (result.hasErrors()) { // ์๊ฐ์ ์ฒญ ๋ด์ญ์ ์ค๋ฅ๊ฐ ์์ ๊ฒฝ์ฐ
System.out.println("== ์๊ฐ์ ์ฒญ ์ค๋ฅ ==");
List<ObjectError> errors = result.getAllErrors();
for (ObjectError error : errors) {
System.out.println(error.getDefaultMessage());
}
return "register"; // ๋ค์ ์๊ฐ์ ์ฒญ ํ์ด์ง์์ ์
๋ ฅ ๋ฐ์ ์ ์๋๋ก ํจ
}
courseService.insert(course); // ์ค๋ฅ๊ฐ ์๋ค๋ฉด DB์ ์ ์ฅํ๊ณ
return "successRegistration"; // ์๊ฐ์ ์ฒญ ์๋ฃ ํ์ด์ง๋ก ์ด๋
}
@RequestMapping("/viewRegistration") // ์๊ฐ์ ์ฒญ ๋ด์ญ ํ์ด์ง
public String viewRegistration(Model model) {
List<Course> courses = courseService.getRegisterCourses();
model.addAttribute("courses", courses);
return "viewRegistration";
}
}
ํ๊ธฐ ๋ณ ์ด์ ํ์ ์กฐํ(summary.jsp
) ๋ฉ๋ด๋ฅผ ๋ค์ด๊ฐ๋ฉด CourseController.java
์์ /summary
์ summaries์ totalCredits ๋ฅผ ์ฌ์ฉํ์ฌ ์ฐ๋, ํ๊ธฐ, ์ทจ๋ํ์ ๊ณผ ์ด๊ณ๋ฅผ ํ์ธํ ์ ์๋ค. ๋งํฌ์๋ ์ฐ๋์ ํ๊ธฐ ์ ๋ณด๋ฅผ ๋ฃ์ด ๊ฐ๊ฐ์ ๋ค๋ฅธ ํ์ด์ง๋ก ์ฐ๊ฒฐ๋๋๋ก ํ๋ค.
<table class="table" border="1">
...
<tfoot>
<tr><th>์ด๊ณ</th><th></th>
<th><c:out value="${ totalCredits }"></c:out></th><th></th></tr>
</tfoot>
<tbody>
<c:forEach var="summary" items="${ summaries }">
<tr>
<td><c:out value="${ summary.year }"></c:out></td>
<td><c:out value="${ summary.semester }"></c:out></td>
<td><c:out value="${ summary.credits }"></c:out></td>
<td><a href="${ pageContext.request.contextPath }/details/${ summary.year }-${summary.semester}">๋งํฌ</a></td>
</tr>
</c:forEach>
</tbody>
</table>
![](https://github.com/coding-Benny/web-framework/raw/master/myCourseMVC/images/summary.png)
ํ๊ธฐ ๋ณ ์ด์ ํ์ ์กฐํ ๋ฉ๋ด(summary.jsp
)์์ โ์์ธ๋ณด๊ธฐโ์ ๋งํฌ๋ฅผ ํด๋ฆญํ๋ฉด ๊ฐ ํ๊ธฐ ๋ณ ์๊ฐ ๋ด์ญ์ CourseController.java
์ /details/{semesterInfo}
(์: 2020๋
1ํ๊ธฐ๋ /details/2020-1
)๋ฅผ ํตํด ํด๋น ํ๊ธฐ course๋ค์ ๊ฐ์ ธ์ ์ถ๋ ฅํ๋ค.
<table class="table" border="1">
<tbody>
<c:forEach var="course" items="${ courses }">
<tr>
<td><c:out value="${ course.year }"></c:out></td>
<td><c:out value="${ course.semester }"></c:out></td>
<td class="className"><c:out value="${ course.className }"></c:out></td>
<td class="classifcation">
<c:out value="${ course.classification }"></c:out></td>
<td class="professor"><c:out value="${ course.professor }"></c:out></td>
<td><c:out value="${ course.credits }"></c:out></td>
</tr>
</c:forEach>
</tbody>
</table>
![](https://github.com/coding-Benny/web-framework/raw/master/myCourseMVC/images/detail-2020-1.png)
์๊ฐ ์ ์ฒญ ๋ฉ๋ด์์ ์น ํผ(form)์ ํตํด 2021๋
1ํ๊ธฐ์ ์ ์ฒญํ ๊ณผ๋ชฉ์ ์
๋ ฅํ๋ค. 2021๋
๊ณผ 1ํ๊ธฐ๋ผ๋ ์ ๋ณด๋ ์๊ฐ์ ์ฒญ ์ ์ฌ์ฉ์๊ฐ ์
๋ ฅํ ๋ฐ์ดํฐ๊ฐ ์๋๋ผ๊ณ ํ๋จํ์ฌ hidden์ผ๋ก ์ฒ๋ฆฌํด์ ์ ์กํ๋๋ก ํ์๋ค. ๋๋จธ์ง๋ ์ฌ์ฉ์๊ฐ ์
๋ ฅํ ๋ฐ์ดํฐ์ ๋ํ ๊ฒ์ฆ ์์
์ ํ๋๋ฐ ์ผ๋ถ ๋น์์ง ์นธ๋ค์ด ์๊ณ ํ์ ์ 1~3ํ์ ์ด ์ ํจํ ๊ฐ์ธ๋ฐ 0์ด ์
๋ ฅ๋์ด ์์ด ์ค๋ฅ๊ฐ ๋ฌ์ผ๋ฏ๋ก CourseController.java
์ /doRegister
์์ ๋ช
์ํ ๊ฒ์ฒ๋ผ ๋ค์ ์๊ฐ์ ์ฒญ ํ์ด์ง(register.jsp
)๋ก ๋์์ ์ฌ์ฉ์๊ฐ ์์์ ๋ง๊ฒ ํผ์ ์ฑ์ธ ์ ์๋๋ก ์ฌ ์์ฒญํ๊ณ ์๋ค.
<sf:form method="post" action="${ pageContext.request.contextPath }/doRegister"
modelAttribute="course" acceptCharset="UTF-8">
<table class="formtable">
<sf:input class="control" type="hidden" value="2021" path="year" />
<sf:input class="control" type="hidden" value="1" path="semester" />
<tr>
<td class="label">๊ต๊ณผ๋ชฉ๋ช
</td>
<td><sf:input class="control" type="text" path="className" /><br/>
<sf:errors path="className" class="error" /> </td>
</tr>
<tr>
<td class="label">๊ต๊ณผ๊ตฌ๋ถ</td>
<td><sf:input class="control" type="text" path="classification" /><br/>
<sf:errors path="classification" class="error" /></td>
</tr>
<tr>
<td class="label">๋ด๋น๊ต์</td>
<td><sf:input class="control" type="text" path="professor" /><br/>
<sf:errors path="professor" class="error" /></td>
</tr>
<tr>
<td class="label">ํ์ </td>
<td><sf:input class="control" type="text" path="credits" /><br/>
<sf:errors path="credits" class="error" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="์๊ฐ์ ์ฒญ" /></td>
</tr>
</table>
</sf:form>
๋ชจ๋ ํผ์ ์ ํจํ ๊ฐ์ผ๋ก ์ฑ์ ์ ๊ฒฝ์ฐ์๋ ์๊ฐ์ ์ฒญ์ด ์ ์์ ์ผ๋ก ์งํ๋์ด CourseController.java
์ /doRegister
์์ ๋ช
์ํ๋๋ก ์๊ฐ์ ์ฒญํ ๊ฐ์ข ์ ๋ณด๋ฅผ DB์ ์ ์ฅํ๊ณ ์๊ฐ์ ์ฒญ ์๋ฃ(successRegistration.jsp
) ํ์ด์ง๊ฐ ์ถ๋ ฅ๋๋ค.
![](https://github.com/coding-Benny/web-framework/raw/master/myCourseMVC/images/register.png)
![](https://github.com/coding-Benny/web-framework/raw/master/myCourseMVC/images/register-completed.png)
์๊ฐ์ ์ฒญ ์กฐํ(viewRegistration.jsp
) ๋ฉ๋ด์์๋ CourseController.java
์ /viewRegistration
์์ ์๊ฐ์ ์ฒญ ๊ฐ์ ์ ๋ณด๋ฅผ ์กฐํํ์ฌ 2021๋
1ํ๊ธฐ ์๊ฐ ์ ์ฒญ ๋ด์ญ์ ์ถ๋ ฅํ๋ค.
<c:forEach var="course" items="${ courses }">
<tr>
<td><c:out value="${ course.year }"></c:out></td>
<td><c:out value="${ course.semester }"></c:out></td>
<td class="className"><c:out value="${ course.className }"></c:out></td>
<td class="classifcation"><c:out value="${ course.classification }"></c:out></td>
<td class="professor"><c:out value="${ course.professor }"></c:out></td>
<td><c:out value="${ course.credits }"></c:out></td>
</tr>
</c:forEach>
![](https://github.com/coding-Benny/web-framework/raw/master/myCourseMVC/images/registration.png)