portaldacalheta.pt
  • Κύριος
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
Διεπαφή Ιστού

Δημιουργία σύγχρονων εφαρμογών Ιστού με AngularJS και Play Framework



Η επιλογή του σωστού εργαλείου για το σωστό σκοπό προχωρά πολύ, ειδικά όταν πρόκειται για τη δημιουργία σύγχρονων εφαρμογών ιστού. Πολλοί από εμάς είναι εξοικειωμένοι με το AngularJS και πόσο εύκολο καθιστά την ανάπτυξη ισχυρών διεπαφών εφαρμογών ιστού. Αν και πολλοί θα υποστηρίξουν τη χρήση αυτού του δημοφιλούς πλαισίου ιστού, σίγουρα έχει πολλά να προσφέρει και μπορεί να είναι μια κατάλληλη επιλογή για ένα ευρύ φάσμα αναγκών. Από την άλλη πλευρά, τα στοιχεία που χρησιμοποιείτε στο πίσω μέρος θα υπαγορεύσουν πολλά για την απόδοση της εφαρμογής ιστού, καθώς επηρεάζουν τη συνολική εμπειρία χρήστη. Παίζω είναι ένα διαδικτυακό πλαίσιο υψηλής ταχύτητας για Java και Scala. Βασίζεται σε μια ελαφριά, ανιθαγενή, φιλική προς το web αρχιτεκτονική και ακολουθεί μοτίβα και αρχές MVC παρόμοια με τα Rails και Django.

διαδικτυακές εφαρμογές με γωνιακό και παιχνίδι πλαίσιο



Σε αυτό το άρθρο, θα ρίξουμε μια ματιά στον τρόπο με τον οποίο μπορούμε να χρησιμοποιήσουμε το AngularJS και το Play για να δημιουργήσουμε μια απλή εφαρμογή ιστολογίου με έναν βασικό μηχανισμό ελέγχου ταυτότητας και τη δυνατότητα υποβολής αναρτήσεων και σχολίων. Ανάπτυξη AngularJS , με μερικά Bootstrap Twitter καλούδια, θα μας επιτρέψουν να ενισχύσουμε μια εμπειρία εφαρμογής μιας σελίδας πάνω από ένα REST API βασισμένο στο Play.



Εφαρμογές Ιστού - Ξεκινώντας

Σκελετός εφαρμογής AngularJS

Οι εφαρμογές AngularJS και Play θα βρίσκονται σε καταλόγους πελατών και διακομιστών. Προς το παρόν, θα δημιουργήσουμε τον κατάλογο «πελάτης».



mkdir -p blogapp/client

Για να δημιουργήσουμε ένα σκελετό εφαρμογής AngularJS, θα χρησιμοποιήσουμε το Yeoman - ένα καταπληκτικό εργαλείο σκαλωσιάς. Η εγκατάσταση του Yeoman είναι εύκολη . Η χρήση του για ικρίωμα μιας απλής σκελετικής εφαρμογής AngularJS είναι πιθανώς ακόμη πιο εύκολη:

cd blogapp/client yo angular

Η εκτέλεση της δεύτερης εντολής θα ακολουθηθεί από μερικές επιλογές που πρέπει να διαλέξετε. Για αυτό το έργο, δεν χρειαζόμαστε το 'Sass (με πυξίδα)'. Χρειαζόμαστε το Boostrap μαζί με τις ακόλουθες προσθήκες AngularJS:



  • angular-animate.js
  • angular-cookies.js
  • angular-resource.js
  • angular-route.js
  • angular-sanitize.js
  • angular-touch.js

Σε αυτό το σημείο, μόλις ολοκληρώσετε τις επιλογές σας, θα αρχίσετε να βλέπετε έξοδο NPM και Bower στο τερματικό σας. Όταν ολοκληρωθούν οι λήψεις και έχουν εγκατασταθεί τα πακέτα, θα έχετε ένα σκελετό εφαρμογής AngularJS έτοιμο για χρήση.

Παίξτε Skeleton Application Framework

Ο επίσημος τρόπος δημιουργίας μιας νέας εφαρμογής Play περιλαμβάνει τη χρήση του εργαλείου Typesafe Activator. Προτού μπορέσετε να το χρησιμοποιήσετε, πρέπει να το κατεβάσετε και να το εγκαταστήσετε στον υπολογιστή σας. Εάν χρησιμοποιείτε Mac OS και χρησιμοποιείτε το Homebrew, μπορείτε να εγκαταστήσετε αυτό το εργαλείο με μία μόνο γραμμή εντολών:



brew install typesafe-activator

Η δημιουργία μιας εφαρμογής Play από τη γραμμή εντολών είναι εξαιρετικά εύκολη:

cd blogapp/ activator new server play-java cd server/

Εισαγωγή σε IDE

Για να εισαγάγετε την εφαρμογή σε IDE όπως το Eclipse ή το IntelliJ, πρέπει να «εκλείψετε» ή να «εξιδανικεύσετε» την εφαρμογή σας. Για να το κάνετε αυτό, εκτελέστε την ακόλουθη εντολή:



activator

Μόλις δείτε μια νέα προτροπή, πληκτρολογήστε είτε «έκλειψη» είτε «ιδέα» και πατήστε enter για να προετοιμάσετε τον κωδικό εφαρμογής για το Eclipse ή το IntelliJ, αντίστοιχα.

Για συντομία, θα καλύψουμε μόνο τη διαδικασία εισαγωγής του έργου στο IntelliJ σε αυτό το άρθρο. Η διαδικασία εισαγωγής του στο Eclipse πρέπει να είναι εξίσου απλή. Για να εισαγάγετε το έργο στο IntelliJ, ξεκινήστε ενεργοποιώντας την επιλογή 'Έργο από υπάρχουσες πηγές ...' που βρίσκεται στην ενότητα 'Αρχείο -> Νέο'. Στη συνέχεια, επιλέξτε το αρχείο build.sbt και κάντε κλικ στο 'OK'. Κάνοντας κλικ στο 'OK' ξανά στο επόμενο παράθυρο διαλόγου, το IntelliJ θα πρέπει να αρχίσει να εισάγει την εφαρμογή Play ως έργο SBT.



Το Typesafe Activator διαθέτει επίσης ένα γραφικό περιβάλλον εργασίας χρήστη, στο οποίο μπορείτε να χρησιμοποιήσετε δημιουργήστε αυτόν τον κωδικό εφαρμογής σκελετού .

Τώρα που έχουμε εισαγάγει την εφαρμογή Play στο IntelliJ, θα πρέπει επίσης να εισαγάγουμε την εφαρμογή AngularJS στον χώρο εργασίας. Μπορούμε να το εισαγάγουμε είτε ως ξεχωριστό έργο είτε ως ενότητα στο υπάρχον έργο όπου βρίσκεται η εφαρμογή Play.



Εδώ, θα εισαγάγουμε την εφαρμογή Angular ως ενότητα. Κάτω από το μενού 'Αρχείο', θα επιλέξουμε την επιλογή 'Νέο -> Ενότητα από υπάρχουσες πηγές ...'. Από το παράθυρο διαλόγου, θα επιλέξουμε τον κατάλογο «πελάτης» και θα κάνουμε κλικ στο «OK». Στις επόμενες δύο οθόνες, κάντε κλικ στο 'Επόμενο' και 'Τέλος', αντίστοιχα.

Τοπικοί διακομιστές αναπαραγωγής

Σε αυτό το σημείο, θα πρέπει να είναι δυνατή η εκκίνηση της εφαρμογής AngularJS ως εργασία Grunt από το IDE. Αναπτύξτε το φάκελο του πελάτη σας και κάντε δεξί κλικ στο Gruntfile.js. Στο αναδυόμενο μενού επιλέξτε 'Show Grunt Tasks'. Θα εμφανιστεί ένας πίνακας με την ένδειξη 'Grunt' με μια λίστα εργασιών:

Τοπικοί διακομιστές αναπαραγωγής

Για να ξεκινήσετε την προβολή της εφαρμογής, κάντε διπλό κλικ στο 'serve'. Αυτό θα ανοίξει αμέσως το προεπιλεγμένο πρόγραμμα περιήγησης ιστού και θα το δείξει σε μια διεύθυνση localhost. Θα πρέπει να δείτε μια γωνιακή σελίδα AngularJS με το λογότυπο του Yeoman.

Στη συνέχεια, πρέπει να ξεκινήσουμε τον διακομιστή εφαρμογών back-end. Προτού προχωρήσουμε, πρέπει να αντιμετωπίσουμε μερικά ζητήματα:

  1. Από προεπιλογή, τόσο η εφαρμογή AngularJS (bootstrapped by Yeoman) όσο και η εφαρμογή Play προσπαθούν να εκτελεστούν στη θύρα 9000.
  2. Κατά την παραγωγή, και οι δύο εφαρμογές πιθανότατα θα εκτελούνται σε έναν τομέα και πιθανότατα θα χρησιμοποιήσουμε το Nginx για τη δρομολόγηση των αιτημάτων ανάλογα. Αλλά σε κατάσταση ανάπτυξης, όταν αλλάζουμε τον αριθμό θύρας μιας από αυτές τις εφαρμογές, τα προγράμματα περιήγησης στο Web θα τα αντιμετωπίζουν σαν να εκτελούνται σε διαφορετικούς τομείς.

Για να επιλύσουμε και τα δύο αυτά ζητήματα, το μόνο που χρειάζεται να κάνουμε είναι να χρησιμοποιήσουμε έναν διακομιστή μεσολάβησης Grunt έτσι ώστε να πληρούνται όλα τα αιτήματα AJAX στην εφαρμογή Play. Με αυτό, ουσιαστικά και οι δύο αυτοί διακομιστές εφαρμογών θα είναι διαθέσιμοι στον ίδιο εμφανή αριθμό θύρας.

m&a κερδίζουν δομές

Ας αλλάξουμε πρώτα τον αριθμό θύρας του διακομιστή εφαρμογών Play σε 9090. Για να το κάνετε αυτό, ανοίξτε το παράθυρο 'Εκτέλεση / εντοπισμός σφαλμάτων' κάνοντας κλικ στο 'Εκτέλεση -> Επεξεργασία διαμορφώσεων'. Στη συνέχεια, αλλάξτε τον αριθμό θύρας στο πεδίο 'Url To Open'. Κάντε κλικ στο 'OK' για να εγκρίνετε αυτήν την αλλαγή και να κλείσετε το παράθυρο. Κάνοντας κλικ στο κουμπί 'Εκτέλεση' θα ξεκινήσει η διαδικασία επίλυσης εξάρτησης - θα αρχίσουν να εμφανίζονται αρχεία καταγραφής αυτής της διαδικασίας.

Τοπικοί διακομιστές αναπαραγωγής

Μόλις ολοκληρωθεί, μπορείτε να πλοηγηθείτε στο http: // localhost: 9090 στο πρόγραμμα περιήγησής σας και σε λίγα δευτερόλεπτα θα πρέπει να μπορείτε να δείτε την εφαρμογή Play. Για να διαμορφώσετε έναν διακομιστή μεσολάβησης Grunt, πρέπει πρώτα να εγκαταστήσουμε ένα μικρό πακέτο Node.js χρησιμοποιώντας NPM:

cd blogapp/client npm install grunt-connect-proxy --save-dev

Στη συνέχεια πρέπει να τροποποιήσουμε το Gruntfile.js. Σε αυτό το αρχείο, εντοπίστε την εργασία 'σύνδεση' και εισαγάγετε το κλειδί / τιμή 'διακομιστές μεσολάβησης' μετά από αυτό:

τι είδη llc υπάρχουν
proxies: [ { context: '/app', // the context of the data service host: 'localhost', // wherever the data service is running port: 9090, // the port that the data service is running on changeOrigin: true } ],

Το Grunt θα κάνει μεσολάβηση όλων των αιτημάτων στο '/ app / *' στην εφαρμογή Play back-end. Αυτό θα μας σώσει από το να πρέπει να προσθέτουμε λίστα επιτρεπόμενων σε κάθε κλήση στο back-end. Επιπλέον, πρέπει επίσης να τροποποιήσουμε τη συμπεριφορά μας στο φορτίο του ήπατος:

livereload: { options: { open: true, middleware: function (connect) { var middlewares = []; // Setup the proxy middlewares.push(require('grunt-connect-proxy/lib/utils').proxyRequest); // Serve static files middlewares.push(connect.static('.tmp')); middlewares.push(connect().use( '/bower_components', connect.static('./bower_components') )); middlewares.push(connect().use( '/app/styles', connect.static('./app/styles') )); middlewares.push(connect.static(appConfig.app)); return middlewares; } } },

Τέλος, πρέπει να προσθέσουμε μια νέα εξάρτηση '' configigureProxies: server 'στην εργασία' serve ':

grunt.registerTask('serve', 'Compile then start a connect web server', function (target) { if (target === 'dist') { return grunt.task.run(['build', 'connect:dist:keepalive']); } grunt.task.run([ 'clean:server', 'wiredep', 'concurrent:server', 'autoprefixer:server', 'configureProxies:server', 'connect:livereload', 'watch' ]); });

Κατά την επανεκκίνηση του Grunt, θα πρέπει να παρατηρήσετε τις ακόλουθες γραμμές στα αρχεία καταγραφής που δείχνουν ότι ο διακομιστής μεσολάβησης εκτελείται:

Running 'autoprefixer:server' (autoprefixer) task File .tmp/styles/main.css created. Running 'configureProxies:server' (configureProxies) task Running 'connect:livereload' (connect) task Started connect web server on http://localhost:9000

Δημιουργία Φόρμας Εγγραφής

Θα ξεκινήσουμε δημιουργώντας μια φόρμα εγγραφής για την εφαρμογή ιστολογίου μας. Αυτό θα μας επιτρέψει επίσης να επαληθεύσουμε ότι όλα λειτουργούν όπως πρέπει. Μπορούμε να χρησιμοποιήσουμε το Yeoman για να δημιουργήσουμε έναν ελεγκτή εγγραφής και προβολή στο AngularJS:

yo angular:controller signup yo angular:view signup

Στη συνέχεια θα πρέπει να ενημερώσουμε τη δρομολόγηση της εφαρμογής μας για να αναφέρουμε αυτήν την πρόσφατα δημιουργημένη προβολή και να καταργήσουμε τον περιττό ελεγκτή και την προβολή 'σχετικά' που δημιουργήθηκε αυτόματα. Από το αρχείο 'app / scripts / app.js', καταργήστε τις αναφορές στα 'app / scripts / Controllers / about.js' και 'app / views / about.html', αφήνοντάς τα με:

.config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }) .when('/signup', { templateUrl: 'views/signup.html', controller: 'SignupCtrl' }) .otherwise({ redirectTo: '/' });

Ομοίως, ενημερώστε το αρχείο 'app / index.html' για να καταργήσετε τους περιττούς συνδέσμους και προσθέστε έναν σύνδεσμο στη σελίδα εγγραφής:

  • Home
  • Signup

Επίσης, καταργήστε την ετικέτα σεναρίου για το 'about.js':

Email Password Sign up!

Στη συνέχεια, προσθέστε μια φόρμα στο αρχείο 'signup.html':

angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log) { $scope.signup = function() { var payload = { email : $scope.email, password : $scope.password }; $http.post('app/signup', payload) .success(function(data) { $log.debug(data); }); }; });

Πρέπει να επεξεργαστούμε τη φόρμα από τον ελεγκτή Angular. Αξίζει να σημειωθεί ότι δεν χρειάζεται να προσθέσουμε συγκεκριμένα το χαρακτηριστικό 'ng-controller' στις προβολές μας, καθώς η λογική δρομολόγησης στο 'app.js' ενεργοποιεί αυτόματα έναν ελεγκτή πριν φορτωθεί η προβολή μας. Το μόνο που πρέπει να κάνουμε για να συμπληρώσουμε αυτήν τη φόρμα είναι να έχουμε μια σωστή συνάρτηση 'εγγραφής' που ορίζεται στο πεδίο $. Αυτό πρέπει να γίνει στο αρχείο 'signup.js':

public static Result signup() { return ok('Success!'); }

Ας ανοίξουμε τώρα την κονσόλα προγραμματιστή Chrome, μεταβείτε στην καρτέλα 'Δίκτυο' και προσπαθήστε να υποβάλετε τη φόρμα εγγραφής.

Παράδειγμα γωνιακής εγγραφής Play

Θα δούμε ότι το back-end του Play απαντά φυσικά με μια σελίδα σφάλματος 'Η ενέργεια δεν βρέθηκε'. Αυτό αναμένεται καθώς δεν έχει εφαρμοστεί ακόμη. Αλλά αυτό σημαίνει επίσης ότι η ρύθμιση διακομιστή μεσολάβησης Grunt λειτουργεί σωστά!

Στη συνέχεια, θα προσθέσουμε μια 'Ενέργεια' που ουσιαστικά είναι μια μέθοδος στον ελεγκτή εφαρμογών Play. Στην κατηγορία 'Εφαρμογή' στο πακέτο 'app / Controllers', προσθέστε μια νέα μέθοδο 'εγγραφή':

POST /app/signup controllers.Application.signup

Τώρα ανοίξτε το αρχείο 'conf / route' και προσθέστε την ακόλουθη γραμμή:

db.default.driver=org.h2.Driver db.default.url='jdbc:h2:mem:play' db.default.user=sa db.default.password='' ... ebean.default='models.*'

Τέλος, επιστρέφουμε στο πρόγραμμα περιήγησης ιστού μας, http: // localhost: 9000 / # / εγγραφή. Κάνοντας κλικ στο κουμπί 'Υποβολή' αυτή τη φορά θα έχετε κάτι διαφορετικό:

Παράδειγμα γωνιακής εγγραφής Play στο πρόγραμμα περιήγησης

Θα πρέπει να βλέπετε την τιμή του κωδικού που επιστρέφεται, αυτή που γράψαμε στη μέθοδο εγγραφής. Σε αυτήν την περίπτωση, είμαστε έτοιμοι να προχωρήσουμε καθώς το περιβάλλον ανάπτυξης μας είναι έτοιμο και λειτουργεί τόσο για τις εφαρμογές Angular όσο και για Play.

Ορισμός μοντέλων Ebean στο Play

Πριν ορίσουμε μοντέλα, ας επιλέξουμε πρώτα ένα κατάστημα δεδομένων. Σε αυτό το άρθρο, θα χρησιμοποιήσουμε τη βάση δεδομένων H2 στη μνήμη. Για να το ενεργοποιήσετε, βρείτε και αποσυνδέστε τις ακόλουθες γραμμές στο αρχείο 'application.conf':

applyEvolutions.default=true

Και προσθέστε την ακόλουθη γραμμή:

// User.java @Entity public class User extends Model { @Id public Long id; @Column(length = 255, unique = true, nullable = false) @Constraints.MaxLength(255) @Constraints.Required @Constraints.Email public String email; @Column(length = 64, nullable = false) private byte[] shaPassword; @OneToMany(cascade = CascadeType.ALL) @JsonIgnore public List posts; public void setPassword(String password) { this.shaPassword = getSha512(password); } public void setEmail(String email) { this.email = email.toLowerCase(); } public static final Finder find = new Finder( Long.class, User.class); public static User findByEmailAndPassword(String email, String password) { return find .where() .eq('email', email.toLowerCase()) .eq('shaPassword', getSha512(password)) .findUnique(); } public static User findByEmail(String email) { return find .where() .eq('email', email.toLowerCase()) .findUnique(); } public static byte[] getSha512(String value) { try { return MessageDigest.getInstance('SHA-512').digest(value.getBytes('UTF-8')); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } }

Το μοντέλο τομέα ιστολογίου μας είναι μάλλον απλό. Πρώτα απ 'όλα, έχουμε χρήστες που μπορούν να δημιουργήσουν αναρτήσεις και έπειτα κάθε ανάρτηση μπορεί να σχολιάζεται από οποιονδήποτε συνδεδεμένο χρήστη. Ας δημιουργήσουμε τα μοντέλα Ebean.

Χρήστης

// BlogPost.java @Entity public class BlogPost extends Model { @Id public Long id; @Column(length = 255, nullable = false) @Constraints.MaxLength(255) @Constraints.Required public String subject; @Column(columnDefinition = 'TEXT') @Constraints.Required public String content; @ManyToOne public User user; public Long commentCount; @OneToMany(cascade = CascadeType.ALL) public List comments; public static final Finder find = new Finder( Long.class, BlogPost.class); public static List findBlogPostsByUser(final User user) { return find .where() .eq('user', user) .findList(); } public static BlogPost findBlogPostById(final Long id) { return find .where() .eq('id', id) .findUnique(); } }

Ανάρτηση

// PostComment.java @Entity public class PostComment extends Model { @Id public Long id; @ManyToOne @JsonIgnore public BlogPost blogPost; @ManyToOne public User user; @Column(columnDefinition = 'TEXT') public String content; public static final Finder find = new Finder( Long.class, PostComment.class); public static List findAllCommentsByPost(final BlogPost blogPost) { return find .where() .eq('post', blogPost) .findList(); } public static List findAllCommentsByUser(final User user) { return find .where() .eq('user', user) .findList(); } }

Αναρτήστε Σχόλιο

// Application.java public static Result signup() { Form signUpForm = Form.form(SignUp.class).bindFromRequest(); if ( signUpForm.hasErrors()) { return badRequest(signUpForm.errorsAsJson()); } SignUp newUser = signUpForm.get(); User existingUser = User.findByEmail(newUser.email); if(existingUser != null) { return badRequest(buildJsonResponse('error', 'User exists')); } else { User user = new User(); user.setEmail(newUser.email); user.setPassword(newUser.password); user.save(); session().clear(); session('username', newUser.email); return ok(buildJsonResponse('success', 'User created successfully')); } } public static class UserForm { @Constraints.Required @Constraints.Email public String email; } public static class SignUp extends UserForm { @Constraints.Required @Constraints.MinLength(6) public String password; } private static ObjectNode buildJsonResponse(String type, String message) { ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', message); wrapper.put(type, msg); return wrapper; }

Πραγματική ενέργεια εγγραφής

Τώρα ας δημιουργήσουμε την πρώτη μας πραγματική ενέργεια, επιτρέποντας στους χρήστες να εγγραφούν:

yo angular:service alerts

Λάβετε υπόψη ότι ο έλεγχος ταυτότητας που χρησιμοποιείται σε αυτήν την εφαρμογή είναι πολύ βασικός και δεν συνιστάται για χρήση στην παραγωγή.

Το ενδιαφέρον είναι ότι χρησιμοποιούμε φόρμες Play για να χειριστούμε φόρμες εγγραφής. Έχουμε ορισμένους περιορισμούς στην τάξη φόρμας SignUp. Η επικύρωση θα γίνει για εμάς αυτόματα χωρίς να απαιτείται ρητή λογική επικύρωσης.

Εάν επιστρέψουμε στην εφαρμογή AngularJS στο πρόγραμμα περιήγησης ιστού και κάνουμε ξανά κλικ στο 'Υποβολή', θα δούμε ότι ο διακομιστής αποκρίνεται τώρα με ένα κατάλληλο σφάλμα - ότι αυτά τα πεδία είναι απαραίτητα.

Υποβολή φόρμας παιχνιδιού

Αντιμετώπιση σφαλμάτων διακομιστή στο AngularJS

Λάβαμε λοιπόν ένα σφάλμα από τον διακομιστή, αλλά ο χρήστης της εφαρμογής δεν έχει ιδέα τι συμβαίνει. Το λιγότερο που μπορούμε να κάνουμε είναι να εμφανίσουμε το σφάλμα στον χρήστη μας. Στην ιδανική περίπτωση, θα πρέπει να κατανοήσουμε τι είδους λάθη λαμβάνουμε και να εμφανίσουμε ένα φιλικό προς το χρήστη μήνυμα. Ας δημιουργήσουμε μια απλή υπηρεσία ειδοποίησης που θα μας βοηθήσει να εμφανίσουμε το σφάλμα.

Πρώτον, πρέπει να δημιουργήσουμε ένα πρότυπο υπηρεσίας με το Yeoman:

angular.module('clientApp') .factory('alertService', function($timeout) { var ALERT_TIMEOUT = 5000; function add(type, msg, timeout) { if (timeout) { $timeout(function(){ closeAlert(this); }, timeout); } else { $timeout(function(){ closeAlert(this); }, ALERT_TIMEOUT); } return alerts.push({ type: type, msg: msg, close: function() { return closeAlert(this); } }); } function closeAlert(alert) { return closeAlertIdx(alerts.indexOf(alert)); } function closeAlertIdx(index) { return alerts.splice(index, 1); } function clear(){ alerts = []; } function get() { return alerts; } var service = { add: add, closeAlert: closeAlert, closeAlertIdx: closeAlertIdx, clear: clear, get: get }, alerts = []; return service; } );

Στη συνέχεια, προσθέστε αυτόν τον κωδικό στο 'alerts.js':

yo angular:controller alerts

Τώρα, ας δημιουργήσουμε έναν ξεχωριστό ελεγκτή υπεύθυνο για ειδοποιήσεις:

angular.module('clientApp') .controller('AlertsCtrl', function ($scope, alertService) { $scope.alerts = alertService.get(); }); bower install angular-bootstrap --save

Τώρα πρέπει πραγματικά να δείξουμε ωραία μηνύματα σφάλματος Bootstrap. Ο ευκολότερος τρόπος είναι να το χρησιμοποιήσετε Γωνιακό περιβάλλον χρήστη . Μπορούμε να χρησιμοποιήσουμε το Bower για να το εγκαταστήσουμε:

angular .module('clientApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.bootstrap' ])

Στην ενότητα 'app.js', προσθέστε τη γωνιακή ενότητα διεπαφής χρήστη:

{{ alert.msg }}

Ας προσθέσουμε την οδηγία ειδοποίησης στο αρχείο 'index.html':

angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log, alertService, $location, userService) { $scope.signup = function() { var payload = { email : $scope.email, password : $scope.password }; $http.post('app/signup', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'email' || key === 'password') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } if(status === 500) { alertService.add('danger', 'Internal server error!'); } }) }; });

Τέλος, πρέπει να ενημερώσουμε τον ελεγκτή SignUp:

πώς δημιουργείτε μια γλώσσα προγραμματισμού
yo angular:view dashboard yo angular:controller dashboard

Τώρα, αν στείλουμε ξανά την κενή φόρμα, θα εμφανιστούν σφάλματα πάνω από τη φόρμα:

Σφάλματα γωνιακής αναπαραγωγής

Τώρα που αντιμετωπίζονται τα σφάλματα, πρέπει να κάνουμε κάτι όταν η εγγραφή χρήστη είναι επιτυχής. Μπορούμε να ανακατευθύνουμε τον χρήστη σε μια σελίδα πίνακα ελέγχου όπου μπορεί να προσθέσει αναρτήσεις. Αλλά πρώτα, πρέπει να το δημιουργήσουμε:

angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log, alertService, $location) { // .. .success(function(data) { if(data.hasOwnProperty('success')) { $location.path('/dashboard'); } });

Τροποποιήστε τη μέθοδο εγγραφής ελεγκτή 'signup.js' έτσι ώστε με επιτυχία να ανακατευθύνει τον χρήστη:

.when('/dashboard', { templateUrl: 'views/dashboard.html', controller: 'DashboardCtrl' })

Προσθέστε μια νέα διαδρομή στο 'apps.js':

yo angular:service user

Πρέπει επίσης να παρακολουθήσουμε εάν ο χρήστης είναι συνδεδεμένος. Ας δημιουργήσουμε μια ξεχωριστή υπηρεσία για αυτό:

// user.js angular.module('clientApp') .factory('userService', function() { var username = ''; return { username : username }; }); .success(function(data) { if(data.hasOwnProperty('success')) { userService.username = $scope.email; $location.path('/dashboard');; } });

Επίσης, τροποποιήστε τον ελεγκτή εγγραφής για να ορίσετε τον χρήστη σε αυτόν που μόλις εγγράφηκε:

Είμαι το μέγεθος της αγοράς
public static Result login() { Form loginForm = Form.form(Login.class).bindFromRequest(); if (loginForm.hasErrors()) { return badRequest(loginForm.errorsAsJson()); } Login loggingInUser = loginForm.get(); User user = User.findByEmailAndPassword(loggingInUser.email, loggingInUser.password); if(user == null) { return badRequest(buildJsonResponse('error', 'Incorrect email or password')); } else { session().clear(); session('username', loggingInUser.email); ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', 'Logged in successfully'); msg.put('user', loggingInUser.email); wrapper.put('success', msg); return ok(wrapper); } } public static Result logout() { session().clear(); return ok(buildJsonResponse('success', 'Logged out successfully')); } public static Result isAuthenticated() { if(session().get('username') == null) { return unauthorized(); } else { ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', 'User is logged in already'); msg.put('user', session().get('username')); wrapper.put('success', msg); return ok(wrapper); } } public static class Login extends UserForm { @Constraints.Required public String password; }

Πριν προσθέσουμε την κύρια λειτουργικότητα της προσθήκης αναρτήσεων, ας φροντίσουμε μερικές άλλες σημαντικές λειτουργίες, όπως δυνατότητα σύνδεσης και αποσύνδεσης, εμφάνιση πληροφοριών χρήστη στον πίνακα ελέγχου και επίσης προσθήκη υποστήριξης ελέγχου ταυτότητας στο παρασκήνιο.

Βασικός έλεγχος ταυτότητας

Ας περάσουμε στην εφαρμογή Play και εφαρμόστε τις ενέργειες σύνδεσης και αποσύνδεσης. Προσθέστε αυτές τις γραμμές στο 'Application.java':

public class Secured extends Security.Authenticator { @Override public String getUsername(Context ctx) { return ctx.session().get('username'); } @Override public Result onUnauthorized(Context ctx) { return unauthorized(); } }

Στη συνέχεια ας προσθέσουμε τη δυνατότητα να επιτρέπονται συγκεκριμένες κλήσεις back-end μόνο σε πιστοποιημένους χρήστες. Δημιουργήστε το 'Secured.java' με τον ακόλουθο κώδικα:

yo angular:controller menu

Θα χρησιμοποιήσουμε αυτήν την τάξη αργότερα για την προστασία νέων ενεργειών. Στη συνέχεια, πρέπει να τροποποιήσουμε το κύριο μενού της εφαρμογής AngularJS, έτσι ώστε να εμφανίζει τους συνδέσμους ονόματος χρήστη και αποσύνδεσης. Για αυτό, πρέπει να δημιουργήσουμε ελεγκτή:

// menu.js angular.module('clientApp') .controller('MenuCtrl', function ($scope, $http, userService, $location) { $scope.user = userService; $scope.logout = function() { $http.get('/app/logout') .success(function(data) { if(data.hasOwnProperty('success')) { userService.username = ''; $location.path('/login'); } }); }; $scope.$watch('user.username', function (newVal) { if(newVal === '') { $scope.isLoggedIn = false; } else { $scope.username = newVal; $scope.isLoggedIn = true; } }); }); yo angular:controller login yo angular:view login

Χρειαζόμαστε επίσης μια προβολή και έναν ελεγκτή για τη σελίδα σύνδεσης:

Email Password Log in // login.js angular.module('clientApp') .controller('LoginCtrl', function ($scope, userService, $location, $log, $http, alertService) { $scope.isAuthenticated = function() { if(userService.username) { $log.debug(userService.username); $location.path('/dashboard'); } else { $http.get('/app/isauthenticated') .error(function() { $location.path('/login'); }) .success(function(data) { if(data.hasOwnProperty('success')) { userService.username = data.success.user; $location.path('/dashboard'); } }); } }; $scope.isAuthenticated(); $scope.login = function() { var payload = { email : this.email, password : this.password }; $http.post('/app/login', payload) .error(function(data, status){ if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'email' || key === 'password') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { alertService.add('danger', 'Invalid login or password!'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data){ $log.debug(data); if(data.hasOwnProperty('success')) { userService.username = data.success.user; $location.path('/dashboard'); } }); }; });
  • Sign up!
  • Login
{{ username }} Toggle Dropdown
  • Dashboard
  • Logout

Στη συνέχεια τροποποιούμε το μενού έτσι ώστε να μπορεί να εμφανίζει δεδομένα χρήστη:

yo angular:view addpost

Τώρα εάν συνδεθείτε στην εφαρμογή, θα πρέπει να μπορείτε να δείτε την ακόλουθη οθόνη:

Παίξτε στιγμιότυπο οθόνης

Προσθήκη δημοσιεύσεων

Τώρα που έχουμε στη διάθεσή μας βασικούς μηχανισμούς εγγραφής και ελέγχου ταυτότητας, μπορούμε να εφαρμόσουμε τη λειτουργία δημοσίευσης. Ας προσθέσουμε μια νέα προβολή και ελεγκτή για την προσθήκη αναρτήσεων.

Subject Post Submit post yo angular:controller addpost // addpost.js angular.module('clientApp') .controller('AddpostCtrl', function ($scope, $http, alertService, $location) { $scope.post = function() { var payload = { subject : $scope.subject, content: $scope.content }; $http.post('/app/post', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'subject' || key === 'content') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { $location.path('/login'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data) { $scope.subject = ''; $scope.content = ''; alertService.add('success', data.success.message); }); }; }); .when('/addpost', { templateUrl: 'views/addpost.html', controller: 'AddpostCtrl' })

Στη συνέχεια, ενημερώνουμε το 'app.js' για να συμπεριλάβουμε:

  • Dashboard
  • Add post
  • Logout

Στη συνέχεια, τροποποιούμε το 'index.html' για να προσθέσουμε έναν σύνδεσμο για την προβολή 'addpost' στο μενού του πίνακα ελέγχου:

// Post.java public class Post extends Controller { public static Result addPost() { Form postForm = Form.form(PostForm.class).bindFromRequest(); if (postForm.hasErrors()) { return badRequest(postForm.errorsAsJson()); } else { BlogPost newBlogPost = new BlogPost(); newBlogPost.commentCount = 0L; newBlogPost.subject = postForm.get().subject; newBlogPost.content = postForm.get().content; newBlogPost.user = getUser(); newBlogPost.save(); } return ok(Application.buildJsonResponse('success', 'Post added successfully')); } private static User getUser() { return User.findByEmail(session().get('username')); } public static class PostForm { @Constraints.Required @Constraints.MaxLength(255) public String subject; @Constraints.Required public String content; } }

Τώρα από την πλευρά της εφαρμογής Play, ας δημιουργήσουμε έναν νέο ελεγκτή Post με τη μέθοδο addPost:

POST /app/post controllers.Post.addPost

Προσθέστε μια νέα καταχώρηση στο αρχείο διαδρομών για να μπορείτε να χειριστείτε τις νέες μεθόδους που έχετε προσθέσει στη δρομολόγηση:

// Application.java public static Result getPosts() { return ok(Json.toJson(BlogPost.find.findList())); }

Σε αυτό το σημείο, θα πρέπει να μπορείτε να προσθέσετε νέες δημοσιεύσεις.

Προσθήκη νέων δημοσιεύσεων στο Play

Εμφάνιση δημοσιεύσεων

Η προσθήκη αναρτήσεων έχει μικρή αξία, αν δεν μπορούμε να τις εμφανίσουμε. Αυτό που θέλουμε να κάνουμε είναι να απαριθμήσουμε όλες τις δημοσιεύσεις στην κύρια σελίδα. Ξεκινάμε προσθέτοντας μια νέα μέθοδο στον ελεγκτή εφαρμογών μας:

GET /app/posts controllers.Application.getPosts

Και την εγγραφή στο αρχείο διαδρομών:

// main.js angular.module('clientApp') .controller('MainCtrl', function ($scope, $http) { $scope.getPosts = function() { $http.get('app/posts') .success(function(data) { $scope.posts = data; }); }; $scope.getPosts(); });

Στη συνέχεια, στην εφαρμογή AngularJS τροποποιούμε τον κύριο ελεγκτή μας:

{{ post.subject }}

{{ post.content }}

Post by: {{ post.user.email }} | Comments {{ post.commentCount }}

Τέλος, καταργήστε τα πάντα από το 'main.html' και προσθέστε το:

yo angular:controller viewpost yo angular:view viewpost

Τώρα, εάν φορτώσετε την αρχική σελίδα της εφαρμογής σας, θα πρέπει να βλέπετε κάτι παρόμοιο με αυτό:

Φορτώθηκε το παράδειγμα του Angularjs Play

Πιθανότατα θα πρέπει επίσης να έχουμε μια ξεχωριστή προβολή για μεμονωμένες δημοσιεύσεις.

// viewpost.js angular.module('clientApp') .controller('ViewpostCtrl', function ($scope, $http, alertService, userService, $location) { $scope.user = userService; $scope.params = $routeParams; $scope.postId = $scope.params.postId; $scope.viewPost = function() { $http.get('/app/post/' + $scope.postId) .error(function(data) { alertService.add('danger', data.error.message); }) .success(function(data) { $scope.post = data; }); }; $scope.viewPost(); });

{{ post.subject }}

{{ post.content }}

Post by: {{ post.user.email }} | Comments {{ post.commentCount }}
app.js: .when('/viewpost/:postId', { templateUrl: 'views/viewpost.html', controller: 'ViewpostCtrl' })

Και η διαδρομή AngularJS:

eclipse vs notepad++
// Application.java public static Result getPost(Long id) { BlogPost blogPost = BlogPost.findBlogPostById(id); if(blogPost == null) { return notFound(buildJsonResponse('error', 'Post not found')); } return ok(Json.toJson(blogPost)); }

Όπως και πριν, προσθέτουμε μια νέα μέθοδο στον ελεγκτή εφαρμογών μας:

GET /app/post/:id controllers.Application.getPost(id: Long)

… Και μια νέα διαδρομή:

// dashboard.js angular.module('clientApp') .controller('DashboardCtrl', function ($scope, $log, $http, alertService, $location) { $scope.loadPosts = function() { $http.get('/app/userposts') .error(function(data, status) { if(status === 401) { $location.path('/login'); } else { alertService.add('danger', data.error.message); } }) .success(function(data) { $scope.posts = data; }); }; $scope.loadPosts(); });

Τώρα εάν μεταβείτε στο http: // localhost: 9000 / # / viewpost / 1, θα μπορείτε να φορτώσετε μια προβολή για μια συγκεκριμένη ανάρτηση. Στη συνέχεια, ας προσθέσουμε τη δυνατότητα προβολής των αναρτήσεων του χρήστη στον πίνακα ελέγχου:

My Posts

No posts yet. Add a post {{ post.subject }} | Comments {{ post.commentCount }}
// Post.java public static Result getUserPosts() { User user = getUser(); if(user == null) { return badRequest(Application.buildJsonResponse('error', 'No such user')); } return ok(Json.toJson(BlogPost.findBlogPostsByUser(user))); }

Προσθέστε επίσης μια νέα μέθοδο στο Post controller, ακολουθούμενη από μια διαδρομή που αντιστοιχεί σε αυτήν τη μέθοδο:

GET /app/userposts controllers.Post.getUserPosts // Post.java public static Result addComment() { Form commentForm = Form.form(CommentForm.class).bindFromRequest(); if (commentForm.hasErrors()) { return badRequest(commentForm.errorsAsJson()); } else { PostComment newComment = new PostComment(); BlogPost blogPost = BlogPost.findBlogPostById(commentForm.get().postId); blogPost.commentCount++; blogPost.save(); newComment.blogPost = blogPost; newComment.user = getUser(); newComment.content = commentForm.get().comment; newComment.save(); return ok(Application.buildJsonResponse('success', 'Comment added successfully')); } } public static class CommentForm { @Constraints.Required public Long postId; @Constraints.Required public String comment; }

Τώρα, όταν δημιουργείτε αναρτήσεις, θα εμφανίζονται στον πίνακα ελέγχου:

Εμφανίζονται νέες αναρτήσεις στον πίνακα ελέγχου

Σχολιασμός λειτουργικότητας

Για την εφαρμογή της λειτουργικότητας σχολιασμού, θα ξεκινήσουμε προσθέτοντας μια νέα μέθοδο στο Post controller:

POST /app/comment controllers.Post.addComment

Και όπως πάντα, πρέπει να καταχωρήσουμε μια νέα διαδρομή για αυτήν τη μέθοδο:

$scope.addComment = function() { var payload = { postId: $scope.postId, comment: $scope.comment }; $http.post('/app/comment', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'comment') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { $location.path('/login'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data) { alertService.add('success', data.success.message); $scope.comment = ''; $scope.viewPost(); }); };

Στην εφαρμογή μας AngularJS, προσθέτουμε τα ακόλουθα στο 'viewpost.js':

By: {{ comment.user.email }}
{{ comment.content }}

Login to comment

Add comment

Comment Add comment

Και τέλος προσθέστε τις ακόλουθες γραμμές στο 'viewpost.html':

|_+_|

Τώρα, εάν ανοίξετε οποιαδήποτε ανάρτηση, θα μπορείτε να προσθέσετε και να δείτε σχόλια.

Δείτε το στιγμιότυπο οθόνης σχολίων

Τι έπεται?

Σε αυτό το σεμινάριο, δημιουργήσαμε ένα blog AngularJS με εφαρμογή Play που χρησιμεύει ως REST API back-end. Παρόλο που η εφαρμογή δεν διαθέτει ισχυρή επικύρωση δεδομένων (ειδικά από την πλευρά του πελάτη) και ασφάλεια, αυτά τα θέματα ήταν εκτός του πεδίου αυτού του σεμιναρίου. Στόχος του ήταν να δείξει έναν από τους πολλούς πιθανούς τρόπους δημιουργίας μιας τέτοιας εφαρμογής. Για ευκολία, ο πηγαίος κώδικας αυτής της εφαρμογής έχει μεταφορτωθεί στο ένα αποθετήριο GitHub .

Εάν θεωρείτε ενδιαφέρον αυτόν τον συνδυασμό AngularJS και Play στην ανάπτυξη εφαρμογών ιστού, σας συνιστώ να εξετάσετε περαιτέρω τα ακόλουθα θέματα:

  • Τεκμηρίωση AngularJS
  • Αναπαραγωγή τεκμηρίωσης
  • Προτεινόμενη προσέγγιση ασφαλείας σε μια εφαρμογή JS μιας σελίδας με το Play ως back-end (περιέχει παράδειγμα)
  • Ασφαλές REST API χωρίς OAuth
  • Πρόσθετο ελέγχου ταυτότητας Ready Play (μπορεί να μην είναι πλήρως χρησιμοποιήσιμο για εφαρμογές JavaScript μιας σελίδας, αλλά μπορεί να χρησιμοποιηθεί ως καλό παράδειγμα)

Καλύτερα UX μέσω μικρο αλληλεπιδράσεων

Σχεδιασμός Ux

Καλύτερα UX μέσω μικρο αλληλεπιδράσεων
Μετρήσεις επιβίωσης: Πως να πιάσετε τον ρυθμό καύσης εκκίνησης

Μετρήσεις επιβίωσης: Πως να πιάσετε τον ρυθμό καύσης εκκίνησης

Διαδικασίες Χρηματοδότησης

Δημοφιλείς Αναρτήσεις
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
 
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Διευθυντής έργου και διαχείρισης προϊόντων
Διευθυντής έργου και διαχείρισης προϊόντων
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Δημοφιλείς Αναρτήσεις
  • διαφορά μεταξύ agile scrum και kanban
  • αυτό μπορεί να είναι το μόνο που χρειάζεται να ξέρω
  • Το javascript παίρνει την τρέχουσα ώρα σε χιλιοστά του δευτερολέπτου
  • πώς να λάβετε στοιχεία πιστωτικής κάρτας στο διαδίκτυο
  • ποια από τις παρακάτω εκφράσεις ισχύει για την ελαστικότητα της ζήτησης ως προς την τιμή;
  • χειρισμός εξαίρεσης στην ελατηριωτή μπότα
Κατηγορίες
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt